direct3d11 - 调整窗口大小时 Direct3D11 崩溃和/或故障
问题描述
我目前正在将渲染引擎从 OpenGL 移植到 Direct3D11
它在我的开发机器上运行良好,但现在已将其发布给一些 beta 测试人员,2 名测试人员报告了调整窗口大小的问题(一个崩溃,另一个 UI 冻结)。由于它可以在我的机器上运行,而且我在代码中看不到任何错误,我希望有更多 Direct3D 经验的人能够发现我做错了什么。
下面的代码是窗口调整大小时发生的相关代码(m_stencilview 等是指向 Com 对象的智能指针,D3D_CHECK 是用于检查结果的宏包装器)
m_stencilview.Clear();
m_stencil.Clear();
m_rendertargetview.Clear();
ctx.OMSetRenderTargets(0, 0, 0);
D3D_CHECK(m_swpchain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0));
ComPtr <ID3D11Texture2D> framebuffer;
D3D_CHECK(m_swpchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&framebuffer));
D3D_CHECK(engine.m_device->CreateRenderTargetView(framebuffer, 0, &m_rendertargetview));
解决方案
请注意,一个关键问题是:
ctx.OMSetRenderTargets(0, 0, 0);
这根本不会清除设置的渲染目标。您实际上需要传递一个 nullptr 数组来清除绑定:
ID3D11RenderTargetView* nullViews [] = { nullptr };
ctx.OMSetRenderTargets(1, nullViews, nullptr);
如果您使用的是“多个渲染目标”,那么您必须传递多个 nullptr,这就是数组简单易用的原因。
此外,您需要在运行时检查HRESULT
来自。ResizeBuffers
目前你只是把它当作它总是会成功,这是不正确的。
特别是,您需要同时检查ResizeBuffers
和Present
的返回值DXGI_ERROR_DEVICE_REMOVED
或DXGI_ERROR_DEVICE_RESET
.
运行时出现这种情况的最常见原因是在应用程序运行时在后台更新设备驱动程序。如果驱动程序崩溃并重新启动,或者 GPU 硬件挂起和超时,也会发生这种情况。
您有两个基本选择:
(a) 出现“您必须立即重新启动此应用程序”之类的消息框出现致命错误。这很蹩脚,但至少很清楚发生了什么。
(b) 更好的响应是基本上执行 Direct3D 9 应用程序对“丢失设备”所做的操作:销毁所有 Direct3D 对象并重新创建它们。
dxcap -forcetdr
您可以通过在 Direct3D 应用程序运行时从开发人员命令提示符(以管理员身份打开)运行,使用最新的 Visual Studio 版本测试此行为。
有关“丢失设备”处理的完整游戏循环,请参见GitHub 。
另请参阅超时检测和恢复 (TDR)
推荐阅读
- amazon-web-services - springboot应用程序在ec2上自动关闭
- pagination - 自定义部分页面
- string - 使用 write() 在堆栈上输出字符串
- javascript - 类型 string 不是颤振中 int 类型的子类型
- python-3.x - 在 Python 3.7 中使用 XPath 和 ElementTree 从 XML 文件中查找和提取值
- python - 来自 csv 数据的幂律(Python)
- java - Spring AOP 方面在多模块项目中不起作用
- karate - 如何将完整的行数据从 csv 迭代场景大纲传递到其他功能?
- android - 即使我做了flutter clean,flutter build apk也会创建旧版本的应用程序
- python - 删除列表中的重复项而不进行排序