Direct3d 设备丢失 (device lost) ._idirect3ddevice9::present返回错误码d3derr_devicelost-程序员宅基地

技术标签: D3D  

[-]
  1. 什么时候设备丢失
  2. 如何发现设备丢失
  3. 发现设备丢失后
  4. 4管理资源
  5. 处理设备丢失
  6. 人工制造设备丢失

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不会造成设备丢失,这个概念别弄混了。 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiangzhang321/article/details/8331071

智能推荐

ad hoc是什么的简称_苹果ios签名有几种?分别什么价格?app分发内测有几种?-程序员宅基地

文章浏览阅读425次。随着经济的发展,苹果手机用户在不断的增加,苹果方面对于app上架也越来越严格,因此,很多app都上架不了。所以逼得很多app开发商不得不另外寻找出路,寻找其他能做苹果app分发下载的渠道。那么目前市场上关于苹果app内测分发的渠道有哪几种呢?接下来大家就和‘咕噜分发’小编一起来看一下。就目前市场上苹果分发的渠道来看,苹果app的分发下载主流主要有4种:AppStore,企业签名,超级签名,TF上架..._adhoc和tf

html页面整体隐藏,从html页面隐藏javascript / jquery脚本?-程序员宅基地

文章浏览阅读326次。最好的办法是在加载dom树后立即删除脚本标记,或者在javascript中动态创建脚本标记.无论哪种方式,如果有人想使用Web开发人员工具或Firebug,他们仍然会看到javascript.如果它在浏览器中,它将被看到.动态创建脚本标记的一个优点是,如果关闭javascript,则不会加载javascript.如果我关闭了javascript,我仍然可以在html中看到所有内容,因为您无法删除脚..._html隐藏脚本

搭建Ubuntu 10.04系统(嵌入式开发) _initrd.lz和vmlinuz下载-程序员宅基地

文章浏览阅读3.9k次。搭建Ubuntu 10.04系统(嵌入式开发) 1. 下载安装:1.1下载ubuntu:http://cdimage.ubuntu.com/releases/ 1.2 安装ubuntu:1.2.1 硬盘安装: (windows,硬盘安装ubuntu)------------ boot.ini: ------------------------[boot loader]timeout=10default=multi(0)disk(0)rdisk(0)partition(1)/WINDOWS[operatin_initrd.lz和vmlinuz下载

「Tensorflow」基于CNN的数字OCR识别_tensorflow ocr-程序员宅基地

文章浏览阅读1.9k次,点赞4次,收藏14次。导读对于人类来说,识别手写的数字是一件非常容易的事情。我们甚至不用思考,就可以看出下面的数字分别是1,2,3。本期将使用Tensorflow搭建卷积神经网络,进行手写数字的识别。代码可关注公众号 IamZLT,后台回复「手写数字识别」即可免费获取。本系列文章Part1:基于CNN的数字OCR识别part2:基于CNN的汉字识别预处理对于手写数字的初始图片如下所示。在搭建网络前我们需要对其进行预处理。▌读入图片并进行二值化图像._tensorflow ocr

数据结构笔记03 线性表_int function (sq)-程序员宅基地

文章浏览阅读215次。线性表定义:零个或多个【数据元素】的有限集合 抽象数据类型:(可以参考大话数据结构)ADT 线性表(List)Data ...Operation ...endADT 线性表的顺序存储结构、链式存储结构a. 顺序存储结构源码:#include#include#define MAXSIZE 20#define OK 1#define_int function (sq)

枚举、二分问题总结_二分枚举-程序员宅基地

文章浏览阅读1.6k次。枚举算法设计步骤:1.确定枚举对象2.逐一列举可能解3.逐一验证可能解例题:数组配对—枚举题目描述给你一个长度为n的数组和一个正整数k,问从数组中任选两个数使其和是k的倍数,有多少种选法对于数组a1=1 , a2=2 , a3=2而言:(a1,a2)和(a2,a1)被认为是同一种选法;(a1,a2)和(a1,a3)被认为是不同的选法。输入数据第一行有两个正整数n,k。n<..._二分枚举

随便推点

android应用程序安装后自动打开_android 安装应用并自动打开-程序员宅基地

文章浏览阅读8.5k次。GetBroadcast.registerReceiver(getApplicationContext());//注册广播,用于监听应用是否安装完成//安装apkIntent intent = new Intent(Intent.ACTION_VIEW);intent.setDataAndType(Uri.fromFile(new File(fileURL)),"applicati_android 安装应用并自动打开

大坑:git无法添加一个空的文件夹_git 文件夹没有内容不可以add 吗-程序员宅基地

文章浏览阅读2.3w次,点赞3次,收藏9次。楔子今天在github上创建了个有初始化选中Initialize this repository with a README(初始化本库)的空白工程,然后用git clone到本地。我本意想创建一个gradle规范的目录,于是创建了.gitignore , README.md, settings.gradle这几个标准的文件,然后通过如下的脚本创建标准的代码目录。task "create-d..._git 文件夹没有内容不可以add 吗

phpexcel 设置批注_PHPExcel-设置表格字体颜色背景样式、数据格式、对齐方式、添加图片、批注、文字块、合并拆分单元格、单元格密码保护...-程序员宅基地

文章浏览阅读591次。首先到phpexcel官网上下载最新的phpexcel类,下周解压缩一个classes文件夹,里面包含了PHPExcel.php和PHPExcel的文件夹,这个类文件和文件夹是我们需要的,把classes解压到你项目的一个目录中,重名名为phpexcel,开始喽,(代码都摘自自带实例)程序部分require_once'./phpexcel/PHPExcel.php';//首先创建一个新的对象..._phpexcel_style_fill

html的<c >循环,C标签之forEach-程序员宅基地

文章浏览阅读2.8k次。属 性描 述是否必须缺省值items进行循环的项目否无begin開始条件否0end结束条件否集合中的最后一个项目step步长否1var代表当前项目的变量名否无varStatus显示循环状态的变量否无varStatus 属性JSTL中的varStatus和 var 属性一样。varStatus 用于创建限定了作用域的变量。只是。由 varStatus 属性命名的变量并不存储当前索引值或当前元素,而是..._html foreach

动态规划专题:beginner_字典序最小的lis-程序员宅基地

文章浏览阅读676次。UVa 11584:看了这道题我才知道我的思维有多弱……纠结了好久…… 状态转移方程:d[i]=min{d[j-1]+1|str[j-->i]为回文串}。 LA4256:水题一道,可我又搞了半天!就因为少记录了一维! 状态转移方程为:d[i][u]=min{d[i+1][v]|u,v相连},如果u!=原串的第i个数,再加上1。 UVa 105_字典序最小的lis

ecplise 如何导入包到web app library-程序员宅基地

文章浏览阅读545次。2019独角兽企业重金招聘Python工程师标准>>> ..._ecplise web app libary