什么是设备丢失

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函数会失败。设备丢失的处理可以大致分成如下三个步骤

  1. 使用TestCooperativeLevel函数检测当前设备状态,如果可以重置,则重置,并重建使用D3DPOOL_DEFAULT创建的资源及SwapChain。
  2. 如果设备仍然处于丢失状态,则等待一段时间
  3. 如果是其他状态,比如驱动内部错误,则告知用户(比如显示错误框)

处理设备丢失的代码如下

// 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中设备丢失的处理相关推荐

  1. Direct3D中设备丢失处理

    2011年3月11日 onedouble.net 原来总发现最小化侯再打开会失去键盘鼠标响应,最近搞明白,原来这就是TMD的设备丢失啊,丢失了该怎么办呢?先试着小心翼翼地问电脑,可以恢复吗(Reset ...

  2. DirectX 3D 设备丢失(lost device)的处理

    在创建时使用D3DPOOL_MANAGED标志的资源可以不需要重新载入,但D3DPOOL_DEFAULT加载的资源就需要先释放,后重建. 通常需要这样处理的有ID3DXFont和ID3DXSprite ...

  3. Direct3d 设备丢失 (device lost)

    1.什么时候设备丢失 一个Direct3D设备, 有两种状态: 操作状态或丢失状态. 操作状态: 是设备的正常状态, 设备按预期运行, 并且能present所有渲染效果 丢失状态: 所有渲染操作悄然失 ...

  4. D3D中2D图片的绘制

    想要在D3D中加载2D图片可以使用如下两种方法(我只想到这两种方法,如果有其他方法,请指教).第一种就是把图片以纹理方式加载,然后以此为纹理绘制一个四边形即可:第二种就是使用2D点精灵,不解释,你懂得 ...

  5. 电脑硬盘中文件丢失怎样才能找回?硬盘数据丢失能恢复吗

    电脑硬盘中文件丢失怎样才能找回?数据丢失的情况还很普遍,经常会有小伙伴会来咨询小编关于文件丢失如何恢复的问题.既然如此,小编就和大家分享一个数据恢复的好方法,让大家面临数据丢失时不用在手足无措. 首先 ...

  6. D3D中2D图片的绘制两种方法

    2014/09/19 (转载自:http://blog.csdn.net/rabbit729/article/details/6388703) 想要在D3D中加载2D图片可以使用如下两种方法(我只想到 ...

  7. D3D中的纹理贴图(1)

    D3D中的纹理贴图(1) 提示: 阅读本文需要一定的3D图形学和DirectX9基础,如果你发现阅读困难,请参阅 D3D中基本三角形面的绘制. 本文用到的坐标系统变换函数请参阅 DirectX 9的坐 ...

  8. D3D中基本立体面的绘制

    [转][收藏]2010-09-01 D3D中基本立体面的绘制 提示: 阅读本文需要一定的3D图形学和DirectX9基础,如果你发现阅读困难,请参阅D3D 中基本三角形面的绘制. 本文用到的坐标系统变 ...

  9. D3D中简单的截图方法 (转)

    [ZT]D3D中简单的截图方法 试了下,果然可以. 在渲染完所有东东后(Present之前) 获得BackBuffer表面 然后用D3DX的函数保存 void ScreenShot (char *fi ...

  10. vCenter Server Appliance 6.5 中重置丢失或忘记的 root 密码

    vCenter Server Appliance 6.5 中重置丢失或忘记的 root 密码 目前安装vCenter Server Appliance 6.5客户原来越多,给用户配置过程中,往往会忽略 ...

最新文章

  1. [NC14301]K-th Number
  2. 【西安交大】2020年最新深度学习目标检测方法综述
  3. html 超出部分被遮挡,div被iframe遮住的几种情况及解决方法
  4. JavaScript学习总结(7)——JavaScript基础知识汇总
  5. QTableWidget去掉默认行号
  6. SQL各种join用法
  7. 如何将Excel中,某个单元格中的下拉选删除掉
  8. MySQL ORDER BY IF() 条件排序
  9. [蓝桥杯][2017年第八届真题]发现环
  10. threejs相机和渲染器
  11. SQL Server Profiler使用方法
  12. 【原创】记一次HttpWebRequest中国移动查账单爬虫的攻克历程
  13. 实验5.4 编程实现两字符串的连接(使用string类定义字符串对象)
  14. 转]python 结巴分词(jieba)学习
  15. Kubernetes入门——k8s核心技术
  16. matlab图像画轮毂,轮毂设计及三维造型(全套图纸三维).doc
  17. 职工考勤表(vba工作日自动填充批量打印)---源码在最后
  18. HTML实现倒计时插件
  19. 一文搞定卷积神经网络——从原理到应用
  20. CC2530 IIC 4线驱动中景0.96寸OLED屏显示程序,从c51移植过来的

热门文章

  1. Ubuntu 安装网易云音乐
  2. 漫画分销系统服务器配置,漫画分销平台哪个好?月流水30万的老手来谈谈!
  3. Linux 部署turnserver
  4. 【SSM分布式架构电商项目-32】Dubbo入门
  5. 建立矩阵 reshape函数,pascal函数,magic函数,diag函数【Matlab】
  6. java毕业设计成品源码网站基于SpringBoot旅游信息管理系统
  7. 野火stm32资源下载(视频,手册等)
  8. cmd整人小程序(e~~,不要乱用)
  9. 富文本Ueditor
  10. Chrome插件:中国天气预报与万年历