(转)Direct3d 设备丢失 (device lost)
1.什么时候设备丢失
一个Direct3D设备, 有两种状态: 操作状态或丢失状态。
操作状态: 是设备的正常状态, 设备按预期运行, 并且能present所有渲染效果
丢失状态: 所有渲染操作悄然失败, IDirect3DDevice9::present返回错误码D3DERR_DEVICELOST
查帮助Lost Devices (Direct3D 9)看更详细介绍,用最民工的语言简略说说:什么时候设备会丢失?
(1)全屏模式下当前Direct3D窗口丢失焦点时
(2)有多个Direct3D窗口,其中一个进入全屏则其它设备丢失(多显卡时情况则不同,每个显卡设备只有一个能全屏)
系统休眠或者锁定(Win+L)
(3)IDirect3DDevice9::Reset调用失败时, 设备也会被设置为丢失状态
(4)重新设置Direct3D device 参数时
2.如何发现设备丢失
IDirect3DDevice9::present返回错误码D3DERR_DEVICELOST 或 D3DERR_DRIVERINTERNALERROR(这种情况下基本上要exit了)
IDirect3DDevice9::TestCooperativeLevel返回错误码D3DERR_DEVICELOST或D3DERR_DRIVERINTERNALERROR(DX10整合到present中了)
不论通过任何方式发生了设备丢失,所有的操作几乎都会失效,只有Release()可以用——其实D3D会保证有部分操作可以成功,但
是也仅仅是“可以”成功而不是“一定”成功,所以你还不如认定丢失的时候全都会失败比较好——以及
IDirect3DDevice9::TestCooperativeLevel。因此在设备丢失之后,你应该停止整个游戏循环,而通过反复调用
IDirect3DDevice9::TestCooperativeLevel判断设备是否可用。
『IDirect3DDevice9::TestCooperativeLevel』
这个方法检测当前的设备状态。返回值有四种:D3D_OK一切正常,D3DERR_DEVICELOST设备丢失,D3DERR_DEVICENOTRESET设备
可以Reset。另外还有D3D9新增的D3DERR_DRIVERINTERNALERROR,遇到这个你就完蛋了,基本不可能恢复了,终止程序吧。
按照顺序来讲,如果游戏在正常运行,D3D_OK会返回;如果发生了设备丢失并且在这个时候不能恢复,比如全屏幕模式的时候
用户切换到了Windows桌面,就会返回D3DERR_DEVICELOST;如果用户又切换回了游戏,设备可以恢复了(还没恢复呢!只是“可
以”恢复而已),就会返回D3DERR_DEVICENOTRESET。
另外,IDirect3DDevice9::Present也会返回类似的值,不过你最好别指望这个,老老实实的用TestCooperativeLevel。因为
Present在设备可以恢复的时候还是返回D3DERR_DEVICELOST(外一句:D3D10的时候TestCooperativeLevel就会完全整合到Present
里面了,可喜可贺可喜可贺)
3.发现设备丢失后
1.查询设备状态, 看是否可以将之恢复到操作状态. 如果不行, 则必须要等到设备可以被恢复为止.
2.释放所有在D3DPOOL_DEFAULT中分配的资源, 包括用IDirect3DDevice9::CreateRenderTarget和
IDirect3DDevice9::CreateDepthStencilSurface方法创建的资源. (不进行这一步, 下一步的Reset操作会失败)
3.调用IDirect3DDevice::Reset进行恢复. Reset方法是当设备丢失时, 唯一有效的方法, 并且是应用程序可用来把设备从丢失状态
恢复到操作状态的唯一方法.
4.重建在步骤2中释放的资源, 同时还需要重新设置state等
4.管理资源
1.资源管理是将资源从系统内存提升到设备可访问存储器及从设备可访问存储器中抛弃的过程
2.D3DPOOL_MANAGED标志指定一个由系统管理的资源。由系统管理的资源在设备的丢失状态和操作状态间的转换中持续存在。通过调
用IDirect3DDevice9::Reset设备可以被重置,并且这类资源可以继续正常运作而无需重新载入图片。但是,如果设备必须被销毁和
重建,那么所有用D3DPOOL_MANAGED创建的资源也必须被重建
3.D3DPOOL_DEFAULT标志指定把资源放在默认的池中。在默认的池中的资源在设备从丢失状态到操作状态的转换过程中不持续存在,
这些资源必须在调用Reset之前释放,然后重建
4.不是所有的类型和用途都支持资源管理。例如,用D3DUSAGE_RENDERTARGET标志创建的对象不支持资源管理。另外,不建议对需要
频繁改变其内容的对象使用资源管理。例如,在某些硬件上对一个每帧都需改变的顶点缓存进行自动管理会严重降低性能。但是,
对纹理资源来说这不是一个问题
5.处理设备丢失
下面的伪代码:
switch (IDirect3DDevice9::TestCooperativeLevel()){
case D3D_OK:
GameLoop();
break;
case D3DERR_DEVICELOST:
break;
case D3DERR_DEVICENOTRESET
OnLostDevice();
IDirect3DDevice9::Reset();
OnResetDevice();
break;
default:
QuitGame();
break;
}
GameLoop()就是你的游戏运行的过程了。把这个switch写在我们游戏框架的GameMain()部分,具体的位置可以看任何一话附带
的源代码。
好像我一直没有讲IDirect3DDevice9::Reset的参数啊?因为只有一个参数,就是指向D3DPRESENT_PARAMS的指针。把你第
一次创建设备时使用的D3DPRESENT_PARAMS结构保存起来,供Reset来用。
OnLostDevice()就是Release掉所有D3DPOOL_DEFAULT的资源,OnResetDevice()就是Create*()恢复啦!你可能注意到
ID3DXFont、ID3DXSprite等等都有同名的方法,就是在这个时候调用的。如果你没有这么做,也就是说还保留着任何
D3DPOOL_DEFAULT的资源的话,IDirect3DDevice9::Reset就一定会失败。
另外在OnResetDevice里面你还要重新进行SetRenderState、SetSamplerState等等,Reset之后这些东西也丢失了。实际上
Reset和重新创建一次设备类似,所不同的是重新创建设备的话你需要连D3DPOOL_MANAGED的资源也Release掉。这个话题就不
讨论了。
从代码可以看出来,D3DERR_DEVICELOST时程序什么都没做,只是在傻等。我认为这是一个好习惯,因为实在不能保证在
D3DERR_DEVICELOST时除了Release还能干什么,与其这样还不如等设备能用了再说。
实在懒得管资源的话,全部D3DPOOL_MANAGED好了。至于渲染对象?自己想办法。
6.人工制造“设备丢失
“干嘛还要制造设备丢失啊?”如果更改游戏分辨率、色深、切换全屏幕及窗口状态,进行这样的操作也要通过Reset,同样
的,Reset之前也要释放掉所有D3DPOOL_DEFAULT资源(其实严格来说,还有更多的资源也要释放,不过在2D下基本不会创建这类资
源,你就不用管了)并且调用ID3DXSprite::OnLostDevice之类的方法。这就是人工制造“设备丢失”了。实际上在这个过程设备并
没有真正的丢失,只是会有一段时间处于不可用的状态,此时Reset尚未返回,整个D3D设备就好像死了一样。举个例子,你切换桌
面分辨率,会有那么一段时间显示器上什么都不显示,然后很快就正常了。和这个现象是同一个原因。Reset成功后记得恢复资源。
你可能注意到这里的Reset和上面的Reset不是一回事。的确是这样,这里是为了重设状态而不是恢复设备。因此更改分辨率、色
深的Reset需要写到switch外面,也就是别和它搅和的意思-_-bb。而且你只需要OnLostDevice -> Reset -> OnResetDevice。记
住:正确的调用Reset不会造成设备丢失,这个概念别弄混了。
转自:http://blog.csdn.net/kuangfengwu/article/details/7674074
(转)Direct3d 设备丢失 (device lost)的更多相关文章
- Direct3d 设备丢失 (device lost) (转载)
转:http://blog.csdn.net/kuangfengwu/article/details/7674074 1.什么时候设备丢失 一个Direct3D设备, 有两种状态: 操作状态或丢失状态 ...
- (转)directx中丢失的设备(lost device)
directx中丢失的设备(lost device) 丢失的设备 一个Microsoft? Direct3D?可以处于操作状态或丢失状态.操作状态是设备的正常状态,设备按预期运行并present所 ...
- 项目中遇到的direct3d问题,设备丢失
今天在调试项目的时候,遇到一个问题,之前在写代码的时候,调试都是在本地的电脑上进行调试,然而今天是通过远程登陆到电脑进行调试的,所以在调试的过程中遇到了一个问题. 其实开始的时候,有同事反应说,当远程 ...
- 设备模型(device-model)之平台总线(bus),驱动(driver),设备(device)
关于关于驱动设备模型相关概念请参考<Linux Device Drivers>等相关书籍,和内核源码目录...\Documentation\driver-model 简单来说总线(bus) ...
- ARM Linux 3.x的设备树(Device Tree)
1. ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称“this whole ARM thing is a f*cking pai ...
- 【转载】Linux设备树(Device Tree)机制
转:Linux设备树(Device Tree)机制 目录 1. 设备树(Device Tree)基本概念及作用2. 设备树的组成和使用 2.1. DTS和DTSI 2.2. DTC 2.3. DT ...
- dev/null和dev/zero区别 以及换回设备(loopback device)
转自:http://blog.chinaunix.net/uid-20729677-id-765105.html dev/zero,是一个输入设备,你可你用它来初始化文件. /dev/zero---- ...
- Direct3D 11的Device接口和DeviceContext接口
D3D的两个主要的接口: Device,ID3D11Device.创建资源,Shader对象,状态对象,查询对象,等.以及检查硬件功能,调试函数.可以认为是资源的提供者. Device Context ...
- 主次设备号 Device Major and Minor Numbers
对于一个设备文件而言真正重要的标志是它的主次设备号(major and minor device numbers).如果我们用ls命令列出/dev下的一个设备: frank@under:~$ ls - ...
随机推荐
- GO!自制一款【不丑】的名片
大概每一个人都有自己的名片.也见过不少名片. 我敢打赌,你常常认为很多名片"不咋地".尽管不是全部人都具备一定的审美眼光,但实际上每一个人都具备较高的"审丑"眼 ...
- 算法笔记_028:字符串转换成整数(Java)
1 问题描述 输入一个由数字组成的字符串,请把它转换成整数并输出.例如,输入字符串“123”,输出整数123. 请写出一个函数实现该功能,不能使用库函数. 2 解决方案 解答本问题的基本思路:从左至右 ...
- 【微软100题】定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部。 如把字符串abcdef左旋转2位得到字符串cdefab。请实现字符串左旋转的函数。
package test; /** * 定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部. 如把字符串abcdef左旋转2位得到字符串cdefab. 请实现字符串左旋转的函数. * ...
- Android中源码Launcher主屏幕程序排列详解【安卓Launcher进化一】
最近研究Lancher,从短信Mms的框架中过度到Launcher的bug和需求修改中,下面对launcher最简单的主屏幕程序的程序的布局的详 解,给读者一个入门的感觉,android的主屏幕一共分 ...
- postgresql一般crud存储过程参考[转]
http://blog.csdn.net/cdnight/article/details/18082255 这里是一份经过再三调试测试而成功的postgres数据库单表crud存储过程,请注意,对于多 ...
- 了解C#文件操作
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...
- IT行业面试指导 计算机行业面试技巧 面试技巧
简历篇 简历是你的的第一张脸,简历写的是否合理,是否吸引人,将决定你能否赢得宝贵的面试机会,迈出第一步! l 姓名,性别,学历,居住地,工作年限,邮箱,手机号 l 填“现居住地”,不要填成“户籍所 ...
- RESTful Web Service实战 小结1
1 REST的基本实现形式HTTP+URI+XML,但不是唯一形式.XML后来被Json格式替代.REST是一中架构风格(Representational State Transfer,表述性状态转移 ...
- unity, 获取mesh名称
正确的获取mesh名称的方法: MeshFilter meshFilter=node.GetComponent<MeshFilter>(); string meshName=mesh ...
- CentOS 6 下升级安装Mysql 5.5 完整步骤
使用系统CentOS 6.2本来已经系统自带安装了mysql 5.1,但是奈何5.1不支持utf8mb4字符集(详见:http://blog.csdn.net/shootyou/article/det ...