Creating and Recording Command Lists and Bundles
Creating and Recording Command Lists and Bundles
Creating and Recording Command Lists and Bundles
This topic describes recording command lists and bundles in Direct3D 12 apps. Command lists
and bundles both allow apps to record drawing or state-changing calls for later execution on
the graphics processing unit (GPU).
o D3D12_COMMAND_LIST_TYPE
o ID3D12CommandAllocator
o ID3D12PipelineState
o ID3D12DescriptorHeap
Example
Reference counting
Bundle restrictions
Related topics
Beyond command lists, the API exploits functionality present in GPU hardware by adding a
second level of command lists, which are referred to as bundles. The purpose of bundles is to
allow apps to group a small number of API commands together for later execution. At bundle
creation time, the driver will perform as much pre-processing as is possible to make these
cheap to execute later. Bundles are designed to be used and re-used any number of times.
Command lists, on the other hand, are typically executed only a single time. However, a
command list can be executed multiple times (as long as the application ensures that the
previous executions have completed before submitting new executions).
Typically though, the build up of API calls into bundles, and API calls and bundles into
command lists, and command lists into a single frame, is shown in the following diagram,
noting the reuse of Bundle 1 inCommand list 1 and Command list 2, and that the API method
names in the diagram are just as examples, many different API calls can be used.
There are different restrictions for creating and executing bundles and direct command lists,
and these differences are noted throughout this topic.
D3D12_COMMAND_LIST_TYPE
ID3D12CommandAllocator
A command allocator allows the app to manage the memory that is allocated for command
lists. The command allocator is created by calling CreateCommandAllocator. When creating a
command list, the command list type of the allocator, specified
by D3D12_COMMAND_LIST_TYPE, must match the type of command list being created. A
given allocator can be associated with no more than one currently recording command list at a
time, though one command allocator can be used to create any number
of GraphicsCommandList objects.
ID3D12PipelineState
The initial pipeline state for the command list. In Microsoft Direct3D 12, most graphics pipeline
state is set within a command list using the ID3D12PipelineState object. An app will create a
large number of these, typically during app initialization, and then the state is updated by
changing the currently bound state object
using ID3D12GraphicsCommandList::SetPipelineState. For more information about pipeline
state objects, see Managing graphics pipeline state in Direct3D 12.
Note that bundles don't inherit the pipeline state set by previous calls in direct command lists
that are their parents.
ID3D12DescriptorHeap
The ID3D12DescriptorHeap allows command lists to bind resources to the graphics pipeline.
Direct command lists must specify an initial descriptor heap, but may change the currently-
bound descriptor heap inside the command list by
calling ID3D12GraphicsCommandList::SetDescriptorHeap.
Specifying a descriptor heap at creation time is optional for bundles. If a descriptor heap is not
specified, however, the application is not allowed to set any descriptor tables within that
bundle. Either way, bundles are not permitted to change the descriptor heap within a bundle.
If a heap is specified for a bundle, it must match the currently bound heap in the direct
command list that is the calling parent.
Once a command list is in the recording state, you simply call methods of
the ID3D12GraphicsCommandList interface to add commands to the list. Many of these
methods enable common Direct3D functionality that will be familiar to Microsoft Direct3D 11
developers; other APIs are new for Direct3D 12.
After adding commands to the command list, you transition the command list out of the
recording state by calling Close.
Example
The following code snippets illustrate the creation and recording of a command list. Note that
this example includes the following Direct3D 12 features:
Pipeline state objects - These are used to set most of the state parameters of the
render pipeline from within a command list. For more information, see Managing
graphics pipeline state in Direct3D 12.
Descriptor heap - Apps use descriptor heaps to manage pipeline binding to memory
resources.
Resource barrier - This is used to manage the transition of resources from one state to
another, such as from a render target view to a shader resource view. For more
information, see Using resource barriers to synchronize resource states.
For example,
After a command list has been created and recorded, it can be executed using a command
queue. For more information, see Executing and synchronizing command lists.
Reference counting
Most D3D12 APIs continue to use reference counting following COM conventions. A notable
exception to this is the D3D12 graphics command list APIs. All APIs
on ID3D12GraphicsCommandList do not hold references to the objects passed into those APIs.
This means applications are responsible for ensuring that a command list is never submitted
for execution that references a destroyed resource.
Applications can expect to see DXGI_DEVICE_REMOVED errors in the following API calls:
ID3D12Resource::Map
IDXGISwapChain1::Present1
GetDeviceRemovedReason
Bundle restrictions
Restrictions enable Direct3D 12 drivers to do most of the work associated with bundles at
record time, thus enabling the ExecuteBundle API to be run with low overhead. All pipeline
state objects referenced by a bundle must have the same render target formats, depth buffer
format, and sample descriptions.
The following command list API calls are not allowed on command lists created with type:
D3D12_COMMAND_LIST_TYPE_BUNDLE:
DiscardResource
ExecuteBundle
ResourceBarrier
ResolveSubresource
SetPredication
BeginQuery
EndQuery
SOSetTargets
OMSetRenderTargets
RSSetViewports
RSSetScissorRects
SetDescriptorHeaps can be called on a bundle, but the bundle descriptor heaps must match
the calling command list descriptor heap.
If any of these APIs are called on a bundle, the runtime will drop the call. The debug layer will
issue an error whenever this occurs.
Related topics