DirectX中文文档系列:二、Direct3D设备(device)

一、介绍

      Direct3D device 是 D3D的渲染组件,他封装并保存了渲染状态(rendering state)。D3D device负责模型转换和光照操作,并将最终结果光栅化(rasterize)到表面(surface)。

      结构上,d3d device 包含了转换、光照和光栅化模块。

      Direct3D 目前支持两种主要的设备类型: 硬件设备和参考设备。其中硬件设备支持硬件加速光栅化和硬件,软件处理顶点的阴影(shading)。

      最好的应用这两种设备的方法是:使用使用硬件设备进行最终游戏的发布,运用参考设备进行效果测试(ps:NV PerfHUD必须在参考设备中使用)。因为特定的硬件中可能无法支持所有的d3d效果。

 

二、创建一个设备

      如果要创建一个d3d设备,首先必须穿件一个d3d对象(使用 Direct3DCreate9)。因为所有的渲染设备共享一套物理(物理)资源,所以如果你从一个d3d对象创建多个渲染设备的话,效能的损耗将是相当大的。

      首先,初始化 D3DPRESENT_PARAMETERS 结构体,用于创建d3d设备。下面的代码创建了一个只在垂直同步操作下背部缓冲区(back buffer)和前置缓冲区交换的窗口程序。

         LPDIRECT3DDEVICE9 pDevice = NULL;
         D3DPRESENT_PARAMETERS d3dpp;

         ZeroMemory( &d3dpp, sizeof(d3dpp) );
         d3dpp.Windowed   = TRUE;
         d3dpp.SwapEffect = D3DSWAPEFFECT_COPY;

      接下来就可以创建D3D设备了。下面的代码创建了一个默认(显示)适配器,硬件设备(HAL device)和软件顶点处理的d3d设备。

         if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT,

                                                                  D3DDEVTYPE_HAL,

                                                                  hWnd,

                                                                  D3DCREATE_SOFTWARE_VERTEXPROCESSING,

                                                                  &d3dpp,

                                                                  &d3dDevice ) ) )

        {
               return E_FAIL;
        }

      注意:所有创建、释放、重置设备的操作都必须在和窗口程序同一个线程上进行。

 

三、窗口和全屏模式

      全屏模式下需要双显或者使用远程调试器来调试程序。可以使用DirectX Control Panel Tool来允许双显调试。窗口模式下就不用这样了。

 

四、选择设备

      我们的程序可以检测硬件所支持的d3d设备类型。这一节主要介绍枚举显卡和选择d3d设备。

      接下来我们来看一下创建一个全屏程序所需的步骤(窗口程序可以跳过大部分步骤):

      1、初始化时,程序必须枚举显示适配器(注意:一个显卡里头可能包含多个显示适配器)。 如果你的程序中不考虑多台显示器支持的话,可以忽略这个步骤,并将 D3DADAPTER_DEFAULT 作为参数传给步骤2的方法 IDirect3D9::EnumAdaptermodes .

      2、对每一个(显示)适配器,使用 IDirect3D9::EnumAdaptermodes 枚举她所支持的显示模式。

      3、如果有需要的话,我们可以调用 IDirect3D9::CheckDeviceType 检查特定显示模式下硬件加速支持的情况。以下列出示例代码:

	D3DPRESENT_PARAMETERS Params;
	// 初始化D3DPRESENT_PARAMETERS结构体的其他成员. 

	Params.BackBufferFormat = D3DFMT_X1R5G5B5; 

	if(FAILED(m_pD3D->CheckDeviceType(Device.m_uAdapter, 
                  		Device.m_DevType, 
                  		Params.BackBufferFormat, Params.BackBufferFormat, 
                  		FALSE))) 
		return E_FAIL;

      4、使用 IDirect3D9::GetDeviceCaps 检测在特定(显示)适配器上的显示设备所支持的特性。这个函数返回的特性在所有显示模式下都是一个常量。

      5、D3D设备如果使用枚举出来的显示模式和(显示)格式,就可以顺利在表面上做渲染。如果想使用不同的格式,就要调用 IDirect3D9::CheckDeviceFormat 确保设备支持渲染到这种格式上。如果可以渲染这种格式的话,那么调用 IDirect3D9::GetDeviceCaps 返回的所有特性都是可以使用的。

      6、最后,我们可以使用 IDirect3D9::CheckDeviceMultiSampleType 检测设备是否支持多重采样技术。

      在以上步骤结束之后,我们的程序就已经有了一堆可用的显示模式。最后一个步骤就是确认可用显存空间。这个步骤是很重要的,因为显存消耗无法预测。还有就是要注意有些显卡有不固定显存,这要求我们在全屏模式下检测显存不足之后进行提示。通常程序可以转为窗口模式,或者降低背部缓冲区的数量,亦或使用低复杂度的多重采样技术。

   

      窗口程序创建的步骤和上面差不多

      1、决定窗口显示区域。

      2、枚举适配器,找到显示区域所在显示器的适配器。如果显示区域依赖于多个适配器,那么程序可以分开使用每一个适配器,也可以只使用一个适配器,在显示的时候将Direct3D转换的像素传递给其他适配器。程序也可以忽略这两个步骤,使用 D3DADAPTER_DEFAULT 适配器。但是,如果这样,窗口程序被拖到附显示器上时,操作会变慢。 

      3、程序可以调用 IDirect3D9::CheckDeviceType 去确认,设备是否支持以特定的(像素颜色)格式渲染到背部缓冲区。IDirect3D9::GetAdapterDisplayMode 可以用来获取桌面显示的(像素颜色)格式,如下

	D3DPRESENT_PARAMETERS Params;
	// 初始化D3DPRESENT_PARAMETERS成员. 

	// 使用当前显示模式
	D3DDISPLAYMODE mode;

	if(FAILED(m_pD3D->GetAdapterDisplayMode(Device.m_uAdapter , &mode)))
		return E_FAIL;

	Params.BackBufferFormat = mode.Format;

	if(FAILED(m_pD3D->CheckDeviceType(Device.m_uAdapter, Device.m_DevType, 
	   Params.BackBufferFormat, Params.BackBufferFormat, FALSE)))
		return E_FAIL;

 

五、丢失设备

      d3d设备可以处于两种状态:操作状态(operational state)和丢失状态(lost state)。操作状态,就是设备的正常状态。设备在此状态下可以正常的运作和显示。设备在一些情况下会转变成丢失状态,如:在全屏模式下丢失键盘聚焦focus(比如其他全屏程序打开,或者用Alt+Tab键切换到桌面),因为此时无法进行渲染。丢失状态有个特性,静默失败。这种情况下所有渲染操作调用失败时,均返回成功。在这种情况下,IDirect3DDevice9::Present 会返回 错误码 D3DERR_DEVICELOST.

      我们并没有一个完整的列表,表明设备丢失的情况。这里列出一些会造成设备丢失的情况,比如丢失焦点(按alt+tab),电源管理器的事件,或者执行了其他全屏程序。还有就是,一切调用 IDirect2DDevice9::Reset 而返回失败的操作也会造成设备丢失。     

      在设备丢失的时,所有的从 IUnkown 继承的方法都可以执行。但是在这种情况下,一般会函数会返回如下三种情况:

  • 返回 D3DERR_DEVICELOST - 这表明程序必须处理设备丢失的情况,否者会造成一些预期之外的结果。
  • 静默失败 - 返回 S_OK 或者其他返回值,程序没法区分“成功”或者“静默失败”这两种情况。
  • 函数返回一个返回值

      注意

  • Direct3D 9 设备 -  IDirect3DDevice9::Present 返回D3DERR_DEVICELOST时,对枚举的操作就会失败,直到设备被重成功重置。
  • Direct3D 9Ex 设备永远不会返回 D3DERR_DEVICELOST,但是他会返回新的状态消息。

 1. 应对设备丢失

      丢失的设备重设时,必须重新创建资源(包括显存资源)。设备丢失时,程序通过请求设备判断能否回到操作状态。如果不行程序就会一直等待,直到设备可以被重置。

      如果设备可以被重置,就必须销毁所有显存资源,并且交换显示链。然后调用 IDirect3DDevice9::Reset 方法,这唯一可以让设备回到可操作模式下的方法。只有在程序释放了在D3DPOOL_DEFAULT分配的显存(包括 IDirect3DDevice9::CreateRenderTarget 和 IDirect3DDevice9::CreateDepthStencilSurface方法),设备才可以被重设。

      一般情况下,对Direct3D的操作会被忽略,直到设备重置到可操作状态。

      在丢失设备时,我们可以通过调用 IDirect3DDevice9::TestCooperativeLevel 方法得到的返回值来判断我们该怎么做。

2. 锁定操作

      在设备丢失后,Direct3D的内部机制会保证锁定操作成功。然而,他不能确保在锁定状态下的显存资源数据是正确的,只保证不返回错误代码。这种机制让程序锁定操作写写显存时不用考虑设备丢失情况。

3. 资源

六、硬件支持什么

 

 

七、处理顶点数据

 

 

(未完待续......) 

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭