-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[DirectX] Documenting Root Signature Binary representation #131011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 20 commits
e26ef18
4f3930a
8fae269
7ad5d2b
93116c0
e1d385a
b390cd2
46face1
6a260b3
82a7de3
b591fd8
583e29c
16e3642
3da10bd
73c645d
fcabc0e
b13609d
4525033
15babc8
5303de8
8dc983a
b013080
0bcfa6b
787c920
351e6bb
32fd3de
7dcad52
a9260e5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -111,7 +111,7 @@ FXC are marked with \*. | |||
#. `PSV0`_ - Stores Pipeline State Validation data. | ||||
#. RDAT† - Stores Runtime Data. | ||||
#. RDEF\* - Stores resource definitions. | ||||
#. RTS0 - Stores compiled root signature. | ||||
#. `RTS0`_ - Stores compiled root signature. | ||||
#. `SFI0`_ - Stores shader feature flags. | ||||
#. SHDR\* - Stores compiled DXBC bytecode. | ||||
#. SHEX\* - Stores compiled DXBC bytecode. | ||||
|
@@ -400,3 +400,258 @@ SFI0 Part | |||
The SFI0 part encodes a 64-bit unsigned integer bitmask of the feature flags. | ||||
This denotes which optional features the shader requires. The flag values are | ||||
defined in `llvm/include/llvm/BinaryFormat/DXContainerConstants.def <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/DXContainerConstants.def>`_. | ||||
|
||||
Root Signature (RTS0) Part | ||||
-------------------------- | ||||
.. _RTS0: | ||||
|
||||
The Root Signature defines the interface between the shader and the pipeline, | ||||
specifying which resources are bound to the shader and how they are accessed. | ||||
This structure serves as a contract between the application and the GPU, | ||||
establishing a layout for resource binding that both the shader compiler and | ||||
the runtime can understand. | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These two sentences feel very redundant with one another, and neither really has a lot of content. The first says this defines an interface and the second literally defines what an interface is. Something like "The root signature part describes how resources are bound to the shader pipeline" is both more direct and clearer. |
||||
|
||||
The Root Signature consists of a header followed by a collection of root parameters | ||||
and static samplers. The structure uses a versioned design with offset-based references | ||||
joaosaffran marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
to allow for flexible serialization and deserialization. | ||||
|
||||
Root Signature Header | ||||
~~~~~~~~~~~~~~~~~~~~~ | ||||
|
||||
.. code-block:: c | ||||
|
||||
struct RootSignatureHeader { | ||||
uint32_t Version; | ||||
uint32_t NumParameters; | ||||
uint32_t ParametersOffset; | ||||
uint32_t NumStaticSamplers; | ||||
uint32_t StaticSamplerOffset; | ||||
uint32_t Flags; | ||||
} | ||||
|
||||
|
||||
The `RootSignatureHeader` structure contains the top-level information about a root signature: | ||||
|
||||
#. **Version**: Specifies the version of the root signature format. This allows for backward | ||||
compatibility as the format evolves. | ||||
#. **NumParameters**: The number of root parameters contained in this root signature. | ||||
#. **ParametersOffset**: Byte offset from the beginning of RST0 section to the array of root | ||||
parameters header. | ||||
#. **NumStaticSamplers**: The number of static samplers defined in the root signature. | ||||
#. **StaticSamplerOffset**: Byte offset to the array of static samplers. | ||||
#. **Flags**: Bit flags that define global behaviors for the root signature, such as whether | ||||
to deny vertex shader access to certain resources. | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's probably fine, but I wonder if showing an example C structure followed by the list of fields is overly verbose here. What do you think of simply describing the header in a sentence and then illustrating with a C struct, like
|
||||
|
||||
This header allows readers to navigate the binary representation of the root signature by | ||||
providing counts and offsets to locate each component within the serialized data. | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is just defining a header - I don't think it's necessary |
||||
|
||||
Root Parameter Header | ||||
inbelic marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
~~~~~~~~~~~~~~~~~~~~~ | ||||
|
||||
.. code-block:: c | ||||
|
||||
struct RootParameterHeader { | ||||
dxbc::RootParameterType ParameterType; | ||||
dxbc::ShaderVisibility ShaderVisibility; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're describing a binary format, not C. An enum in C does not necessarily map to 32 bits, so we should really be explicit about the size of the data here. This is a 32-bit value describing the parameter type (from a binary format point of view), not an enum of type RootParameterType. Also, as above, I think having a description of what the values in a root paramter header are before we bother showing the example C struct would make this easier to follow. |
||||
uint32_t ParameterOffset; | ||||
}; | ||||
|
||||
|
||||
Each root parameter in the signature is preceded by a `RootParameterHeader` that describes | ||||
the parameter's basic attributes: | ||||
|
||||
#. **ParameterType**: Enumeration indicating what type of parameter this is (e.g., descriptor | ||||
table, constants, CBV, SRV, UAV). | ||||
#. **ShaderVisibility**: Specifies which shader stages can access this parameter (e.g., all stages, | ||||
vertex shader only, pixel shader only). | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be helpful to explain the full set of parameter types and possible visibilities in the top level description of root parameters. Then this can simply refer back to that and say we describe the parameter type and visibility and we don't need the "e.g." for each of these. |
||||
#. **ParameterOffset**: Byte offset to the specific parameter data structure | ||||
for this entry. | ||||
|
||||
The header uses a parameter type field rather than encoding the version of the parameter through | ||||
size, allowing for a more explicit representation of the parameter's nature. | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have no idea what this sentence means. |
||||
|
||||
Root Parameters | ||||
~~~~~~~~~~~~~~~ | ||||
|
||||
The Root Parameters section contains structured definitions for each type of root parameter that can | ||||
be included in a root signature. Each structure corresponds to a specific parameter type as identified | ||||
by the ``ParameterType`` field in the ``RootParameterHeader``. | ||||
|
||||
Root Constants | ||||
~~~~~~~~~~~~~~ | ||||
|
||||
.. code-block:: cpp | ||||
|
||||
struct RootConstants { | ||||
uint32_t ShaderRegister; | ||||
uint32_t RegisterSpace; | ||||
uint32_t Num32BitValues; | ||||
}; | ||||
|
||||
The ``RootConstants`` structure represents inline root constants that are directly embedded in the root | ||||
signature and passed to the shader without requiring a constant buffer resource: | ||||
|
||||
#. **ShaderRegister**: The shader register (b#) where these constants are bound. | ||||
#. **RegisterSpace**: The register space used for the binding. | ||||
#. **Num32BitValues**: The number of 32-bit values included in this constant buffer. | ||||
|
||||
Root constants provide a fast way to pass small amounts of data directly to the shader without the | ||||
overhead of creating and binding a constant buffer resource. | ||||
|
||||
Root Descriptor | ||||
~~~~~~~~~~~~~~~ | ||||
|
||||
Root descriptors provide a mechanism for binding individual resources to shader stages in the Direct3D 12 | ||||
rendering pipeline. They allow applications to specify how shader stages access specific GPU resources. | ||||
|
||||
.. code-block:: cpp | ||||
|
||||
enum RootDescriptorFlags { | ||||
None = 0, | ||||
DataVolatile = 0x2, | ||||
DataStaticWhileSetAtExecute = 0x4, | ||||
DataStatic = 0x8, | ||||
} | ||||
|
||||
// Version 1.0 Root Descriptor | ||||
struct RootDescriptor_V1_0 { | ||||
uint32_t ShaderRegister; | ||||
uint32_t RegisterSpace; | ||||
}; | ||||
|
||||
// Version 1.1 Root Descriptor | ||||
struct RootDescriptor_V1_1 { | ||||
uint32_t ShaderRegister; | ||||
uint32_t RegisterSpace; | ||||
// Bitfield of flags from the Flags enum | ||||
uint32_t Flags; | ||||
}; | ||||
|
||||
Version 1.1 of Root Descriptors has introduced some flags that can hint the drivers into | ||||
performing further code optimizations. For details, check | ||||
`Direct X documentation <https://learn.microsoft.com/en-us/windows/win32/direct3d12/root-signature-version-1-1#static-and-volatile-flags>`_. | ||||
|
||||
Version 1.0 Root Descriptor | ||||
''''''''''''''''''''''''''' | ||||
The Version 1.0 RootDescriptor_V1_0 provides basic resource binding: | ||||
|
||||
#. **ShaderRegister**: The shader register where the descriptor is bound. | ||||
#. **RegisterSpace**: The register space used for the binding. | ||||
|
||||
Version 1.1 Root Descriptor | ||||
''''''''''''''''''''''''''' | ||||
The Version 1.1 RootDescriptor_V1_1 extends the base structure with the following additional fields: | ||||
|
||||
#. **Flags**: Provides additional metadata about the descriptor's usage pattern. | ||||
|
||||
Root Descriptor Table | ||||
~~~~~~~~~~~~~~~~~~~~~ | ||||
|
||||
Descriptor tables function as containers that hold references to descriptors in descriptor heaps. | ||||
inbelic marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
They allow multiple descriptors to be bound to the pipeline through a single root signature parameter. | ||||
|
||||
.. code-block:: cpp | ||||
|
||||
struct DescriptorRange_V1_0 { | ||||
dxbc::DescriptorRangeType RangeType; | ||||
uint32_t NumDescriptors; | ||||
uint32_t BaseShaderRegister; | ||||
uint32_t RegisterSpace; | ||||
uint32_t OffsetInDescriptorsFromTableStart; | ||||
}; | ||||
|
||||
struct DescriptorRange_V1_1 { | ||||
dxbc::DescriptorRangeType RangeType; | ||||
uint32_t NumDescriptors; | ||||
uint32_t BaseShaderRegister; | ||||
uint32_t RegisterSpace; | ||||
uint32_t OffsetInDescriptorsFromTableStart; | ||||
// New flags for Version 1.1 | ||||
enum Flags { | ||||
None = 0x0, | ||||
// Descriptors are static and known at root signature creation | ||||
DESCRIPTORS_STATIC = 0x1, | ||||
// Descriptors remain constant during command list execution | ||||
DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS = 0x2, | ||||
// Descriptors may change frequently | ||||
DESCRIPTORS_VOLATILE = 0x4 | ||||
}; | ||||
|
||||
// Bitfield of flags from the Flags enum | ||||
uint32_t Flags; | ||||
}; | ||||
|
||||
struct RootDescriptorTable { | ||||
uint32_t NumDescriptorRanges; | ||||
uint32_t DescriptorRangesOffset; | ||||
}; | ||||
|
||||
|
||||
Descriptor Range Version 1.0 | ||||
'''''''''''''''''''''''''''' | ||||
The Version 1.0 ``DescriptorRange_V1_0`` provides basic descriptor range definition: | ||||
|
||||
#. **RangeType**: Type of descriptors (CBV, SRV, UAV, or Sampler) | ||||
#. **NumDescriptors**: Number of descriptors in the range | ||||
#. **BaseShaderRegister**: First shader register in the range | ||||
#. **RegisterSpace**: Register space for the range | ||||
#. **OffsetInDescriptorsFromTableStart**: Offset from the descriptor heap start | ||||
|
||||
Descriptor Range Version 1.1 | ||||
'''''''''''''''''''''''''''' | ||||
The Version 1.1 DescriptorRange_V1_1 extends the base structure with performance optimization flags. | ||||
|
||||
#. **Flags**: Provide additional information about the descriptors and enable further driver optimizations. | ||||
For details, check `Direct X documentation <https://learn.microsoft.com/en-us/windows/win32/direct3d12/root-signature-version-1-1#static-and-volatile-flags>`_. | ||||
|
||||
Root Descriptor Table | ||||
''''''''''''''''''''' | ||||
RootDescriptorTable provides basic table structure: | ||||
joaosaffran marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
|
||||
#. **NumDescriptorRanges**: Number of descriptor ranges | ||||
#. **DescriptorRangesOffset**: Offset to descriptor range array | ||||
joaosaffran marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
|
||||
Static Samplers | ||||
~~~~~~~~~~~~~~~ | ||||
|
||||
Static samplers provide a way to define fixed sampler states within the root signature itself. | ||||
|
||||
.. code-block:: cpp | ||||
|
||||
struct StaticSamplerDesc { | ||||
FilterMode Filter; | ||||
TextureAddressMode AddressU; | ||||
TextureAddressMode AddressV; | ||||
TextureAddressMode AddressW; | ||||
float MipLODBias; | ||||
uint32_t MaxAnisotropy; | ||||
ComparisonFunc ComparisonFunc; | ||||
StaticBorderColor BorderColor; | ||||
float MinLOD; | ||||
float MaxLOD; | ||||
uint32_t ShaderRegister; | ||||
uint32_t RegisterSpace; | ||||
ShaderVisibility ShaderVisibility; | ||||
}; | ||||
|
||||
|
||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
The StaticSamplerDesc structure defines all properties of a static sampler: | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think it would make sense to remove all of these lines and instead just link to the top of the https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_static_sampler_desc page? Although, that link could break one day. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The intention here is to document the binary representation of root signatures inside dxcontainer, one of such parts is static samplers. Although, DX12 representation and the compiler representation are the same, that might not be the case in the future. For example, if we decide to change this representation or if DX12 decide to change theirs representation. Therefore, I think this duplication might be okay IMHO. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does that mean that this struct will be defined in .../BinaryFormat/DXContainer.h ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. DXC has similar structs as well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This references a lot of types that aren't defined in this document. As a description of a binary format it really needs to discuss the sizes and layout of things more so than what the things are for. |
||||
|
||||
#. Filter: The filtering mode (e.g., point, linear, anisotropic) used for texture sampling. | ||||
For details, check `Static Sampler Fileters definition. <https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_filter#syntax>`_. | ||||
#. AddressU: The addressing mode for the U texture coordinate. | ||||
For details, check `Texture address mode definition. <https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode>`_. | ||||
#. AddressV: The addressing mode for the V texture coordinate. | ||||
#. AddressW: The addressing mode for the W texture coordinate. | ||||
#. MipLODBias: Bias value applied to mipmap level of detail calculations. | ||||
#. MaxAnisotropy: Maximum anisotropy level when using anisotropic filtering. | ||||
#. ComparisonFunc: Comparison function used for comparison samplers. | ||||
For details, check `Comparison Function definition. <https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_comparison_func>`_. | ||||
#. BorderColor: Predefined border color used when address mode is set to border. | ||||
For details, check `Static border color <https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_static_border_color>`_. | ||||
#. MinLOD: Minimum level of detail to use for sampling. | ||||
#. MaxLOD: Maximum level of detail to use for sampling. | ||||
#. ShaderRegister: The shader sampler register (s#) where this sampler is bound. | ||||
#. RegisterSpace: The register space used for the binding. | ||||
#. ShaderVisibility: Specifies which shader stages can access this sampler. | ||||
For details, check `Sahder Visibility definition. <https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shader_visibility>`_. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's odd that the order here doesn't match the order of the sections later. Probably makes sense to insert the new content right before the SFI0 section rather than right after.