-
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 23 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,151 @@ 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 data defines the shader's resource interface with Direct3D 12, | ||||||||||||||||
specifying what resources the shader needs to access and how they're organized | ||||||||||||||||
and bound to the pipeline. | ||||||||||||||||
|
||||||||||||||||
The RTS0 part comprises three data structures: ``RootSignatureHeader``, | ||||||||||||||||
``RootParameters`` and ``StaticSamplers``. The details of each will be described | ||||||||||||||||
in the following sections. All ``RootParameters`` will be serialized following the | ||||||||||||||||
order they were defined in the metadata representation. | ||||||||||||||||
|
||||||||||||||||
Root Signature Header | ||||||||||||||||
~~~~~~~~~~~~~~~~~~~~~ | ||||||||||||||||
|
||||||||||||||||
The root signature header is 24 bytes long, consisting of six 32 bit values | ||||||||||||||||
representing the version, number and offset of parameters, number and offset | ||||||||||||||||
of static samplers, and a flags field for global behaviours: | ||||||||||||||||
|
||||||||||||||||
.. code-block:: c | ||||||||||||||||
|
||||||||||||||||
struct RootSignatureHeader { | ||||||||||||||||
uint32_t Version; | ||||||||||||||||
uint32_t NumParameters; | ||||||||||||||||
uint32_t ParametersOffset; | ||||||||||||||||
uint32_t NumStaticSamplers; | ||||||||||||||||
uint32_t StaticSamplerOffset; | ||||||||||||||||
uint32_t Flags; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
|
||||||||||||||||
Root Parameters | ||||||||||||||||
~~~~~~~~~~~~~~~ | ||||||||||||||||
Root parameters define how resources are bound to the shader pipeline, each | ||||||||||||||||
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. nit:
Suggested change
|
||||||||||||||||
type having different size and fields. | ||||||||||||||||
|
||||||||||||||||
Each slot of root parameters is preceded by 12 bytes, three 32 bit values, | ||||||||||||||||
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
|
||||||||||||||||
representing the parameter type, a flag encoding the pipeline stages where | ||||||||||||||||
the data is visible, and an offset calculated from the start of RTS0 section. | ||||||||||||||||
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. Is this saying that each root parameter starts with this header, and the parameters are laid out one after the other, or are the headers contiguous and then index into a single blob of data for all of the parameters? The description here sounds like the former, but I suspect the format actually works like the latter, otherwise having the offset field here wouldn't make much sense. 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. Checking DXC source code, I am not 100% sure how this is layout, because the logic used to calculate the Offset is confusing, but my understanding is headers are contiguous and then index into a single blob of data for all the parameters. At least that is how the data appears to be read in DXC. I will update the text to reflect this. |
||||||||||||||||
|
||||||||||||||||
.. code-block:: c | ||||||||||||||||
|
||||||||||||||||
struct RootParameterHeader { | ||||||||||||||||
uint32_t ParameterType; | ||||||||||||||||
uint32_t ShaderVisibility; | ||||||||||||||||
uint32_t ParameterOffset; | ||||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
The following sections will describe each of the root parameters types and their encodings. | ||||||||||||||||
|
||||||||||||||||
Root Constants | ||||||||||||||||
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. If you deem worthwhile, we could add the parameter type enum value. Something like:
Suggested change
|
||||||||||||||||
'''''''''''''' | ||||||||||||||||
|
||||||||||||||||
Root constants are values passed directly to shaders without needing a constant | ||||||||||||||||
buffer. It is a 12 bytes long structure, two 32 bit values encoding the register | ||||||||||||||||
and space the constant is assigned to, and one 32 bit value encoding the constant value. | ||||||||||||||||
|
||||||||||||||||
.. code-block:: c | ||||||||||||||||
|
||||||||||||||||
struct RootConstants { | ||||||||||||||||
uint32_t Register; | ||||||||||||||||
uint32_t Space; | ||||||||||||||||
uint32_t Value; | ||||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
Root Descriptor | ||||||||||||||||
''''''''''''''' | ||||||||||||||||
|
||||||||||||||||
Root descriptors provide direct GPU memory addresses to resources. Version 1.1 of | ||||||||||||||||
root descriptor is a 12 byte long, the first two 32 bit values encode the register | ||||||||||||||||
and space being assigned to the descriptor, and the last 32 bit value is an access flag flag. | ||||||||||||||||
|
||||||||||||||||
Version 1.0 doesn't contain the flags available in version 1.1. | ||||||||||||||||
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. Now that I see how this reads I think describing these additively might be better after all. Maybe something like:
If this makes sense to you, similar handling in the root descriptor table section should work too. 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. Remove - this sentence is redundant with the above at this point 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. Looks like you didn't have a chance to address this one yet. 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. Sorry, thought this was gone in the latest pr, address it in the most recent changes |
||||||||||||||||
|
||||||||||||||||
.. code-block:: c | ||||||||||||||||
|
||||||||||||||||
struct RootDescriptor_V1_0 { | ||||||||||||||||
uint32_t ShaderRegister; | ||||||||||||||||
uint32_t RegisterSpace; | ||||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
struct RootDescriptor_V1_1 { | ||||||||||||||||
uint32_t ShaderRegister; | ||||||||||||||||
uint32_t RegisterSpace; | ||||||||||||||||
uint32_t Flags; | ||||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
Root Descriptor Table | ||||||||||||||||
''''''''''''''''''''' | ||||||||||||||||
Descriptor tables let shaders access multiple resources through a single pointer to a descriptor heap. | ||||||||||||||||
|
||||||||||||||||
The tables are made of a collection of descriptor ranges. Version 1.1 ranges are 24 bytes long, containing | ||||||||||||||||
five 32 bit values: The type of register, the number of registers in the range, the starting register number, | ||||||||||||||||
the register space, an offset in number of descriptors from the start of the table and finally an access flag. | ||||||||||||||||
|
||||||||||||||||
Version 1.0 ranges are the 20 bytes long, following the same structure without the flags. | ||||||||||||||||
|
||||||||||||||||
.. code-block:: c | ||||||||||||||||
|
||||||||||||||||
struct DescriptorRange_V1_0 { | ||||||||||||||||
uint_32t 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; | ||||||||||||||||
// Bitfield of flags from the Flags enum | ||||||||||||||||
uint32_t Flags; | ||||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
Static Samplers | ||||||||||||||||
~~~~~~~~~~~~~~~ | ||||||||||||||||
|
||||||||||||||||
Static samplers are predefined filtering settings built into the root signature, avoiding descriptor heap lookups. | ||||||||||||||||
|
||||||||||||||||
This section also has a variable size. The size is 68 bytes long, containing the following fields: 32 bits for a | ||||||||||||||||
filter mode, three 32 bit fields for texture address mode, 64 bits for the bias value of minmap level calculation, | ||||||||||||||||
32 bits for maximum anisotropy level, 32 bits for the comparison function type, 32 bits for the static border colour, | ||||||||||||||||
two 64 bit fields for the min and max level of detail, two 32 bit fields for the register number and space and finally | ||||||||||||||||
32 bits for the shader visibility flag. | ||||||||||||||||
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 doesn't look quite right:
I also think describing each field in a paragraph like this gets a bit muddled. It might be better to simply say that the structure consists of 13 32-byte fields (as it appears to, assuming the 64-bit mentions in the text above are mistakes) of various enum, float, and integer values and let the names of the fields in the code block speak for themselves. |
||||||||||||||||
|
||||||||||||||||
.. code-block:: c | ||||||||||||||||
|
||||||||||||||||
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 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.