Better Device Creation for Hardware Acceleration

Submit New Article

June 18, 2009 12:00 AM PDT


The objective of this document is to help Direct3D 9 application developers use a better method to create the best D3D 9 device possible. By following these boilerplate steps, the most capable device will be created to support your application. This procedure does not involve long and tedious device ID lists, switching on various SKUs, or other manual and time-consuming tasks. Instead, take advantage of the reporting capabilities that the graphics driver must do anyway! We hope that after reading this article the reader would be able to take these ideas and incorporate them into their own application with little effort… and a lot of gain.

D3D 9 Devices and Vertex Processing
To make sure we’re all on the same page, let’s begin with a D3D Device. Your application probably starts with creating one anyway, so it seems a handy place to begin. Essentially, this construct determines how everything is going to work later on. When you create this device, you determine when and where your D3D pipeline will use the CPU or the GPU, among other things. For example, you can ask for a D3D device to be created that does vertex processing on the GPU. (As an aside, that’s known as “hardware processing” – what’s the CPU, chopped liver?) If the GPU doesn’t do vertex processing, like early integrated graphics chipsets, then the device won’t be created. It used to be that that was your only choice, and if you had a high-power game and lower-performance CPU… well, you might as well give up. Creating a device that used the CPU for vertex processing on top of AI and physics and game logic and sound and…not too pretty.

But… My Game Needs Hardware Vertex Processing
Does it? Today‘s CPUs are incredibly fast and with multi-core and SMT, they can pretty much handle everything thrown at them. However, you still want to offload as much as possible to the GPU because it’s a good assistant. In general, you should try to use the GPU, but fall back to the CPU before bailing out altogether. Handily enough, you can do all this at device creation time fairly easily.

The example code included here demonstrates a way to gracefully choose “pure” HW (on the GPU using PUREDEVICE), then "mixed" HW/SW (GPU/CPU), and finally just SW (on the CPU). This code also takes into account the vertex and pixel shader levels that you may require. This type of device creation decision tree will create the best GPU/CPU combination for all hardware – including future enhancements. If someone is running this code on an Intel® GMA 950 (older Intel Integrated Graphics), it will allow the game to run. If they then purchase the latest-and-greatest 3rd party graphics card and put it in the system, the game will run with no modifications – and will use the (probably) more advanced GPU vertex processing.

Summary
With some simple care to your initialization code, your game can run the best on a wide variety of graphics hardware. This ensures happy customer experiences as well as less maintenance on your end when newer hardware is released. As always, questions and feedback are gladly taken at the ISN graphics forum: http://software.intel.com/en-us/forums/developing-software-for-intel-graphics-technology

Example Code – Note the items in green and red

HRESULT hr;
IDirect3DDevice9* pDevice = NULL;
 

UINT nMinRequiredVertexShaderLevel = yourMinimumVSLevel;   // i.e. D3DVS_VERSION(3,0)
UINT nMinRequiredPixelShaderLevel = yourMinimumPSLevel;   // i.e. D3DPS_VERSION(2,0)

 
// Clear any vertex processing flags… 
BehaviorFlags &= ~( D3DCREATE_HARDWARE_VERTEXPROCESSING |
                    D3DCREATE_MIXED_VERTEXPROCESSING | 
                    D3DCREATE_SOFTWARE_VERTEXPROCESSING );
 
// We’ll try to get ‘PURE’ hardware first;
BehaviorFlags |= D3DCREATE_PUREDEVICE;
 

hr = pD3D->CreateDevice( Adapter, 
                          DeviceType, 
                          hFocusWindow,
                          BehaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING,
                          pPresentationParameters,
                          &pDevice );
if ( D3D_OK == hr )
{
         // NOTICE: We’re using pDevice->GetDeviceCaps() … not pD3D->GetDeviceCaps()
         hr = pDevice->GetDeviceCaps( &Caps9 );
}
 
if ( ( D3D_OK != hr) || 
     ( Caps9.VertexShaderVersion < nMinRequiredVertexShaderLevel ) ||
     ( Caps9.PixelShaderVersion < nMinRequiredPixelShaderLevel ) )
{
         // we didn’t get ‘PURE’ hardware ... so clear the flag.
         BehaviorFlags &= ~D3DCREATE_PUREDEVICE;
 
         hr = pD3D->CreateDevice( Adapter, 
                                   DeviceType, 
                                   hFocusWindow,
                                   BehaviorFlags | D3DCREATE_MIXED_VERTEXPROCESSING,
                                   pPresentationParameters,
                                   &pDevice );
         if ( D3D_OK == hr )
         {
                  hr = pDevice->GetDeviceCaps( &Caps9 );
         }
 
         if ( ( D3D_OK != hr ) || 
              ( Caps9.VertexShaderVersion < nMinRequiredVertexShaderLevel ) ||
              ( Caps9.PixelShaderVersion < nMinRequiredPixelShaderLevel ) )
 
         {
                  hr = pD3D->CreateDevice( Adapter, 
                                            DeviceType, 
                                            hFocusWindow,
                                            BehaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                            pPresentationParameters,
                                            &pDevice );
                 if ( D3D_OK == hr )
                 {
                          //NOTE: use pD3D for SW otherwise 0 will be returned for VS version
                          hr = pD3D->GetDeviceCaps(Adapter, DeviceType, &Caps9 );
                          
                          //Software Vertex Processing Device should always support VS3.0
                          ASSERT( Caps9.VertexShaderVersion >= nMinRequiredVertexShaderLevel );
 
                          if ( Caps9.PixelShaderVersion < nMinRequiredPixelShaderLevel );
                          {
                                   // … Minimum specs for this application are 
                                   // … higher than this system can handle 
                                   // …  PLEASE: Exit application gracefully …
                                   pDevice->Release();
                                   pDevice = NULL;
                                   hr = E_FAIL;
                          }
                  }
         }
}