Namespace: Microsoft.Directx.Direct3D
Assembly: Microsoft.Directx.Direct3D.dll
Command lists are a fundamental mechanism in modern graphics APIs like DirectX 12 for managing and submitting drawing commands to the GPU. They allow for asynchronous execution and parallel command buffer recording, leading to significant performance improvements by offloading CPU work and enabling better GPU utilization.
Instead of recording commands directly to a main command buffer, you record them into individual command lists. These command lists can then be batched together and submitted to a command queue for execution by the GPU. This separation provides flexibility in how commands are structured and executed.
The DirectX graphics API provides several key structures and interfaces for working with command lists:
ID3D12GraphicsCommandListThis is the primary interface for recording graphics commands. It provides methods for:
DrawInstanced, DrawIndexedInstanced).ID3D12CommandAllocatorEach command list requires a corresponding command allocator. The allocator manages the memory used to store the commands recorded into a command list. Once a command list is submitted to the GPU, its allocator can be reset to be reused for recording new commands.
ID3D12CommandQueueThis interface represents the command queue through which command lists are sent to the GPU for execution. Key methods include:
ExecuteCommandLists: Submits one or more command lists for execution.Signal: Signals a fence on the GPU.Wait: Waits for a fence to be signaled.ID3D12CommandAllocator.ID3D12GraphicsCommandList, passing the allocator.ID3D12GraphicsCommandList::Begin.ID3D12GraphicsCommandList::End.End for some APIs, or explicit Close).ID3D12CommandQueue using ExecuteCommandLists.ID3D12CommandAllocator::Reset to prepare for the next frame or set of commands.The following is a simplified, conceptual example of how command lists might be used. Actual implementation details may vary based on the specific DirectX version and context.
// Assume pCommandList is an ID3D12GraphicsCommandList*
// Assume pCommandAllocator is an ID3D12CommandAllocator*
// Assume pCommandQueue is an ID3D12CommandQueue*
// Reset the command allocator for the new frame
pCommandAllocator->Reset();
// Begin recording commands
pCommandList->Reset(pCommandAllocator, nullptr); // nullptr for initial pipeline state
// Set pipeline state, root signature, and descriptor heaps...
// pCommandList->SetPipelineState(pPipelineState);
// pCommandList->SetGraphicsRootSignature(pRootSignature);
// ...
// Set render target and depth stencil views
// CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(rtvHeap->GetCPUDescriptorHandleForHeapStart());
// CD3DX12_CPU_DESCRIPTOR_HANDLE dsvHandle(dsvHeap->GetCPUDescriptorHandleForHeapStart());
// pCommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, &dsvHandle);
// Clear the render target
// FLOAT clearColor[] = { 0.0f, 0.2f, 0.4f, 1.0f };
// pCommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
// Set vertex and index buffers
// pCommandList->IASetVertexBuffers(0, 1, &vertexBufferView);
// pCommandList->IASetIndexBuffer(&indexBufferView);
// Issue draw calls
// pCommandList->DrawIndexedInstanced(indexCount, 1, 0, 0, 0);
// End recording
pCommandList->Close();
// Create an array of command lists to execute
ID3D12CommandList* ppCommandLists[] = { pCommandList };
// Submit command lists to the command queue
pCommandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
// ... proceed to present frame, sync with GPU using fences etc.