D3D中的设备丢失
周末闲着没事,翻译一段DirectX SDK帮助文档,是关于设备丢失及其处理方法的。路径是DirectX Graphics-Direct3d 9-Programming Guide-Getting Started-Direct3D Devices-Lost Devices,翻译完才发觉,原来翻译并不是那么容易的事,总是觉得某些地方词不达意,英文水平亟待提高!
设备丢失
一个Direct3D设备要么处于可操作状态,要么处于丢失状态,可操作状态即正常状态,设备按预期运行并渲染。当某些事件发生时,设备将转入丢失状态,比如在全屏状态下失去键盘焦点,这将导致无法继续渲染。设备丢失的一个特点是所有的渲染操作都会silent failure,这就意味着即使渲染操作失败了,渲染函数也能正确返回。在这种情况下,函数Present将返回D3DERR_DEVICELOST。
按照设计,并没有一个详细的列表指定哪些情况下设备会丢失。一些典型的情形包括失去焦点,比如用户按下了 ALT+TAB或者某个系统对话框被初始化时,设备也会因为电源管理事件而丢失,比如屏保?或者其他程序请求全屏。另外,函数Reset的失败也会导致设备丢失。
所有继承自IUnknown的函数都能在设备丢失后正常运行,当设备丢失后,这些函数有如下三个选择
1 返回D3DERR_DEVICELOST-这意味着设备已经丢失
2 Silently fail,返回S_OK或其他返回值-如果一个函数silently fails,应用程序无法区别结果是成功还是silently failure
3 返回一个返回值
Direct3D9和Direct3D 9Ex的区别
一个Direct3D设备可能在调用Present函数时返回D3DERR_DEVICELOST,这意味着接下来所有的函数调用都将失败,直到设备被重置。
一个Direct3D 9Ex设备从来不会返回D3DERR_DEVICELOST,但是会返回其他的状态信息,在Vista上,只有两种情况会导致设备丢失,一是硬件被重置(由于hardware hanging),二是设备驱动停止了(device driver stopped),当hardware hanging发生时,可以调用IDirect3DDevice9Ex::ResetEx来重置设备。如果hardware hangs, 纹理内存将会丢失。当设备驱动停止时,IDirect9Ex对象必须被重新创建以恢复渲染
当渲染区域被其他窗口遮挡时,或者当全屏程序被最小化时,IDirect3DDevice9Ex::PresentEx 将返回S_D3DPRESENTATIONOCCLUDED。当全屏程序收到WM_ACTIVATEAPP消息时会恢复渲染。
在以前版本的DirectX中,当应用程序的模式改变时(窗口和全屏之间),能恢复渲染的唯一方式就是重置设备并且重新创建所有显存资源和swap chain,而在Vista上则不必,当模式改变时,调用Reset函数不会导致纹理,表面等资源丢失,也不必重建这些资源。
响应设备丢失
丢失的设备被重置后须重新创建资源(包括显存资源),如果设备丢失,应用程序会询问设备以确定它是否能恢复到可操作状态,如果不能,应用程序会一直等待,直到设备能被恢复。
如果设备能被恢复,应用程序会销毁所有显存资源和Swap Chain,然后调用IDirect3DDevice9::Reset函数,该函数是唯一能在设备丢失后起作用的函数,也是唯一能将设备从丢失状态转换到可操作状态的函数。除非应用程序释放了所有内存类型为D3DPOOL_DEFAULT的资源,包括使用函数IDirect3DDevice9::CreateRenderTarget和IDirect3DDevice9::CreateDepthStencilSurface 创建的资源,否则Reset函数将会失败。
大多数情况下,一些频繁调用的D3D函数并不会返回任何信息指出设备是否丢失,应用程序可以继续调用这些函数,比如IDirect3DDevice9::DrawPrimitive,而不会接到设备丢失的通知。但是在D3D内部,设备被恢复到可操作状态之前,这些函数调用都将被忽略。
当应用程序遭遇设备丢失时,可以查询函数IDirect3DDevice9::TestCooperativeLevel的返回值来确定做什么。
锁定操作
在内部,Direct3D会做足够的工作确保设备丢失时锁定操作能够成功进行,尽管如此,也不能确保显存资源在锁定时的正确性。但是能确保不会返回错误码,这使得应用程在执行锁定操作时不必担心设备丢失。
资源
资源会消耗显存。因为设备丢失时,设备将和显卡中的显存失去连接,不能确保在分配显存的成功。于是所有的资源分配函数都会返回D3D_OK,但实际上分配的都是dummy的系统内存,因为所有的资源都必须在设备重置前释放掉,There is no issue of over-allocating video memory. 这些dummy surfaces 能够被锁定和拷贝,看起来似乎是正常工作,直到应用程序调用Present函数并且发现设备已经丢失。
所有的显卡内存必须在设备重置前被释放掉,这意味着应用程序必须释放使用IDirect3DDevice9::CreateAdditionalSwapChain创建的swap chain以及所有使用D3DPOOL_DEFAULT创建的资源。而不必释放D3DPOOL_MANAGED和D3DPOOL_SYSTEMMEM类型的资源。其他状态数据自动被销毁。
我们鼓励您开发的应用程序响应设备丢失,可以使用一段单独立代码来处理,可以用在设备启动的时候初始化设备。
获取数据
对于硬件实现的单通道渲染,Direct3D允许应用程序使用IDirect3DDevice9::ValidateDevice验证纹理和渲染状态。这个函数通常在程序初始化的时候调用,它会在设备丢失时返回D3DERR_DEVICELOST
Direct3D同样允许应用程序从显存中拷贝已经生成的或之前写过的Image到系统内存中。因为传输过程中Images可能会丢失,所以当设备丢失时,Direct3D允许这些操作失败。
至于异步查询,当FLUSH标志被指定时,IDirect3DQuery9::GetData函数返回D3DERR_DEVICELOST以告知程序IDirect3DQuery9::GetData永远不会返回S_OK。
拷贝操作,IDirect3DDevice9::GetFrontBufferData会在设备丢失时返回失败,因为设备丢失时没有主表面(primary surface),IDirect3DDevice9::CreateAdditionalSwapChain也会在设备丢失时返回失败,因为设备丢失时是不能创建back buffer。这些情况时除了IDirect3DDevice9::Present,IDirect3DDevice9::TestCooperativeLevel和IDirect3DDevice9::Reset之外唯一能发现设备丢失的情况。
可编程着色器
在Direct3D 9中,顶点着色器和像素着色器不必在设备重置后重新创建,他们会被记住,在之前的DirectX中,丢失的设备需要重建着色器。