Command Lists
Command lists are a core feature of Direct3D 12 that enable applications to record GPU commands once and execute them multiple times. They improve CPU performance by reducing overhead associated with command submission.
Why Use Command Lists?
- Reduced CPU overhead: Record commands once and reuse.
- Parallel recording: Multiple threads can record separate command lists simultaneously.
- Better GPU utilization: Group related work into a single batch.
Creating a Command List
#include <d3d12.h>
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
ComPtr<ID3D12Device> device;
ComPtr<ID3D12CommandAllocator> allocator;
ComPtr<ID3D12GraphicsCommandList> commandList;
// Assume device is already created
device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&allocator));
device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator.Get(), nullptr, IID_PPV_ARGS(&commandList));
// Record commands...
commandList->Close();
Recording Commands
Once a command list is opened, you can record any GPU operation supported by Direct3D 12:
- Resource barriers.
- Render target setup.
- Draw and dispatch calls.
- Copy operations.
Executing a Command List
ComPtr<ID3D12CommandQueue> commandQueue;
// Assume commandQueue is already created
ID3D12CommandList* ppCommandLists[] = { commandList.Get() };
commandQueue->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
Command List Lifecycle
| State | Description |
|---|---|
| Open | Ready to record commands. |
| Closed | Finished recording, ready for execution. |
| Reset | Returns to the Open state using a command allocator. |
Best Practices
- Reuse command allocators: Reset them after GPU execution.
- Group related work: Keep a command list focused on a single logical task.
- Use multiple command lists for multithreaded recording.
- Avoid state changes inside a command list when possible.