DXUT框架剖析(4)
创建一个设备
通常可以用标准的Direct3D方法CreateDevice()创建一个Direct3D设备,这个方法需要一个有效的显示适配器、设备类型(硬件抽象层设备或参考设备)、窗口句柄、运行标志(软件/硬件顶点运算模式和其他驱动标志)和提交参数。更重要的是,结构体D3DPRESENT_PARAMETERS有许多成员指定了后台缓冲区的设置、多重采样设置、交换效果、窗口模式、深度缓冲区设置、刷新频率、提交间隔和提交标志等。
为所有的参数选择合适的设置是比较繁琐的,DXUT框架使用函数DXUTCreateDevice()简化了Direct3D设备的创建,该函数的声明如下:
Creates a Direct3D 9 or Direct3D 10 device.
HRESULT DXUTCreateDevice(
bool bWindowed,
INT nSuggestedWidth,
INT nSuggestedHeight
);
Parameters
- bWindowed
- [in] If TRUE, the application will start in windowed mode; if FALSE, the application will start in full-screen mode. The default value is TRUE.
- nSuggestedWidth
- [in] The requested initial width of the application's back buffer. The actual width may be adjusted to fit device and operating system constraints. The default value is 0.
- nSuggestedHeight
- [in] The requested initial height of the application's back buffer. The actual height may be adjusted to fit device and operating system constraints. The default value is 0. If both nSuggestedWidth and nSuggestedHeight are zero, the dimension of the client area of the window is used.
Return Values
If the function succeeds, the return value is S_OK. If the function fails, the return value can be one of the error codes in DXUTERR.
Remarks
This function creates a new Direct3D 9 or Direct3D 10 device for the application. DXUT will pick the best device for the application based upon what is availble on the system and which Direct3D API version(s) the application supports. The API version(s) that the application supports is detrimined by which device callbacks are set. This logic can be overridden by calling DXUTSetD3DVersionSupport. If both Direct3D 9 and Direct3D 10 are availble on the system and both are supported by the application, then DXUT will favor Direct3D 10.
Alternately, the application can use the DXUTCreateDeviceFromSettings or handle device creation and pass the desired device to DXUT by using the DXUTSetD3D9Device or DXUTSetD3D10Device function. If neither DXUTCreateDevice, DXUTCreateDeviceFromSettings, nor DXUTSetD3D9Device or DXUTSetD3D10Device have been called before calling DXUTMainLoop, DXUT will automatically call DXUTCreateDevice using the default parameter values.
The application can call this method after a device has already been created to change the current device.
If a device is successfully found, the LPDXUTCALLBACKMODIFYDEVICESETTINGS callback will be called to allow the application to examine or change the device settings before the device is created. This allows an application to modify the device creation settings as it sees fit.
通过这个简单的调用,DXUT框架创建了一个使用默认设置的Direct3D设备,它可以在大多数情况下使用,默认的设备创建设置如下表所示:
Direct3D创建标志
描述
DXUTCreateDevice的默认值
函数CheckDeviceFormat()的参数AdapterFormat
适配器表面格式
当前桌面显示模式,如果桌面显示模式不足32位,则使用D3DFMT_X8R8G8B8
IDirect3D9::CreateDevice()的参数Adapter
显示适配器编号
D3DADAPTER_DEFAULT
D3DPRESENT_PARAMETERS.BackBufferCount
后台缓冲区数目
2,表示有两个后台缓冲区,可实现3倍缓冲。
D3DPRESENT_PARAMETERS.BackBufferFormat
后台缓冲区格式
桌面显示模式,如果桌面显示模式不足32位,则使用D3DFMT_X8R8G8B8
D3DPRESENT_PARAMETERS.AutoDepthStencilFormat
设备将自动创建的深度模板表面的深度格式
如果后台缓冲区格式小于等于16位,则使用D3DFMT_D16,否则使用D3DFMT_D32。
IDirect3D9::CreateDevice()函数的参数DeviceType
设备类型
若D3DDEVTYPE_HAL可行,则使用之,否则使用D3DDEVTYPE_REF,若二者均不可行,则创建失败。
D3DPRESENT_PARAMETERS.MultiSampleQuality
多重采样数量
MultiSampleQuality = 0表示禁用多重采样
D3DPRESENT_PARAMETERS.Flags
提交参数标志
D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
D3DPRESENT_PARAMETERS.PresentationInterval
提交间隔
窗口模式下为D3DPRESENT_INTERVAL_IMMEDIATE,全屏模式下为D3DPRESENT_INTERVAL_DEFAULT。
D3DPRESENT_PARAMETERS.FullScreen_RefreshRateInHz
显示适配器刷新屏幕的频率
0,表示当前桌面设置的刷新频率。
D3DPRESENT_PARAMETERS.BackBufferWidth和BackBufferHeight
显示器分辨率
在窗口模式下为640 x 480,全屏模式下为桌面分辨率。
D3DPRESENT_PARAMETERS.SwapEffect
交换效果
D3DSWAPEFFECT_DISCARD
IDirect3D9::CreateDevice()的参数BehaviorFlags
顶点运算标志
如果硬件支持,就使用D3DCREATE_HARDWARE_VERTEXPROCESSING,否则使用D3DCREATE_SOFTWARE_VERTEXPROCESSING。
D3DPRESENT_PARAMETERS.Windowed
窗口模式或全屏模式
TRUE,表示窗口模式
IDirect3D9::CreateDevice()的参数hFocusWindow
创建窗口的句柄
DXUTSetWindow函数的参数hWndFocus
D3DPRESENT_PARAMETERS.hDeviceWindow
设备窗口的句柄
DXUTSetWindow的参数hWndDeviceFullScreen或hWndDeviceWindowed
D3DPRESENT_PARAMETERS.EnableAutoDepthStencil
深度模板缓冲区创建标志
TRUE,表示自动创建深度模板缓冲区
选择最好的设备设置
在应用程序中,可以使用DXUTSetCallbackD3D9DeviceAcceptable设置回调函数IsDeviceAcceptable()帮助DXUT框架为应用程序选择最好的设备,该函数的声明如下:
Sets the Direct3D 9 device acceptable callback function.
VOID DXUTSetCallbackD3D9DeviceAcceptable(
LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE pCallback,
void* pUserContext
);
Parameters
- pCallback
- [in] Pointer to a LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE callback function. If the callback function is supplied, it will be called after the Direct3D 9 device .
- pUserContext
- [in] Pointer to a user-defined value which is passed to the callback function. Typically used by an application to pass a pointer to a data structure that provides context information for the callback function. The default value is NULL
Return Values
No return value.
Remarks
This function only needs to be called if the application supports rendering with Direct3D 9 device.
The LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE callback function is the appropriate location for the application to.
LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE
Application-defined callback function, called by DXUT to build an enumerated list of all possible Direct3D 9 devices. DXUT then selects the best device for creation among this list. This callback function allows the application to prevent unwanted devices from being added to the list.
bool LPDXUTCALLBACKISD3D9DEVICEACCEPTABLE(
D3DCAPS9* pCaps,
D3DFORMAT AdapterFormat,
D3DFORMAT BackBufferFormat,
bool bWindowed,
void* pUserContext
);
Parameters
- pCaps
- [in] Pointer to the D3DCAPS9 capabilities of the Direct3D 9 device
- AdapterFormat
- [in] Format of the Direct3D 9 adapter
- BackBufferFormat
- [in] Format of the Direct3D 9 backbuffer
- bWindowed
- [in] Indicates windowed mode. TRUE if the application runs windowed; FALSE if the application runs full-screen.
- pUserContext
- [in] Pointer to a user-defined value which is passed to the callback function. Typically used by an application to pass a pointer to a data structure that provides context information for the callback function. The default value is NULL
Return Values
Program the application to return TRUE if the device settings are acceptable. If not, the application should return FALSE.
Remarks
This function's parameters describe a set of unique valid device settings that could be used to create a device. The application can examine and reject this set if desired.
All possible unique valid combinations of the following device settings are sent to this callback function:
- pCaps
- AdapterFormat
- BackBufferFormat
- bWindowed
After the application rejects the unwanted device settings combinations, DXUT picks the best of the remaining combinations and uses that best combination to create the device. Before creating the device, DXUT calls LPDXUTCALLBACKMODIFYDEVICESETTINGS to allow the application to change any of the device creation settings.
应用程序可以使用这个回调函数拒绝任何硬件不支持或不想要的组合。例如,应用程序可以使用下列代码拒绝16位后台缓冲区格式以及所有至少不支持像素渲染2.0版本的设备:
bool CALLBACK IsD3D9DeviceAcceptable(D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,
bool bWindowed, void* pUserContext)
{
if(pCaps->PixelShaderVersion < D3DPS_VERSION(2, 0))
return false;
if(BackBufferFormat == D3DFMT_X1R5G5B5 || BackBufferFormat == D3DFMT_R5G6B5)
return false;
return true;
}
在回调函数IsD3D9DeviceAcceptable()被每种设置的组合调用之后,框架把这些可以接受的组合分级,并从中选出最优的使用。较高级别的组合包括:
(1)D3DDEVTYPE_HAL,为了得到硬件加速。
(2)如果该应用程序运行在全屏模式下,该框架会选择桌面格式所对应的适配器格式,这样从窗口到全屏模式的转换就快多了。例外的是,如果桌面显示模式不足32位,该框架会选择D3DFMT_X8R8G8B8。
(3)适配器格式所对应的后台缓冲区格式。
示例程序中,选择设备设置的核心代码如下:
//--------------------------------------------------------------------------------------
// Rejects any D3D9 devices that aren't acceptable to the app by returning false.
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D9DeviceAcceptable(D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,
bool bWindowed, void* pUserContext)
{
// Typically want to skip back buffer formats that don't support alpha blending
IDirect3D9* pD3D = DXUTGetD3D9Object();
/*
HRESULT CheckDeviceFormat(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DFORMAT AdapterFormat,
DWORD Usage,
D3DRESOURCETYPE RType,
D3DFORMAT CheckFormat
);
/*/
if(FAILED(pD3D->CheckDeviceFormat(pCaps->AdapterOrdinal, pCaps->DeviceType, AdapterFormat,
D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, BackBufferFormat)))
{
return false;
}
return true;
}
IDirect3D9::CheckDeviceFormat
Determines whether a surface format is available as a specified resource type and can be used as a texture, depth-stencil buffer, or render target, or any combination of the three, on a device representing this adapter.
HRESULT CheckDeviceFormat(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DFORMAT AdapterFormat,
DWORD Usage,
D3DRESOURCETYPE RType,
D3DFORMAT CheckFormat
);
Parameters
- Adapter
- [in] Ordinal number denoting the display adapter to query. D3DADAPTER_DEFAULT is always the primary display adapter. This method returns D3DERR_INVALIDCALL when this value equals or exceeds the number of display adapters in the system.
- DeviceType
- [in] Member of the D3DDEVTYPE enumerated type, identifying the device type.
- AdapterFormat
- [in] Member of the D3DFORMAT enumerated type, identifying the format of the display mode into which the adapter will be placed.
- Usage
- [in] Requested usage options for the surface. Usage options are any combination of D3DUSAGE and D3DUSAGE_QUERY constants (only a subset of the D3DUSAGE constants are valid for IDirect3D9::CheckDeviceFormat; see the table on the D3DUSAGE page).
- RType
- [in] Resource type requested for use with the queried format. Member of D3DRESOURCETYPE.
- CheckFormat
- [in] Format of the surfaces which may be used, as defined by Usage. Member of D3DFORMAT.
Return Values
If the format is compatible with the specified device for the requested usage, this method returns D3D_OK.
D3DERR_INVALIDCALL is returned if Adapter equals or exceeds the number of display adapters in the system, or if DeviceType is unsupported.
D3DERR_NOTAVAILABLE is returned if the format is not acceptable to the device for this usage.
Remarks
Here are some examples using IDirect3D9::CheckDeviceFormat to check for hardware support of:
- An off-screen plain surface format - Specify Usage = 0 and RType = D3DRTYPE_SURFACE.
- A depth-stencil format - The following snippet tests for the passed in depth-stencil format:
BOOL IsDepthFormatExisting( D3DFORMAT DepthFormat, D3DFORMAT AdapterFormat )
{
HRESULT hr = pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
AdapterFormat,
D3DUSAGE_DEPTHSTENCIL,
D3DRTYPE_SURFACE,
DepthFormat);
return SUCCEEDED( hr );
}See Selecting a Device (Direct3D 9) for more detail on the enumeration process.
- Can this texture be rendered in a particular format - Given the current display mode, this example shows how to verify that the texture format is compatible with the specific back-buffer format:
BOOL IsTextureFormatOk( D3DFORMAT TextureFormat, D3DFORMAT AdapterFormat )
{
HRESULT hr = pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
AdapterFormat,
0,
D3DRTYPE_TEXTURE,
TextureFormat);
return SUCCEEDED( hr );
} - Alpha blending in a pixel shader - Set Usage to D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING. Expect this to fail for all floating-point render targets.
- Autogeneration of mipmaps - Set Usage to D3DUSAGE_AUTOGENMIPMAP. If the mipmap automatic generation fails, the application will get a non-mipmapped texture. Calling this method is considered a hint, so this method can return D3DOK_NOAUTOGEN (a valid success code) if the only thing that fails is the mipmap generation. For more information about mipmap generation, see Automatic Generation of Mipmaps (Direct3D 9).
D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
Query the resource to verify support for post pixel shader blending support. If IDirect3D9::CheckDeviceFormat fails with D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, post pixel blending operations are not supported. These include alpha test, pixel fog, render-target blending, color write enable, and dithering.