Creating and Recording Command Lists and Bundles

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 4

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).

Creating command lists

o D3D12_COMMAND_LIST_TYPE

o ID3D12CommandAllocator

o ID3D12PipelineState

o ID3D12DescriptorHeap

Recording command lists

Example

Reference counting

Command list errors

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.

Creating command lists

Direct command lists and bundles are created by calling ID3D12Device::CreateCommandList.


This method takes the following parameters as input:

D3D12_COMMAND_LIST_TYPE

The D3D12_COMMAND_LIST_TYPE enumeration indicates the type of command list that is


being created. It can be a direct command list, a bundle, a compute command list, or a copy
command list.

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.

To reclaim the memory allocated by a command allocator, an app


calls ID3D12CommandAllocator::Reset. But before doing so, the app must make sure that the
GPU is no longer executing any command lists which are associated with the allocator;
otherwise, the call will fail. Also, note that this API is not free-threaded and therefore can't be
called on the same allocator at the same time from multiple threads.

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.

If this parameter is NULL, a default state is used.

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.

For more information, refer to Descriptor Heaps.


Recording command lists
Immediately after being created, command lists are in the recording state. You can also re-use
an existing command list by calling ID3D12GraphicsCommandList::Reset, which also leaves the
command list in the recording state. Unlike ID3D12CommandAllocator::Reset, you can
call Reset while the command list is still being executed. A typical pattern is to submit a
command list and then immediately reset it to reuse the allocated memory for another
command list. Note that only one command list associated with each command allocator may
be in a recording state at one time.

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.

Command list errors


Most APIs on ID3D12GraphicsCommandList do not return errors. Errors encountered during
command list creation are deferred until ID3D12GraphicsCommandList::Close. The one
exception is DXGI_ERROR_DEVICE_REMOVED, which is deferred even further. Note that this is
different from D3D11, where many parameter validation errors are silently dropped and never
returned to the caller.

Applications can expect to see DXGI_DEVICE_REMOVED errors in the following API calls:

Any resource creation method

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:

Any Clear method

Any Copy method

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

You might also like