【转贴】DXUT编程指南(四):通过DXUT使用设备

【转贴】DXUT编程指南(四):通过DXUT使用设备

通过DXUT使用设备
DirectX设备的创建在DXUT中得到了改进。你可以让你的应用程序直接创建设备而其它有框架提供的特征仍然可用。
创建设备
选择最佳的设备设置
修改可用的设备设置
降为软件顶点处理
使用你自己的设备

创建设备
典型地,你将通过标准的Direct3D方法创建设备
HRESULT CreateDevice(
    UINT                  Adapter,
    D3DDEVTYPE            DeviceType,
    HWND                  hFocusWindow,
    DWORD                 BehaviorFlags,
    D3DPRESENT_PARAMETERS *pPresentationParameters,
    IDirect3DDevice9      **ppReturnedDeviceInterface
);
这个方法需要有效的适配器,设备类型(HAL or REF),窗口句柄,行为标志(software/hardware vertex processing 和其它驱动标志),以及呈现参数(presentation parameters).此外,D3DPRESENT_PARAMETER结构体还拥有大量的成员指定后备缓冲区,多重采样设定,交换效果,窗口模式,深度模版缓冲,刷新率,呈现间隔,以及呈现标志。
为所有这些参数选择有效的设定是具有挑战性的。框架通过DXUTCreateDevice函数简化了这一选择过程。
HRESULT DXUTCreateDevice(
    UINT AdapterOrdinal  = D3DADAPTER_DEFAULT,
    BOOL bWindowed       = TRUE,
    INT nSuggestedWidth  = 640,
    INT nSuggestedHeight = 480,
    LPDXUTCALLBACKISDEVICEACCEPTABLE pCallbackIsDeviceAcceptable     = NULL,
    LPDXUTCALLBACKMODIFYDEVICESETTINGS pCallbackModifyDeviceSettings = NULL
);
最基本的用法是全部使用缺省参数调用:
DXUTCreateDevice();
通过这样的调用框架使用缺省设置创建一个在大多数情况下可用的设备。缺省的设置如下:

Direct3D Creation Flag Description Default Value from DXUTCreateDevice
AdapterFormat parameter of CheckDeviceFormat Adapter surface format. Desktop display mode, or D3DFMT_X8R8G8B8 if the desktop display mode is less than 32 bits.
Adapter parameter of IDirect3D9::CreateDevice Display adapter ordinal. D3DADAPTER_DEFAULT
D3DPRESENT_PARAMETERS. BackBufferCount Number of back buffers. 2, indicating triple buffering.
D3DPRESENT_PARAMETERS. BackBufferFormat Back buffer format. Desktop display mode, or D3DFMT_X8R8G8B8 if the desktop display mode is less than 32 bits.
D3DPRESENT_PARAMETERS. AutoDepthStencilFormat Depth format of the automatic depth-stencil surface that the device will create. D3DFMT_D16 if the backbuffer format is 16 bits or less, or D3DFMT_D32 otherwise.
The DeviceType parameter of IDirect3D9::CreateDevice Enumerated type of the device. D3DDEVTYPE_HAL if available, otherwise D3DDEVTYPE_REF or failure code if neither is available.
D3DPRESENT_PARAMETERS. MultiSampleQuality Quality level. MultiSampleQuality = 0, indicating multisampling is disabled.
D3DPRESENT_PARAMETERS. Flags Presentation parameters flags. D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
D3DPRESENT_PARAMETERS. PresentationInterval Presentation interval. D3DPRESENT_INTERVAL_IMMEDIATE for windowed mode, or D3DPRESENT_INTERVAL_DEFAULT for full-screen mode.
D3DPRESENT_PARAMETERS. FullScreen_RefreshRateInHz Rate at which the display adapter refreshes the screen. 0, indicating windowed mode.
D3DPRESENT_PARAMETERS. BackBufferWidth and .BackBufferHeight Display mode resolution. 640 x 480 pixels for windowed mode, or the desktop resolution for full-screen mode.
D3DPRESENT_PARAMETERS. AutoDepthStencilFormat Stencil format of the automatic depth-stencil surface that the device will create. D3DFMT_D16 if the backbuffer format is 16 bits or less, or D3DFMT_D32 otherwise.
D3DPRESENT_PARAMETERS. SwapEffect Swap effect. D3DSWAPEFFECT_DISCARD
BehaviorFlags parameter of IDirect3D9::CreateDevice Vertex processing flags. D3DCREATE_HARDWARE_VERTEXPROCESSING if supported, otherwise D3DCREATE_SOFTWARE_VERTEXPROCESSING.
D3DPRESENT_PARAMETERS. Windowed Windowed or full-screen mode. true, indicating windowed mode.
hFocusWindow parameter of CreateDevice Handle to the created window (see Using Application Windows with DXUT). hWndFocus parameter of DXUTSetWindow
D3DPRESENT_PARAMETERS. hDeviceWindow Handle to the device window. hWndDeviceFullScreen or hWndDeviceWindowed parameters of DXUTSetWindow
D3DPRESENT_PARAMETERS. EnableAutoDepthStencil Depth-stencil buffer creation flag. true.

应用程序可以通过参数传递给CreateDevice来更多的控制设备的创建,这将比使用缺省的方式更好。例如,你可以通过nSuggestedWidth and nSuggestedHeight参数改变窗口的尺寸。
DXUTCreateDevice(
    D3DADAPTER_DEFAULT,
    false,
    1024,
    786,
    NULL,
    NULL,
    NULL
);
要得到更多的控制权,应用程序可以使用这两个可选的回调函数,LPDXUTCALLBACKISDEVICEACCEPTABLE and LPDXUTCALLBACKMODIFYDEVICESETTINGS.

选择最佳的设备设置
你可以使用IsDeviceAcceptable回调函数帮助框架为你的应用程序选择最佳的设备设置,就像下面的代码:
bool CALLBACK IsDeviceAcceptable(
D3DCAPS9*     pCaps,
D3DFORMAT     AdapterFormat,
D3DFORMAT     BackBufferFormat,
bool          bWindowed,
void*         pUserContext )
{
    // TODO: return true for acceptable settings and false otherwise.
    return true;
}
这个回调函数的模型基于LPDXUTCALLBACKISDEVICEACCEPTABLE原型(This callback function is modeled on the prototype LPDXUTCALLBACKISDEVICEACCEPTABLE),框架为每个唯一的以下5个设置的有效组合调用这个函数一次:
D3DDEVTYPE DeviceType;
UINT       AdapterOrdinal;
D3DFORMAT  AdapterFormat;
D3DFORMAT  BackBufferFormat;
bool       Windowed;
注意适配器序号和设备类型没有直接的传入回调函数,而是分别作为D3DCAPS9结构体的成员。
通过这个回调函数,应用程序可以拒绝任何它不支持的或不想要的组合。例如,应用程序可以使用下面的代码拒绝16bits的后备缓冲区格式和所有至少不能支持像素着色器PS_2_0的设备:
bool CALLBACK IsDeviceAcceptable(
    D3DCAPS9*     pCaps,
    D3DFORMAT     AdapterFormat,
    D3DFORMAT     BackBufferFormat,
    bool          bWindowed )
{
    if( pCaps->PixelShaderVersion < D3DPS_VERSION(2,0) )
     return false;
    if( BackBufferFormat == D3DFMT_X1R5G5B5 || BackBufferFormat == D3DFMT_R5G6B5 )
        return false;
    return true;
}

为每个唯一的组合调用回调函数后,框架排列剩下的可用组合,并选择它们当中最好的。排名较高的如下:
D3DDEVTYPE_HAL,获取硬件加速
如果应用程序以全屏模式显示,框架更趋向于使用匹配桌面格式的适配器格式,这样可以在全屏与窗口之间快速切换。例外的是,如果桌面显示模式小于32位,框架更趋向于D3DFMT_X8R8G8B8.
匹配适配器格式的后备缓冲区格式
在选择了这些排名高的组合后,要创建设备,行为标志和呈现参数仍然是需要的。对于这些设置,Direct3D使用上面表中的缺省值。

修改可用的设备设置
应用程序可以通过使用第二个可选的回调函数修改对框架可用的设置,这个函数是ModifyDeviceSettings:
bool CALLBACK ModifyDeviceSettings(
    DXUTDeviceSettings* pDeviceSettings,
    const D3DCAPS9*     pCaps )
{
    // TODO: Include device creation requirements here. 
    // 返回真创建设备返回False保持当前设置
    return true;
}
这个函数是基于原型LPDXUTCALLBACKMODIFYDEVICESETTINGS的。DXUTDeviceSettings结构体被框架定义为:
struct DXUTDeviceSettings
{
    UINT       AdapterOrdinal;
    D3DDEVTYPE DeviceType;
    D3DFORMAT  AdapterFormat;
    DWORD      BehaviorFlags;
    D3DPRESENT_PARAMETERS pp;
};

这个结构体包含了创建设备所需要的所有东西,除了窗口句柄,它被假定为先前创建的窗口的句柄。框架用有效的数据填充这个结构体,然后允许应用程序通过ModifyDeviceSettings回调函数改变设备创建的选择。
在这个回调函数中,应用程序可以在DXUTDeviceSettings结构体中改变行为标志以及呈现参数,乃至结构体中任何其它的东西。如果应用程序在回调函数中什么都不改变,设备会成功的创建。然而,对设备创建设置的任何改变都需要被设备支持,否则可能会导致设备创建失败。
比如,如果应用程序需要一个D3DFMT_D24S8的深度模板缓冲区格式,就必须验证设备是否支持,就像下面的代码:
bool CALLBACK ModifyDeviceSettings(
    DXUTDeviceSettings* pDeviceSettings,
    const D3DCAPS9*     pCaps )
{
    IDirect3D9* pD3D = DXUTGetD3DObject();
    if( SUCCEEDED( pD3D->CheckDeviceFormat(
         pDeviceSettings->AdapterOrdinal,
         pDeviceSettings->DeviceType,
         pDeviceSettings->AdapterFormat,
         D3DUSAGE_DEPTHSTENCIL,
         D3DRTYPE_SURFACE,
         D3DFMT_D24S8 ) ) )
    {
     if( SUCCEEDED( pD3D->CheckDepthStencilMatch(
             pDeviceSettings->AdapterOrdinal,
             pDeviceSettings->DeviceType,
             pDeviceSettings->AdapterFormat,
             pDeviceSettings->pp.BackBufferFormat,
             D3DFMT_D24S8 ) ) )
     {
         pDeviceSettings->pp.AutoDepthStencilFormat = D3DFMT_D24S8;
     }
    }
   
    return true;
}

候选的方案是,回调函数可以使用框架的CD3DEnumeration 对象验证D3DFMT_D24S8是否被支持:
 bool CALLBACK ModifyDeviceSettings(
    DXUTDeviceSettings* pDeviceSettings,
    const D3DCAPS9*     pCaps )
{
    CD3DEnumeration *pEnum = DXUTGetEnumeration();
    CD3DEnumDeviceSettingsCombo *pCombo;
 
    pCombo = pEnum->GetDeviceSettingsCombo( pDeviceSettings );
 
    if( pCombo->depthStencilFormatList.Contains( D3DFMT_D24S8 ) )
        pDeviceSettings->pp.AutoDepthStencilFormat = D3DFMT_D24S8;
       
    return true;
}

应用程序修改了设备的设置后,框架就会用新的设置创建设备。
DirectX April 2005 SDK Update中的更新,ModifyDeviceSettings 回调函数返回了一个bool值。如果应用程序返回true框架继续正常的创建设备。如果返回false框架不改变设备并且保持当前的设备,如果已经有一个存在的话。这允许应用程序能够拒绝框架将设备改变到程序不能使用的请求。例如,在多监视器的缺省配置下,在监视器之间拖动窗口会导致框架改变设备。然而,如果应用程序不能使用其它的设备的话,它应当可以拒绝改变,并继续使用当前的设备。

回降到软件顶点处理
如果你设置一个Direct3D设备到支持像素处理却不支持顶点处理的硬件,你会因此需要改变行为标志。为了确保正确地降到软件顶点处理,谨防你不能拒绝一个基于IsDeviceAcceptable回调函数中顶点着色器版本的设备,并确保行为标志在ModifyDeviceSettings 回调函数中被正确调整。这儿有一个例子演示怎样做这些事情。
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings,
                                    const D3DCAPS9* pCaps )
{
    // If device doesn't support HW T&L or doesn't support 1.1 vertex
    // shaders in HW, then switch to SWVP.
    if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
         pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
    {
        pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    }

    else
    {
        pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    }
   
    return true;
}

使用你自己的设备
你没有必要依赖于框架来创建Direct3D设备。应用程序自己可以创建设备并将他传递给框架使用。就像应用程序可以覆盖框架的window creation 设置。简单的使用你想要的设置创建一个设备,然后调用 DXUTSetDevice函数让框架在你的设备上渲染。
注意:如果应用程序创建了不依赖于框架的设备,那么应用程序也必须在主循环执行完以后亲自的通过cleanup 释放设备接口。
另请参阅
通过DXUT作更高级的设备选择

你可能感兴趣的:(【转贴】DXUT编程指南(四):通过DXUT使用设备)