D3D中设备丢失的处理
什么是设备丢失
D3D中设备(Device)有两种状态,一种是可操作状态,也就是正常状态,另一种是丢失状态(Lost),处于丢失状态的设备是不能进行渲染操作的。简单的说,设备丢失是只应用程序(Device)与显卡失去了联系,因此无法使用显存。这里的Device不是只硬件,而是我们在程序中创建的Device对象,可以理解为上下文环境。
什么情况会导致设备丢失
当某些事件发生时,设备会由正常状态转换到丢失状态。这些事件包括
- 程序在全屏状态下失去键盘焦点(全屏时按下Alt+Tab或Win+D键或Win+L键)
- 其他程序进入全屏状态
- 电源管理事件,比如屏保等
设备丢失的现象
- 渲染窗口内模型丢失
- 渲染窗口背景色变黑或者干脆没有背景色
- 程序失去响应或者Crash
如何检测设备丢失
设备丢失以后,大多数渲染操作都只是silent failure,所以仍然会返回正确代码,但是Present函数会返回D3DERR_DEVICELOST,所以可以检测该函数的返回值,如果该函数失败,那么就重置设备。当然失败可能还有其他原因,不仅仅是设备丢失而已,这些情况我们都在ResetDevie函数里面一并处理。
// Present the back buffer contents to the display HRESULT hr = g_pd3dDevice->Present(NULL, NULL, NULL, NULL);// Render failed, try to reset device if(FAILED(hr)) {ResetDevice(d3dpp) ; }
如何处理设备丢失
设备丢失以后,应该进行重置(Reset),可以使用Reset函数来重置设备,Reset函数是设备丢失以后唯一起作用的函数,也是唯一能将设备从丢失状态恢复到正常状态的函数。由于设备丢失后,设备与显卡就失去了联系,所以一切与显卡有关的资源也都无法再通过设备访问了,那么这些资源必须释放并重新创建,一般来说,以D3DPOOL_DEFAULT为参数创建的资源,都是在显卡中分配的内存,所以,在重置设备之前要保证所有D3DPOOL_DEFAULT类型的资源都必须释放掉,而且如果程序中使用了额外的SwapChain,那么也要重新创建之,否则Reset函数会失败。设备丢失的处理可以大致分成如下三个步骤
- 使用TestCooperativeLevel函数检测当前设备状态,如果可以重置,则重置,并重建使用D3DPOOL_DEFAULT创建的资源及SwapChain。
- 如果设备仍然处于丢失状态,则等待一段时间
- 如果是其他状态,比如驱动内部错误,则告知用户(比如显示错误框)
处理设备丢失的代码如下
// Reset device HRESULT ResetDevice(D3DPRESENT_PARAMETERS d3dpp) {// Check device stateHRESULT hr = g_pd3dDevice->TestCooperativeLevel() ;// Device can be reset nowif (SUCCEEDED(hr) || hr == D3DERR_DEVICENOTRESET){// Release resource allocated as D3DPOOL_DEFAULT// Reset deviceHRESULT hr = g_pd3dDevice->Reset(&d3dpp) ;if (SUCCEEDED(hr)){ResizeD3DScene(d3dpp.BackBufferWidth, d3dpp.BackBufferHeight) ;}else// Reset device failed, show error box {const WCHAR* errorString = DXGetErrorString(hr) ;DXTRACE_ERR_MSGBOX(errorString, hr) ;}}// Device is still in lost state, waitelseif (hr == D3DERR_DEVICELOST){Sleep(25) ;}else// Other error, Show error box {const WCHAR* errorString = DXGetErrorString(hr) ;DXTRACE_ERR_MSGBOX(errorString, hr) ;}return hr ; }
需要注意的是,在重置Device的过程中(即调用Reset函数时),仍然会发生错误,这时我们简单的输出一个错误框告知用户。由于重置设备后,窗口的大小可能改变,所以我们要调用ResizeD3DScene来调整投影窗口的纵横比,该函数如下
// Reset the scene by rebuild the viewing frustum void ResizeD3DScene(int width, int height) {if (height ==0 ) // Prevent A Divide By Zero Byheight =1; // Making Height Equal One// Compute aspect ratiofloat fAspectRatio = width / (FLOAT)height;// Setup Projection matrixg_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 1.0f, 1000.0f );g_Camera.SetWindow( width, height ); }
验证一个3D程序是否正确处理了设备丢失
如果不能正确的处理设备丢失,则D3D程序经常会产生莫名其妙的现象 ,我们可以使用如下方法验证
1 在程序处于渲染状态时(窗口或者全屏态皆可)按下锁屏键(Win+L),然后返回程序,看看渲染内容是否丢失。
2 在程序处于全屏状态时,按下Win+D回到桌面,或者按下Atl+Tab切换到其他程序,然后在再到渲染程序,看看渲染内容是否丢失。
3 还有其他的,大家发挥想象力。。。
Vista及后续系统的情况
前面讨论的情况都是针对XP系统而言,如果你使用的是Window Vista及更高版本,那么情况则有所不同了,Vista使用的是WDDM driver(Windows Device Driver Model),而XP使用的是XPDM (XP Driver Model),前面说了,设备丢失的情况很多,并没有一个完整的列表来描述这些情况,但是在Vista系统上则不然,设备丢失只有两种情况,一是硬件hanging,另一种是driver stopped。
- 如果是硬件挂起,那么可以通过ResetEx来重置设备,但是纹理内存会丢失。
- 如果是驱动停止了,那么所有IDirect9Ex 对象必须重新创建以便继续渲染。
在窗口模式下,如果渲染区域被其他窗口遮挡,或者全屏模式下,程序最小化,PresentEx函数都会返回S_D3DPRESENTATIONOCCLUDED,全屏程序在收到WM_ACTIVATEAPP消息时会继续渲染。
在以前版本的DX中,当应用程序经历模式改变时,唯一的恢复办法就是reset device并重新创建所有显存资源及swap chain,但是在Vista上的DirectX,在模式改变后调用reset函数,纹理内存不会丢失,纹理渲染状态信息也不会丢失,这些资源都不必重新创建了。
转载于:https://www.cnblogs.com/graphics/archive/2010/08/21/1805548.html
D3D中设备丢失的处理相关推荐
- Direct3D中设备丢失处理
2011年3月11日 onedouble.net 原来总发现最小化侯再打开会失去键盘鼠标响应,最近搞明白,原来这就是TMD的设备丢失啊,丢失了该怎么办呢?先试着小心翼翼地问电脑,可以恢复吗(Reset ...
- DirectX 3D 设备丢失(lost device)的处理
在创建时使用D3DPOOL_MANAGED标志的资源可以不需要重新载入,但D3DPOOL_DEFAULT加载的资源就需要先释放,后重建. 通常需要这样处理的有ID3DXFont和ID3DXSprite ...
- Direct3d 设备丢失 (device lost)
1.什么时候设备丢失 一个Direct3D设备, 有两种状态: 操作状态或丢失状态. 操作状态: 是设备的正常状态, 设备按预期运行, 并且能present所有渲染效果 丢失状态: 所有渲染操作悄然失 ...
- D3D中2D图片的绘制
想要在D3D中加载2D图片可以使用如下两种方法(我只想到这两种方法,如果有其他方法,请指教).第一种就是把图片以纹理方式加载,然后以此为纹理绘制一个四边形即可:第二种就是使用2D点精灵,不解释,你懂得 ...
- 电脑硬盘中文件丢失怎样才能找回?硬盘数据丢失能恢复吗
电脑硬盘中文件丢失怎样才能找回?数据丢失的情况还很普遍,经常会有小伙伴会来咨询小编关于文件丢失如何恢复的问题.既然如此,小编就和大家分享一个数据恢复的好方法,让大家面临数据丢失时不用在手足无措. 首先 ...
- D3D中2D图片的绘制两种方法
2014/09/19 (转载自:http://blog.csdn.net/rabbit729/article/details/6388703) 想要在D3D中加载2D图片可以使用如下两种方法(我只想到 ...
- D3D中的纹理贴图(1)
D3D中的纹理贴图(1) 提示: 阅读本文需要一定的3D图形学和DirectX9基础,如果你发现阅读困难,请参阅 D3D中基本三角形面的绘制. 本文用到的坐标系统变换函数请参阅 DirectX 9的坐 ...
- D3D中基本立体面的绘制
[转][收藏]2010-09-01 D3D中基本立体面的绘制 提示: 阅读本文需要一定的3D图形学和DirectX9基础,如果你发现阅读困难,请参阅D3D 中基本三角形面的绘制. 本文用到的坐标系统变 ...
- D3D中简单的截图方法 (转)
[ZT]D3D中简单的截图方法 试了下,果然可以. 在渲染完所有东东后(Present之前) 获得BackBuffer表面 然后用D3DX的函数保存 void ScreenShot (char *fi ...
- vCenter Server Appliance 6.5 中重置丢失或忘记的 root 密码
vCenter Server Appliance 6.5 中重置丢失或忘记的 root 密码 目前安装vCenter Server Appliance 6.5客户原来越多,给用户配置过程中,往往会忽略 ...
最新文章
- [NC14301]K-th Number
- 【西安交大】2020年最新深度学习目标检测方法综述
- html 超出部分被遮挡,div被iframe遮住的几种情况及解决方法
- JavaScript学习总结(7)——JavaScript基础知识汇总
- QTableWidget去掉默认行号
- SQL各种join用法
- 如何将Excel中,某个单元格中的下拉选删除掉
- MySQL ORDER BY IF() 条件排序
- [蓝桥杯][2017年第八届真题]发现环
- threejs相机和渲染器
- SQL Server Profiler使用方法
- 【原创】记一次HttpWebRequest中国移动查账单爬虫的攻克历程
- 实验5.4 编程实现两字符串的连接(使用string类定义字符串对象)
- 转]python 结巴分词(jieba)学习
- Kubernetes入门——k8s核心技术
- matlab图像画轮毂,轮毂设计及三维造型(全套图纸三维).doc
- 职工考勤表(vba工作日自动填充批量打印)---源码在最后
- HTML实现倒计时插件
- 一文搞定卷积神经网络——从原理到应用
- CC2530 IIC 4线驱动中景0.96寸OLED屏显示程序,从c51移植过来的