MSDN Documentation

DirectX Execution Model

The DirectX execution model defines how graphics operations are initiated, managed, and processed by the system. Understanding this model is crucial for optimizing performance and ensuring correct rendering behavior.

Core Concepts

DirectX operations are typically managed through a series of steps:

Key APIs

Several core APIs are fundamental to managing DirectX execution:

API Component Description Key Functions/Objects
Command Interface Represents the interface for recording commands. ID3D12CommandAllocator, ID3D12GraphicsCommandList
Command Queue Manages the submission and execution of command lists. ID3D12CommandQueue
Synchronization Objects Facilitate communication and timing between the CPU and GPU. ID3D12Fence, ID3D12QueryHeap
Root Signature Defines the set of resources accessible by shaders. ID3D12RootSignature

Execution Flow

A typical execution flow involves the following steps:

  1. Create a command allocator to manage command list memory.
  2. Create a graphics command list, associating it with the command allocator.
  3. Begin recording commands onto the command list using methods like SetGraphicsRootSignature, IASetPrimitiveTopology, OMSetRenderTargets, and draw/dispatch calls.
  4. End the recording of the command list.
  5. Create a fence for synchronization.
  6. Submit the command list(s) to a command queue using ExecuteCommandLists.
  7. Signal the fence on the CPU and wait for the GPU to reach a certain point using SetEventOnCompletion or Signal.

Example Snippet (Conceptual)


// Assume device, command_allocator, and command_list are already created

// Set root signature
command_list->SetGraphicsRootSignature(root_signature);

// Set render target and depth stencil
command_list->OMSetRenderTargets(1, &render_target_view_handle, TRUE, &depth_stencil_view_handle);

// Bind vertex and index buffers
command_list->IASetVertexBuffers(0, 1, &vertex_buffer_view);
command_list->IASetIndexBuffer(&index_buffer_view);

// Set pipeline state
command_list->SetPipelineState(pipeline_state);

// Draw call
command_list->DrawIndexedInstanced(index_count, instance_count, start_index_location, base_vertex_location, start_instance_location);

// End command list recording
command_list->Close();

// Submit to command queue
command_queue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&command_list);

// Signal fence and wait (simplified)
UINT64 fence_value;
command_queue->Signal(fence, fence_value);
if (fence->GetCompletedValue() < fence_value)
{
    HANDLE event = CreateEvent(nullptr, FALSE, FALSE, nullptr);
    fence->SetEventOnCompletion(fence_value, event);
    WaitForSingleObject(event, INFINITE);
    CloseHandle(event);
}