Skip to content

[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

Merged
merged 28 commits into from
Mar 20, 2025
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e26ef18
Adding root constant documentation
joaosaffran Mar 3, 2025
4f3930a
Removing union, fix typos
joaosaffran Mar 3, 2025
8fae269
Wrapping text
joaosaffran Mar 3, 2025
7ad5d2b
Removing redundant byte offset reference
joaosaffran Mar 3, 2025
93116c0
Try fix test
joaosaffran Mar 3, 2025
e1d385a
Fix git error
joaosaffran Mar 3, 2025
b390cd2
Adding root descriptor subsection
joaosaffran Mar 4, 2025
46face1
Fix git error
joaosaffran Mar 4, 2025
6a260b3
Try fix test
joaosaffran Mar 4, 2025
82a7de3
Updating Root Descriptor documentation
joaosaffran Mar 4, 2025
b591fd8
Linking Direct X docs to details flags
joaosaffran Mar 4, 2025
583e29c
Detail RootDescriptorFlags enum
joaosaffran Mar 5, 2025
16e3642
Update DXContainer.rst
joaosaffran Mar 6, 2025
3da10bd
Addressing comments
joaosaffran Mar 11, 2025
73c645d
Addressing comments
joaosaffran Mar 11, 2025
fcabc0e
Address PR Comments
joaosaffran Mar 11, 2025
b13609d
Adding Static Sampler Documentation
joaosaffran Mar 12, 2025
4525033
Update DXContainer.rst
joaosaffran Mar 12, 2025
15babc8
Merge branch 'documentation/root-descriptors' into documentation/stat…
Mar 13, 2025
5303de8
make a single PR
Mar 13, 2025
8dc983a
Update DXContainer.rst
joaosaffran Mar 13, 2025
b013080
Update DXContainer.rst
joaosaffran Mar 14, 2025
0bcfa6b
Addressing comments
joaosaffran Mar 17, 2025
787c920
Addressing comments
joaosaffran Mar 19, 2025
351e6bb
Addressing some comments
joaosaffran Mar 19, 2025
32fd3de
Address PR Comments
joaosaffran Mar 19, 2025
7dcad52
Update DXContainer.rst
joaosaffran Mar 19, 2025
a9260e5
Update DXContainer.rst
joaosaffran Mar 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 182 additions & 1 deletion llvm/docs/DirectX/DXContainer.rst
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.
Comment on lines +114 to 115
Copy link
Contributor

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.

#. SHDR\* - Stores compiled DXBC bytecode.
#. SHEX\* - Stores compiled DXBC bytecode.
@@ -393,6 +393,187 @@ bit in the mask vector identifies one column of a patch constant input and a
column of an output. A value of 1 means the output is impacted by the primitive
input.

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this is applicable here, but there are limits to the size of the root signatureI, specified here. Not sure if that implies that there are limits to the size of this binary format?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That can be a future validation, since this is a limitation dx12 runtime. But currently, this is not something DXC checks when serializing root signatures.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the validator (dxv) catch root signatures that are over the limit? In any case, we should make sure we have an issue to add validation that we're not allowing root signatures that go over this limit.


The table below summarizes the data being serialized as well as it's size. The
details of it part will be discussed in further details on the next sections
of this document.

======================== =========================================== =============================
Part Name Size In Bytes Maximum number of Instances
======================== =========================================== =============================
Root Signature Header 24 1
Root Parameter Headers 12 Many
Root Parameter ================================ === Many
Root Constants 12
Root Descriptor Version 1.0 8
Root Descriptor Version 1.1 12
Descriptors Tables Version 1.0 20
Descriptors Tables Version 1.1 24
================================ ===

Static Samplers 52 Many
======================== =========================================== =============================


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
type having different size and fields.

The slot of root parameters is preceded by a variable size section containing
the header information for such parameters. Such structure is 12 bytes long,
composed of three 32 bit values, 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.

.. code-block:: c

struct RootParameterHeader {
uint32_t ParameterType;
uint32_t ShaderVisibility;
uint32_t ParameterOffset;
};

After the header information has been serialized, the actual data for each of the
root parameters is layout in a single continous blob. The parameters can be fetch
from such using the offset information, present in the header.

The following sections will describe each of the root parameters types and their
encodings.

Root Constants
Copy link
Contributor

Choose a reason for hiding this comment

The 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
Root Constants: ParameterType = 0u

''''''''''''''

The root constants are inline 32-bit values that show up in the shader
as 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
the last 32 bits encode the number of constants being defined in the buffer.

.. code-block:: c

struct RootConstants {
uint32_t Register;
uint32_t Space;
uint32_t NumOfConstants;
};

Root Descriptor
'''''''''''''''

Root descriptors provide direct GPU memory addresses to resources.

In version 1.0, the root descriptor is 8 bytes. It encodes the register and
space as 2 32-bit values.

In version 1.1, the root descriptor is 12 bytes. It matches the 1.0 descriptor
but adds a 32-bit access flag.

.. 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. In Version 1.0, the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The tables are made of a collection of descriptor ranges. In Version 1.0, the
The tables are made of an array of descriptor ranges. In Version 1.0, the

nit: imo array is less vague and implies they are contiguous

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @bogner, that using an array, imply that they have a fixed size, which is not the case for the binary representation.

descriptor range is 20 bytes, containing five 32 bit values. It encodes a range
of registers, including the register type, range length, register numbers and
space within range and the offset locating each range inside the table.

In version 1.1, the descriptor range is 24 bytes. It matches the 1.0 descriptor
but adds a 32-bit access flag.

.. code-block:: c

struct DescriptorRange_V1_0 {
uint32_t 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;
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, since it can contain multiple static
samplers definitions. However, the definition is a fixed sized struct,
containing 13 32-byte fields of various enum, float, and integer values.
Comment on lines +555 to +557
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see what you were saying here now.

Suggested change
This section also has a variable size, since it can contain multiple static
samplers definitions. However, the definition is a fixed sized struct,
containing 13 32-byte fields of various enum, float, and integer values.
This section consists of a variable number of static sampler definitions as
described in the root signature header. Each definition is 52 bytes made up of
13 32-byte fields of various enum, float, and integer values.


.. 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;
};

SFI0 Part
---------
.. _SFI0: