A new concept in Direct3D 12 is the descriptor. Descriptor management involves the following:
Descriptor heap
The descriptors are managed by an ID3D12DescriptorHeap
. A descriptor heap has a number of slots of a certain type. In addition, there is a difference between whether or not the descriptor heap is shader visible.
Descriptors are very similar in nature to resource views in Direct3D 11, although descriptors are slightly more flexible. Whereas a resource view in Direct3D 11 used to stand on its own, a descriptor can be allocated in an order determined by the programmer. This allows for a range of descriptors to be passed, setting multiple textures in a single call for example.
Root signature
In Direct3D 11, resources used to be bound to the device context. This has changed in Direct3D 12. All shader resources are now bound to an object known as the root signature. The root signature is a map indicating what types of descriptors are contained in what location, can easily be matched to a shader and will retain its bindings.
This concept can be used to reuse bindings at different moments in time without replicating the bindings individually. For instance, the root signature can have its bindings set at initialization, and never change. To set all bindings required by a certain pipeline, only the root signature needs to be set rather than every individual resource.
In addition, a root signature can describe descriptor ranges, which allow dynamic indexing of descriptors in shader visible descriptor heaps. This allows a shader to select a shader based on an index at runtime rather than selecting based on predefined texture slots. This simplifies code when it comes to binding resources, and allows cutting back on the amount of resources to be bound.
Root constants
A new concept in Direct3D 12 is the root constant. This can be a single 32-bit constant or array of 32-bit constants which can be read by the shader. This allows quick, low-overhead passing of indices and other small amounts of data. This can for instance be used to indicate a unique index indicating the current draw index, for indexing a constant buffer with matrix data, or indexing an array of textures.
Since resources are no longer automatically doing buffer renaming in the background, this is now the only way to specify data directly while recording the data.