首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调整窗口大小时Direct3D11崩溃和/或故障

调整窗口大小时Direct3D11崩溃和/或故障
EN

Stack Overflow用户
提问于 2021-06-08 08:27:48
回答 1查看 47关注 0票数 0

我目前正在将一个渲染引擎从OpenGL移植到Direct3D11

它在我的开发机器上运行得很好,但现在已经将它发布给了几个beta测试人员,两个测试人员报告了一个调整窗口大小的问题(一个崩溃,另一个UI冻结)。因为它在我的机器上工作,并且我在代码中看不到任何错误,我希望有更多Direct3D经验的人能够发现我做错了什么。

下面的代码是当窗口调整大小时发生的相关代码( m_stencilview等是指向Com对象的智能指针,D3D_CHECK是用于检查结果的宏包装)

代码语言:javascript
复制
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));
EN

回答 1

Stack Overflow用户

发布于 2021-06-08 11:08:10

请注意,一个关键问题是:

代码语言:javascript
复制
ctx.OMSetRenderTargets(0, 0, 0);

这根本不会清除设置的渲染目标。您需要实际传递一个nullptr数组来让它清除绑定:

代码语言:javascript
复制
ID3D11RenderTargetView* nullViews [] = { nullptr };
ctx.OMSetRenderTargets(1, nullViews, nullptr);

如果你使用的是“多个渲染目标”,那么你必须传递多个nullptr,这就是为什么数组在这里简单易用的原因。

此外,您需要在运行时检查来自ResizeBuffersHRESULT。目前,你只是认为它总是会成功,但事实并非如此。

特别是,您需要检查ResizeBuffersPresent的返回值DXGI_ERROR_DEVICE_REMOVEDDXGI_ERROR_DEVICE_RESET

在运行时出现这种情况的最常见原因是在应用程序运行时在后台更新设备驱动程序。如果驱动程序崩溃并重新启动,或者如果GPU硬件挂起并超时,也会发生这种情况。

您有两个基本选择:

(a)消息框中出现致命错误,如“您必须立即重新启动此应用程序”。这很差劲,但至少发生了什么事情是很清楚的。

(b)更好的应对方法是基本上像Direct3D 9应用程序对“丢失的设备”所做的那样:销毁所有Direct3D对象并重新创建它们。

通过在Direct3D应用程序运行时从开发人员命令提示符(以管理员身份打开)运行dxcap -forcetdr,可以使用最新的Visual Studio发行版

测试此行为。

请参阅GitHub了解完整的游戏循环,以及对“丢失设备”的处理。

另请参阅Timeout detection and recovery (TDR)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67880045

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档