D3DBook:The Direct3D 10 Device

From GDWiki
Jump to: navigation, search

Contents

Direct3D 10 Device

As the former API versions Direct3D 10 is still based on a state machine. The complete current context is stored in the device object. Each device is bound to exactly one graphics adapter but you could have multiple device objects per adapter. Every object that is created on a device can only use together with this one even when you have two or more devices on the same adapter. The only exceptions from this rule are shared resources. But even if you create a resource as shared the object is exclusive bound to its creator. You need to open the resource on the second device using a shared handle to get a second object.

To tell Direct3D 10 that you need a shared resource you have to add D3D10_RESOURCE_MISC_SHARED to the MiscFlags in the description. The actual share handle can only be accessed with the IDXGIResource interface. As there is only one open resource method for all type of resources it is necessary to provide the type of interface that should be used for this resource on the second device.

// Create a shareable texture
ID3D10Texture2D* pTexture2D = NULL;
 
D3D10_TEXTURE2D_DESC Texture2DDesc;
 
Texture2DDesc.Width = 1024;
Texture2DDesc.Height = 1024;
Texture2DDesc.MipLevels = 0;
Texture2DDesc.ArraySize = 1;
Texture2DDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
Texture2DDesc.SampleDesc.Count = 1;
Texture2DDesc.SampleDesc.Quality = 0;
Texture2DDesc.Usage = D3D10_USAGE_DEFAULT;
Texture2DDesc.BindFlags = D3D10_BIND_SHADER_RESOURCE;
Texture2DDesc.CPUAccessFlags = 0;
Texture2DDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED;
 
pD3D10Device->CreateTexture2D (&Texture2DDesc, NULL, &pTexture2D);
 
// Get the handle
 
IDXGIResource* pResource;
 
pTexture2D->QueryInterface (__uuidof(IDXGIResource), (void**)&pResource);
 
HANDLE resourceHandle;
pResource->GetSharedHandle (&resourceHandle); 
 
// Transfer the Handle
// Open the resource
 
ID3D10Texture2D* pSharedTexture2D;
 
pD3D10Device2->OpenSharedResource (resourceHandle,
    __uuidof(ID3D10Texture2D), (void**)&pSharedTexture2D);

In any cases theses resource interfaces are provided to the device interface to configure the 3D pipeline. As there are multiple different stages most method names starts with a two character code that identify the stage. The three shader stages are all based on the common shader core and share most methods names after the two character code. As the second character is always S for shader you need to be careful to not to hit the wrong unit. Additional there are some methods that are not bound to a particular stage.

A Direct3D 10 device and the objects it creates are guaranteed to be working until a major problem makes the under laying hardware inaccessible. This can be caused by a driver fault, a draw operation that need too many time or a physical remove of the graphic hardware. GetDeviceRemovedReason can be used to query the reason. But if it return anything else than S_OK you have to recreate all Direct3D 10 objects. There is no way to recover from such an error without start over complete.

Drawing commands

After the pipeline is configured with the state objects and resources the Direct3D 10 device provides five draw methods. The base Draw method use only the attached vertex buffers and draw the specified number of vertices beginning with the provided start vertex. To make use of an index buffer the device interface provides the DrawIndexed method. Like the non indexed version it takes the number of vertices to draw. Additional you can specify a start position in the index buffer and which vertex should be take for the zero index.

There are methods to draw instanced objects for both draw methods. To use them the device must be configured with an input layout that contains per instances elements. Then the methods take the number of instances and a second start position for the vertex buffers that contain the instance data.

The last Draw Method called DrawAuto is used together with the stream out stage. As the geometry shader that feeds the stream out can generate a dynamic number of results per run the calling application does not necessary know the number of vertices in a streamed out vertex buffer. DrawAuto will use internal counters to draw all vertices that are generated during the last stream out operation on this buffer. As different buffers could have different number of results stored DrawAuto supports only one vertex buffer at the same time.

// First pass: Stream out to vertex buffer
pd3dDevice->SOSetTargets( 1, &pSOBuffer, offset );
pd3dDevice->IASetVertexBuffers( 0, 1, pInputBuffers, stride, offset );
pd3dDevice->Draw (100, 0);
pd3dDevice->SOSetTargets( 1, &pNULLBuffer, offset );
 
// Second pass: Render anything from the vertex buffer that was written before
pd3dDevice->IASetVertexBuffers( 0, 1, pSOBuffers, stride, offset );
pd3dDevice->DrawAuto ();

Counter, Query

A Direct3D 10 device is mostly used to send instructions to a graphics adapter. Beside of this it can create asynchronous objects to feed back some information to the application. There are two main categories of asynchronous objects. The 8 Query types are supported from any device. Counter are optional. Every adapter could support any combination of the 18 predefined counter types and a variable number of additional custom counter types. The second difference is that you can create and use as much queries as you want but the number of active counters could be limited.

Both counters and queries implement the ID3D10Asynchronous interface. Before the current value could read with a call GetData the object need to collect it. To do this you have to call the Begin and End methods to mark the range of commands you are interested in. As the event and timestamp query don't collect data for multiple commands the Begin method could not be used together with theses. In any case you need to be aware that the results are not stored in the objects until the GPU have execute the end command. If you try to read it to early you force the CPU to wait and waste time.

Predications

One of the query types can be use for more than just returning results back to the application. The predication could be used to execute draw commands and resource manipulations based on the result of former operations. As long as a predication object is attached to the device with SetPredictaion the following commands could be dropped if the object is not in the defined state. The advantage over checking the query state with GetData from the applications is that the whole operation could possibly be done from the graphics adapter without stalling the application. But compared to the manual method the usage of predications does not guaranteed that the operations will not execute. Predications are only hints that work could be skipped. Therefore you have to make sure that your rendered image is still valid if all your predicated code is executed.

// First render a occluder mesh to setup the predication
pPredicate->Begin();
 
// Render simple mesh
pPredicate->End();
 
// Do something else
 
// Then render the complex mesh with the predication hint
pd3dDevice->SetPredication( pPredicate, FALSE );
 
// Render the complex mesh
pd3dDevice->SetPredication( NULL, FALSE );

Checks

Direct3D 10 provides a rich set of guaranteed functions but there are still some options that are not necessary supported from every graphics adapter. Therefore each device supports some check methods to ask for these optional features.

CheckFormatSupport allows asking the device for every resource format which usages are valid.


Support flag Description
D3D10_FORMAT_SUPPORT_BUFFER The format can used to create buffer resources
D3D10_FORMAT_SUPPORT_IA_VERTEX_BUFFER A buffer resource with this format can be used as index buffer.
D3D10_FORMAT_SUPPORT_IA_INDEX_BUFFER A buffer resource with this format can be used as vertex buffer.
D3D10_FORMAT_SUPPORT_SO_BUFFER A buffer resource with this format can be used as stream out target.
D3D10_FORMAT_SUPPORT_TEXTURE1D The format can be used to create 1D texture resources.
D3D10_FORMAT_SUPPORT_TEXTURE2D The format can be used to create 2D texture resources.
D3D10_FORMAT_SUPPORT_TEXTURE3D The format can be used to create 3D texture resources.
D3D10_FORMAT_SUPPORT_TEXTURECUBE The format can be used to create cube texture resources.
D3D10_FORMAT_SUPPORT_SHADER_LOAD Resources with this format can be read from a shader with the load instruction.
D3D10_FORMAT_SUPPORT_SHADER_SAMPLE Resources with this format support reads by a sampler.
D3D10_FORMAT_SUPPORT_SHADER_SAMPLE_COMPARISON Resources with this format supports reads by a comparison sampler.
D3D10_FORMAT_SUPPORT_SHADER_SAMPLE_MONO_TEXT Reserved
D3D10_FORMAT_SUPPORT_MIP Resources with this format can have mip maps.
D3D10_FORMAT_SUPPORT_MIP_AUTOGEN Resources with this format can generate mip maps. (GenerateMips)
D3D10_FORMAT_SUPPORT_RENDER_TARGET Resources with this format can be used as render targets.
D3D10_FORMAT_SUPPORT_BLENDABLE Resources with this format support blend operations in the output merger.
D3D10_FORMAT_SUPPORT_DEPTH_STENCIL Resources with this format can be used as depth stencil buffer.
D3D10_FORMAT_SUPPORT_CPU_LOCKABLE Resources with this format can be created with CPU access.
D3D10_FORMAT_SUPPORT_MULTISAMPLE_RESOLVE Resources with this format supports multisample resolve. (ResolveSubresource)
D3D10_FORMAT_SUPPORT_DISPLAY The format is a valid display format.
D3D10_FORMAT_SUPPORT_CAST_WITHIN_BIT_LAYOUT The format is cast able.
D3D10_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET The format supports multisampling when used as render target.
D3D10_FORMAT_SUPPORT_MULTISAMPLE_LOAD Resources with format can be accessed with the shader load instruction.

Table: Format support flags

To check the supported multisampling levels the device provides the CheckMultisampleQualtiyLevels method. It returns the number of different quality levels for a combination of format and sample count.

The last two methods CheckCounter and CheckCounterInfo work together. CheckCounter is used to get information about a single counter. CheckCounterInfo returns the global ones. Beside of the number of custom counter types it tells you how many counter slots are available. As a single counter can requires more than one slot you have to use CheckCounter to get the number of slots for every counter type.

Layers

Direct3D 10 uses a layered design to provide additional functionality. These layers exist between the core device and the application and need to be selected during device creation. To make the additional functions accessible a layer could provide special interfaces that could be accessed with the QueryInterface method of the device object. The base installation of Direct3D 10 provides only the multithreading layer which is enabled as default. After an SDK installation you could use two additional layers. One will provide additional debug information while the second one allows switching between hardware and the reference device without recreation.


Layer Description Interfaces
Debug The debug layer offers additional validations and ist only available on systems with an SDK installation. ID3D10InfoQueueID3D10Debug
Switch to reference This layer allows switching between hardware and the references device without recreate the device. As the debug layer it is only available when the SDK is installed. ID3D10SwitchToRef
Thread-Safe This layer provides multithreading protection for the Direct3D 10 device. It is enabled by default. ID3D10Multithread

Table: Layers

The multithreading layer allows using a Direct3D 10 device from more than one thread. It automatically protects all calls. If this is all you need you will never have to access the IDirect3D10Multithread interface. But sometimes it could be necessary to make sure that a sequence of commands will not be interrupted from a second thread. For this case the IDirect3D10Multithread interface provides Enter and Leave methods to manage the critical section for the device by your own. Beside of this you could disable the multithread protection using this interface.

The debug layer adds two additional interfaces. While IDirect3D10InfoQueue provides access to the messages generate from the debug layer ID3D10Debug let you control the behavior of the debug device.

The switch to reference layer adds the ID3D10SwitchToRef interface to the device. Its purpose is to manage the flag that select the device that should be used to render and the change from the hardware device to the reference rasterizer and back.

To create or in the case of the thread safe layer disable an layer you have to provide a combination of creation flags to one of the two device creation functions.


Flag Layer Comment
D3D10_CREATE_DEVICE_SINGLETHREADED Thread Safe Disable the layer
D3D10_CREATE_DEVICE_DEBUG Debug Only available with the SDK
D3D10_CREATE_DEVICE_SWITCH_TO_REF Switch to Reference Only available with the SDK

Table: Layer control flags

As the layer based on a plug-in technology it is possible that future SDKs or other extensions will provide more layer later.

Personal tools