- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试做一个 UWP 游戏,我遇到了一个问题,我的游戏在 Release模式下比在 Debug模式下慢得多。
我的游戏将绘制一个 3D View (地牢大师风格),并且将有一个在 3D View 上绘制的 UI 部分。因为 3D View 可以减慢到少量每秒帧数 (FPS),所以我决定让我的游戏始终以 60 FPS 运行 UI 部分。
在一些伪代码中,主游戏循环看起来像这样:
Gameloop start
Update game datas
copy actual finished 3D view from buffer to screen
draw UI part
3D view loop start
If no more time to draw more textures on the 3D view exit 3D view loop
Draw one texture to 3D view buffer
3D view loop end --> 3D view loop start
Gameloop end --> Gameloop start
这里是实际的更新和渲染函数:
void Dungeons_of_NargothMain::Update()
{
m_ritonTimer.startTimer(static_cast<int>(E_RITON_TIMER::UI));
m_ritonTimer.frameCountPlusOne((int)E_RITON_TIMER::UI_FRAME_COUNT);
m_ritonTimer.manageFramesPerSecond((int)E_RITON_TIMER::UI_FRAME_COUNT);
m_ritonTimer.manageFramesPerSecond((int)E_RITON_TIMER::LABY_FRAME_COUNT);
if (m_sceneRenderer->m_numberTotalOfTexturesToDraw == 0 ||
m_sceneRenderer->m_numberTotalOfTexturesToDraw <= m_sceneRenderer->m_numberOfTexturesDrawn)
{
m_sceneRenderer->m_numberTotalOfTexturesToDraw = 150000;
m_sceneRenderer->m_numberOfTexturesDrawn = 0;
}
}
// RENDER
bool Dungeons_of_NargothMain::Render()
{
//********************************//
// Render UI part here //
//********************************//
//**********************************//
// Render 3D view to 960X540 screen //
//**********************************//
m_sceneRenderer->setRenderTargetTo960X540Screen(); // 3D view buffer screen
bool screen960GotFullDrawn = false;
bool stillenoughTimeLeft = true;
while (stillenoughTimeLeft && (!screen960GotFullDrawn))
{
stillenoughTimeLeft = m_ritonTimer.enoughTimeForOneMoreTexture((int)E_RITON_TIMER::UI);
screen960GotFullDrawn = m_sceneRenderer->renderNextTextureTo960X540Screen();
}
if (screen960GotFullDrawn)
m_ritonTimer.frameCountPlusOne((int)E_RITON_TIMER::LABY_FRAME_COUNT);
return true;
}
我删除了不重要的部分。
这里是定时器部分(RitonTimer):
#pragma once
#include "pch.h"
#include <wrl.h>
#include "RitonTimer.h"
Dungeons_of_Nargoth::RitonTimer::RitonTimer()
{
initTimer();
if (!QueryPerformanceCounter(&m_qpcGameStartTime))
{
throw ref new Platform::FailureException();
}
}
void Dungeons_of_Nargoth::RitonTimer::startTimer(int timerIndex)
{
if (!QueryPerformanceCounter(&m_qpcNowTime))
{
throw ref new Platform::FailureException();
}
m_qpcStartTime[timerIndex] = m_qpcNowTime.QuadPart;
m_framesPerSecond[timerIndex] = 0;
m_frameCount[timerIndex] = 0;
}
void Dungeons_of_Nargoth::RitonTimer::resetTimer(int timerIndex)
{
if (!QueryPerformanceCounter(&m_qpcNowTime))
{
throw ref new Platform::FailureException();
}
m_qpcStartTime[timerIndex] = m_qpcNowTime.QuadPart;
m_framesPerSecond[timerIndex] = m_frameCount[timerIndex];
m_frameCount[timerIndex] = 0;
}
void Dungeons_of_Nargoth::RitonTimer::frameCountPlusOne(int timerIndex)
{
m_frameCount[timerIndex]++;
}
void Dungeons_of_Nargoth::RitonTimer::manageFramesPerSecond(int timerIndex)
{
if (!QueryPerformanceCounter(&m_qpcNowTime))
{
throw ref new Platform::FailureException();
}
m_qpcDeltaTime = m_qpcNowTime.QuadPart - m_qpcStartTime[timerIndex];
if (m_qpcDeltaTime >= m_qpcFrequency.QuadPart)
{
m_framesPerSecond[timerIndex] = m_frameCount[timerIndex];
m_frameCount[timerIndex] = 0;
m_qpcStartTime[timerIndex] += m_qpcFrequency.QuadPart;
if ((m_qpcStartTime[timerIndex] + m_qpcFrequency.QuadPart) < m_qpcNowTime.QuadPart)
m_qpcStartTime[timerIndex] = m_qpcNowTime.QuadPart - m_qpcFrequency.QuadPart;
}
}
void Dungeons_of_Nargoth::RitonTimer::initTimer()
{
if (!QueryPerformanceFrequency(&m_qpcFrequency))
{
throw ref new Platform::FailureException();
}
m_qpcOneFrameTime = m_qpcFrequency.QuadPart / 60;
m_qpc5PercentOfOneFrameTime = m_qpcOneFrameTime / 20;
m_qpc10PercentOfOneFrameTime = m_qpcOneFrameTime / 10;
m_qpc95PercentOfOneFrameTime = m_qpcOneFrameTime - m_qpc5PercentOfOneFrameTime;
m_qpc90PercentOfOneFrameTime = m_qpcOneFrameTime - m_qpc10PercentOfOneFrameTime;
m_qpc80PercentOfOneFrameTime = m_qpcOneFrameTime - m_qpc10PercentOfOneFrameTime - m_qpc10PercentOfOneFrameTime;
m_qpc70PercentOfOneFrameTime = m_qpcOneFrameTime - m_qpc10PercentOfOneFrameTime - m_qpc10PercentOfOneFrameTime - m_qpc10PercentOfOneFrameTime;
m_qpc60PercentOfOneFrameTime = m_qpc70PercentOfOneFrameTime - m_qpc10PercentOfOneFrameTime;
m_qpc50PercentOfOneFrameTime = m_qpc60PercentOfOneFrameTime - m_qpc10PercentOfOneFrameTime;
m_qpc45PercentOfOneFrameTime = m_qpc50PercentOfOneFrameTime - m_qpc5PercentOfOneFrameTime;
}
bool Dungeons_of_Nargoth::RitonTimer::enoughTimeForOneMoreTexture(int timerIndex)
{
while (!QueryPerformanceCounter(&m_qpcNowTime));
m_qpcDeltaTime = m_qpcNowTime.QuadPart - m_qpcStartTime[timerIndex];
if (m_qpcDeltaTime < m_qpc45PercentOfOneFrameTime)
return true;
else
return false;
}
在 Debug模式下,游戏的 UI 以 60 FPS 运行,而 3D View 在我的 PC 上大约为 1 FPS。但即使在那里,我也不确定为什么我必须在一场比赛时间的 45% 时停止我的纹理绘制并调用当前,以获得 60 FPS,如果我等待更长时间我只能得到 30 FPS。 (此值在 RitonTimer 的“enoughTimeForOneMoreTexture()”中设置。
在 Release模式下,它急剧下降,UI 部分大约为 10 FPS,3D 部分为 1 FPS。在过去的两天里,我试图找出原因,但没有找到。
我还有一个小问题:如何告诉 visual studio 我的游戏实际上是游戏而不是应用程序?或者当我将我的游戏发送到他们的商店时,微软会进行“切换”吗?
这里我已经把我的游戏放在我的OneDrive上了,大家可以下载源文件并尝试编译它,看看你是否得到和我一样的结果:
OneDrive 链接:https://1drv.ms/f/s!Aj7wxGmZTdftgZAZT5YAbLDxbtMNVg
在 x64 调试或 x64 Release模式下编译。
更新:
我想我找到了为什么我的游戏在 Release模式下变慢的原因。CPU 可能不会等待绘图指令完成,而只是将其添加到一个列表中,该列表将在单独的任务中以自己的速度转发给 GPU(或者 GPU 自己缓存)。那可以解释一切。
我的计划是先绘制 UI,然后从 3D View 中绘制尽可能多的纹理,直到 1/60 秒帧时间的 95% 过去,然后将其呈现给交换链。 UI 始终为 60 FPS,3D View 将与系统允许的速度一样快(如果可以在 95% 的帧时间内全部绘制,则也为 60FPS)。这没有用,因为它可能在一个帧时间内缓存了我的 3D View 的所有指令(我正在测试 3D View 的 150000 BIG 纹理绘制指令),所以当然 UI 和 3D View 一样慢结束,或接近。
这也是为什么即使在 Debug模式下,当我等待 95% 的帧时间时我也没有获得 60FPS,我不得不等待 45% 的帧时间才能获得我想要的 UI 60FPS。
我在 Release模式下以较低的值对其进行了测试以验证该理论,事实上,当我仅在帧时间的 15% 处停止绘图时,我的 UI 也获得了 60 FPS。
我认为它只在 DirectX12 中是这样工作的。
最佳答案
“我如何告诉 visual studio 我的游戏实际上是游戏而不是应用程序”- 没有区别,游戏就是应用程序。
我让您的代码在 Debug模式下以 300-400 FPS 的速度运行。
首先,我注释掉了检查您是否有时间渲染另一个纹理的代码。不要那样做。玩家看到的一切都应该在一个帧内呈现。如果您的帧花费的时间超过 16 毫秒(目标为 60fps),请寻找昂贵的操作或重复进行的调用,这可能会增加一些意外的成本。当每帧或每次调整大小时只需要执行一次时,寻找可能重复执行某项操作的代码。等等
所以问题是您渲染了非常大的纹理,而且数量很多。您希望避免 overdraw (在已经渲染过像素的地方渲染像素)。你可以有一点 overdraw ,这有时比迂腐更可取。但是您一遍又一遍地绘制 1000x2000 纹理。所以你绝对是在杀死像素着色器。它只是无法渲染那么多像素。我没有费心去查看试图根据剩余帧时间来控制纹理渲染的代码。对于您正在尝试做的事情,这没有帮助。
在你的渲染方法中注释掉 while 和 if/else 部分并使用它来绘制你的纹理数组..
// set sprite dimensions
int w = 64, h = 64;
for (int y = 0; y < 16; y++)
{
for (int x = 0; x < 16; x++)
{
m_sceneRenderer->renderNextTextureTo960X540Screen(x*64, y*64, w, h);
}
}
并在 RenderNextTextureToScreen(int x, int y, int w, int h) ..
m_squareBuffer.sizeX = w; // 1000;
m_squareBuffer.sizeY = h; // 2000;
m_squareBuffer.posX = x; // (float)(rand() % 1920);
m_squareBuffer.posY = y; // (float)(rand() % 1080);
看看这段代码如何渲染更小的纹理,纹理是 64x64 并且没有过度绘制。
请注意 GPU 并非全都强大,如果您正确使用它,它可以做很多事情,但如果您只是对它进行疯狂的操作,您可以让它停止运转,就像 CPU 一样.因此,尝试渲染“看起来正常”的事物,您可以想象在游戏中。您会及时了解什么是明智的,什么不是。
对于在 Release模式下运行速度较慢的代码,最可能的解释是您的计时和渲染限制器代码已损坏。它无法正常工作,因为 3d View 以 1fps 的速度运行,所以谁知道它的行为是什么。通过我所做的更改,该程序似乎按预期在 Release模式下运行得更快。您的时钟代码现在在 Release模式下为我显示 600-1600fps。
关于c++ - 为什么我的 UWP 游戏在发布时比在 Debug模式下慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56638488/
对此感到疯狂,真的缺少一些东西。 我有webpack 4.6.0,webpack-cli ^ 2.1.2,所以是最新的。 在文档(https://webpack.js.org/concepts/mod
object Host "os.google.com" { import "windows" address = "linux.google.com" groups = ["linux"] } obj
每当我安装我的应用程序时,我都可以将数据库从 Assets 文件夹复制到 /data/data/packagename/databases/ .到此为止,应用程序工作得很好。 但 10 或 15 秒后
我在 cc 模式缓冲区中使用 hideshow.el 来折叠我不查看的文件部分。 如果能够在 XML 文档中做到这一点就好了。我使用 emacs 22.2.1 和内置的 sgml-mode 进行 xm
已结束。此问题不符合 Stack Overflow guidelines .它目前不接受答案。 我们不允许提出有关书籍、工具、软件库等方面的建议的问题。您可以编辑问题,以便用事实和引用来回答它。 关闭
根据java: public Scanner useDelimiter(String pattern) Sets this scanner's delimiting pattern to a patt
我读过一些关于 PRG 模式以及它如何防止用户重新提交表单的文章。比如this post有一张不错的图: 我能理解为什么在收到 2xx 后用户刷新页面时不会发生表单提交。但我仍然想知道: (1) 如果
看看下面的图片,您可能会清楚地看到这一点。 那么如何在带有其他一些 View 的简单屏幕中实现没有任何弹出/对话框/模式的微调器日期选择器? 我在整个网络上进行了谷歌搜索,但没有找到与之相关的任何合适
我不知道该怎么做,我一直遇到问题。 以下是代码: rows = int(input()) for i in range(1,rows): for j in range(1,i+1):
我想为重写创建一个正则表达式。 将所有请求重写为 index.php(不需要匹配),它不是以/api 开头,或者不是以('.html',或'.js'或'.css'或'.png'结束) 我的例子还是这样
MVC模式代表 Model-View-Controller(模型-视图-控制器) 模式 MVC模式用于应用程序的分层开发 Model(模型) - 模型代表一个存取数据的对象或 JAVA PO
我想为组织模式创建一个 RDF 模式世界。您可能知道,组织模式文档基于层次结构大纲,其中标题是主要的分组实体。 * March auxiliary :PROPERTIES: :HLEVEL: 1 :E
我正在编写一个可以从文件中读取 JSON 数据的软件。该文件包含“person”——一个值为对象数组的对象。我打算使用 JSON 模式验证库来验证内容,而不是自己编写代码。符合代表以下数据的 JSON
假设我有 4 张 table 人 公司 团体 和 账单 现在bills/persons和bills/companys和bills/groups之间是多对多的关系。 我看到了 4 种可能的 sql 模式
假设您有这样的文档: doc1: id:1 text: ... references: Journal1, 2013, pag 123 references: Journal2, 2014,
我有这个架构。它检查评论,目前工作正常。 var schema = { id: '', type: 'object', additionalProperties: false, pro
这可能很简单,但有人可以解释为什么以下模式匹配不明智吗?它说其他规则,例如1, 0, _ 永远不会匹配。 let matchTest(n : int) = let ran = new Rand
我有以下选择序列作为 XML 模式的一部分。理想情况下,我想要一个序列: 来自 my:namespace 的元素必须严格解析。 来自任何其他命名空间的元素,不包括 ##targetNamespace和
我希望编写一个 json 模式来涵盖这个(简化的)示例 { "errorMessage": "", "nbRunningQueries": 0, "isError": Fals
首先,我是 f# 的新手,所以也许答案很明显,但我没有看到。所以我有一些带有 id 和值的元组。我知道我正在寻找的 id,我想从我传入的三个元组中选择正确的元组。我打算用两个 match 语句来做到这
我是一名优秀的程序员,十分优秀!