[clang] [Doc][HLSL] Add documentation for root signature. (PR #83933)
Xiang Li via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 5 10:43:59 PDT 2024
https://github.com/python3kgae updated https://github.com/llvm/llvm-project/pull/83933
>From b134854e7e183a1113ee6ae5c5f7b7910270c987 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Mon, 4 Mar 2024 16:39:41 -0800
Subject: [PATCH 01/19] [DOC][HLSL] Add documentation for root signature
This patch adds documentation for the root signature in HLSL.
For issue #55116
---
clang/docs/HLSL/RootSignature.rst | 210 ++++++++++++++++++++++++++++++
1 file changed, 210 insertions(+)
create mode 100644 clang/docs/HLSL/RootSignature.rst
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
new file mode 100644
index 00000000000000..c2f57340dc2730
--- /dev/null
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -0,0 +1,210 @@
+====================
+HLSL Root Signatures
+====================
+
+.. contents::
+ :local:
+
+Usage
+=====
+
+In HLSL, the `root signature
+<https://learn.microsoft.com/en-us/windows/win32/direct3d12/root-signatures>`_
+defines what types of resources are bound to the graphics pipeline.
+
+A root signature can be specified in HLSL as a `string
+<https://learn.microsoft.com/en-us/windows/win32/direct3d12/specifying-root-signatures-in-hlsl#an-example-hlsl-root-signature>`_.
+The string contains a collection of comma-separated clauses that describe root
+signature constituent components.
+
+There are two mechanisms to compile an HLSL root signature. First, it is
+possible to attach a root signature string to a particular shader via the
+RootSignature attribute (in the following example, using the MyRS1 entry
+point):
+
+.. code-block:: c++
+
+ [RootSignature(MyRS1)]
+ float4 main(float4 coord : COORD) : SV_Target
+ {
+ …
+ }
+
+The compiler will create and verify the root signature blob for the shader and
+embed it alongside the shader byte code into the shader blob.
+
+The other mechanism is to create a standalone root signature blob, perhaps to
+reuse it with a large set of shaders, saving space. The name of the define
+string is specified via the usual -E argument. For example:
+
+.. code-block:: c++
+ dxc.exe -T rootsig_1_1 MyRS1.hlsl -E MyRS1 -Fo MyRS1.fxo
+
+Note that the root signature string define can also be passed on the command
+line, e.g, -D MyRS1=”…”.
+
+Root Signature Grammar
+======================
+
+.. code-block:: c++
+
+ RootSignature : (RootElement(,RootElement)?)?
+
+ RootElement : RootFlags | RootConstants | RootCBV | RootSRV | RootUAV | DescriptorTable | StaticSampler
+
+ RootFlags : 'RootFlags' '(' (RootFlag(|RootFlag)?)? ')'
+
+ RootFlag : 'ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT' | 'DENY_VERTEX_SHADER_ROOT_ACCESS'
+
+ RootConstants : 'RootConstants' '(' 'num32BitConstants' '=' NUMBER ',' bReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
+
+ RootCBV : 'CBV' '(' bReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
+
+ RootSRV : 'SRV' '(' tReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
+
+ RootUAV : 'UAV' '(' uReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
+
+ DescriptorTable : 'DescriptorTable' '(' (DTClause(|DTClause)?)? (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
+
+ DTClause : CBV | SRV | UAV | Sampler
+
+ CBV : 'CBV' '(' bReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
+
+ SRV : 'SRV' '(' tReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
+
+ UAV : 'UAV' '(' uReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
+
+ Sampler : 'Sampler' '(' sReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' NUMBER)? ')'
+
+
+ SHADER_VISIBILITY : 'SHADER_VISIBILITY_ALL' | 'SHADER_VISIBILITY_VERTEX' | 'SHADER_VISIBILITY_HULL' | 'SHADER_VISIBILITY_DOMAIN' | 'SHADER_VISIBILITY_GEOMETRY' | 'SHADER_VISIBILITY_PIXEL' | 'SHADER_VISIBILITY_AMPLIFICATION' | 'SHADER_VISIBILITY_MESH'
+
+ DATA_FLAGS : 'DATA_STATIC_WHILE_SET_AT_EXECUTE' | 'DATA_VOLATILE'
+
+ DESCRIPTOR_RANGE_OFFSET : 'DESCRIPTOR_RANGE_OFFSET_APPEND' | NUMBER
+
+ StaticSampler : 'StaticSampler' '(' sReg (',' 'filter' '=' FILTER)? (',' 'addressU' '=' TEXTURE_ADDRESS)? (',' 'addressV' '=' TEXTURE_ADDRESS)? (',' 'addressW' '=' TEXTURE_ADDRESS)? (',' 'mipLODBias' '=' NUMBER)? (',' 'maxAnisotropy' '=' NUMBER)? (',' 'comparisonFunc' '=' COMPARISON_FUNC)? (',' 'borderColor' '=' STATIC_BORDER_COLOR)? (',' 'minLOD' '=' NUMBER)? (',' 'maxLOD' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
+
+ bReg : 'b' NUMBER
+
+ tReg : 't' NUMBER
+
+ uReg : 'u' NUMBER
+
+ sReg : 's' NUMBER
+
+ FILTER : 'FILTER_MIN_MAG_MIP_POINT' | 'FILTER_MIN_MAG_POINT_MIP_LINEAR' | 'FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT' | 'FILTER_MIN_POINT_MAG_MIP_LINEAR' | 'FILTER_MIN_LINEAR_MAG_MIP_POINT' | 'FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR' | 'FILTER_MIN_MAG_LINEAR_MIP_POINT' | 'FILTER_MIN_MAG_MIP_LINEAR' | 'FILTER_ANISOTROPIC' | 'FILTER_COMPARISON_MIN_MAG_MIP_POINT' | 'FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR' | 'FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT' | 'FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR' | 'FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT' | 'FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR' | 'FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT' | 'FILTER_COMPARISON_MIN_MAG_MIP_LINEAR' | 'FILTER_COMPARISON_ANISOTROPIC' | 'FILTER_MINIMUM_MIN_MAG_MIP_POINT' | 'FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR' | 'FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT' | 'FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR' | 'FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT' | 'FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR' | 'FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT' | 'FILTER_MINIMUM_MIN_MAG_MIP_LINEAR' | 'FILTER_MINIMUM_ANISOTROPIC' | 'FILTER_MAXIMUM_MIN_MAG_MIP_POINT' | 'FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR' | 'FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT' | 'FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR' | 'FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT' | 'FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR' | 'FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT' | 'FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR' | 'FILTER_MAXIMUM_ANISOTROPIC'
+
+ TEXTURE_ADDRESS : 'TEXTURE_ADDRESS_WRAP' | 'TEXTURE_ADDRESS_MIRROR' | 'TEXTURE_ADDRESS_CLAMP' | 'TEXTURE_ADDRESS_BORDER' | 'TEXTURE_ADDRESS_MIRROR_ONCE'
+
+ COMPARISON_FUNC : 'COMPARISON_NEVER' | 'COMPARISON_LESS' | 'COMPARISON_EQUAL' | 'COMPARISON_LESS_EQUAL' | 'COMPARISON_GREATER' | 'COMPARISON_NOT_EQUAL' | 'COMPARISON_GREATER_EQUAL' | 'COMPARISON_ALWAYS'
+
+ STATIC_BORDER_COLOR : 'STATIC_BORDER_COLOR_TRANSPARENT_BLACK' | 'STATIC_BORDER_COLOR_OPAQUE_BLACK' | 'STATIC_BORDER_COLOR_OPAQUE_WHITE'
+
+
+Serialized format
+======================
+The root signature string is parsed and serialized into a binary format. The
+binary format is a sequence of bytes that can be used to create a root signature
+object in the Direct3D 12 API. The binary format is defined by the
+`D3D12_ROOT_SIGNATURE_DESC (for rootsig_1_0)
+<https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_signature_desc>`_
+or `D3D12_ROOT_SIGNATURE_DESC1 (for rootsig_1_1)
+<https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_signature_desc1>`_
+structure in the Direct3D 12 API.
+
+
+
+Implementation Details
+======================
+
+The root signature string will be parsed in the HLSL frontend.
+The parsing
+will happened when build HLSLRootSignatureAttr or when build standalone root
+signature blob.
+
+The root signature parsing will generate a VersionedRootSignatureDesc object
+that represents the root signature string.
+VersionedRootSignatureDesc is a struct that contains a RootSignatureVersion
+and a RootSignatureDesc.
+
+.. code-block:: c++
+ struct DescriptorRange {
+ DescriptorRangeType RangeType;
+ uint32_t NumDescriptors = 1;
+ uint32_t BaseShaderRegister;
+ uint32_t RegisterSpace = 0;
+ DescriptorRangeFlags Flags = DescriptorRangeFlags::None;
+ uint32_t OffsetInDescriptorsFromTableStart = DescriptorRangeOffsetAppend;
+ };
+
+ struct RootDescriptorTable {
+ std::vector<DescriptorRange> DescriptorRanges;
+ };
+ struct RootConstants {
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace = 0;
+ uint32_t Num32BitValues;
+ };
+
+ struct RootDescriptor {
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace = 0;
+ RootDescriptorFlags Flags = RootDescriptorFlags::None;
+ };
+ struct RootParameter {
+ RootParameterType ParameterType;
+ std::variant<RootDescriptorTable, RootConstants, RootDescriptor>
+ Parameter;
+ ShaderVisibility ShaderVisibility = ShaderVisibility::All;
+ };
+
+ struct StaticSamplerDesc {
+ Filter Filter = Filter::ANISOTROPIC;
+ TextureAddressMode AddressU = TextureAddressMode::Wrap;
+ TextureAddressMode AddressV = TextureAddressMode::Wrap;
+ TextureAddressMode AddressW = TextureAddressMode::Wrap;
+ float MipLODBias = 0.f;
+ uint32_t MaxAnisotropy = 16;
+ ComparisonFunc ComparisonFunc = ComparisonFunc::LessEqual;
+ StaticBorderColor BorderColor = StaticBorderColor::OpaqueWhite;
+ float MinLOD = 0.f;
+ float MaxLOD = MaxLOD;
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace = 0;
+ ShaderVisibility ShaderVisibility = ShaderVisibility::All;
+ };
+
+ struct RootSignatureDesc {
+ std::vector<RootParameter> Parameters;
+ std::vector<StaticSamplerDesc> StaticSamplers;
+ RootSignatureFlags Flags;
+ };
+
+ struct VersionedRootSignatureDesc {
+ RootSignatureVersion Version;
+ RootSignatureDesc Desc;
+ };
+
+Things like DescriptorRangeType and RootDescriptorFlags will be enums.
+
+After parsing, the VersionedRootSignatureDesc will be translated into a
+constant global variable in the clang AST and save to the
+HLSLRootSignatureAttr.
+
+For case compile to a standalone root signature blob, the global variable will
+be saved in the ASTContext.
+
+The global variable in AST will have a struct type that represents the root signature
+layout and a initializer that contains the values like space and
+numDescriptors of the root signature.
+
+In clang code generation, the global variable in AST will be translated into a global
+variable with cosntant initializer in LLVM IR.
+
+CGHLSLRuntime will generate metadata to link the global variable as root
+signature for given entry function or just nullptr for the standalone root
+signature blob case.
+
+In LLVM DirectX backend, the global variable will be serialized and save into the root
+signature part of dx container when emit DXIL.
>From 47539f7ddfba55b9cfe3584710712e2ba88adf2a Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Mon, 4 Mar 2024 18:23:58 -0800
Subject: [PATCH 02/19] Fix format.
---
clang/docs/HLSL/RootSignature.rst | 101 ++++++++++++++++++++++++------
1 file changed, 82 insertions(+), 19 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index c2f57340dc2730..bf6037dea8ea34 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -38,6 +38,7 @@ reuse it with a large set of shaders, saving space. The name of the define
string is specified via the usual -E argument. For example:
.. code-block:: c++
+
dxc.exe -T rootsig_1_1 MyRS1.hlsl -E MyRS1 -Fo MyRS1.fxo
Note that the root signature string define can also be passed on the command
@@ -50,40 +51,59 @@ Root Signature Grammar
RootSignature : (RootElement(,RootElement)?)?
- RootElement : RootFlags | RootConstants | RootCBV | RootSRV | RootUAV | DescriptorTable | StaticSampler
+ RootElement : RootFlags | RootConstants | RootCBV | RootSRV | RootUAV |
+ DescriptorTable | StaticSampler
RootFlags : 'RootFlags' '(' (RootFlag(|RootFlag)?)? ')'
RootFlag : 'ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT' | 'DENY_VERTEX_SHADER_ROOT_ACCESS'
- RootConstants : 'RootConstants' '(' 'num32BitConstants' '=' NUMBER ',' bReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
+ RootConstants : 'RootConstants' '(' 'num32BitConstants' '=' NUMBER ','
+ bReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
- RootCBV : 'CBV' '(' bReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ RootCBV : 'CBV' '(' bReg (',' 'space' '=' NUMBER)?
+ (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
- RootSRV : 'SRV' '(' tReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ RootSRV : 'SRV' '(' tReg (',' 'space' '=' NUMBER)?
+ (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
- RootUAV : 'UAV' '(' uReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ RootUAV : 'UAV' '(' uReg (',' 'space' '=' NUMBER)?
+ (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
- DescriptorTable : 'DescriptorTable' '(' (DTClause(|DTClause)?)? (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
+ DescriptorTable : 'DescriptorTable' '(' (DTClause(|DTClause)?)?
+ (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
DTClause : CBV | SRV | UAV | Sampler
- CBV : 'CBV' '(' bReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ CBV : 'CBV' '(' bReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)?
+ (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
- SRV : 'SRV' '(' tReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ SRV : 'SRV' '(' tReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)?
+ (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
- UAV : 'UAV' '(' uReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ UAV : 'UAV' '(' uReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)?
+ (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
- Sampler : 'Sampler' '(' sReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' NUMBER)? ')'
+ Sampler : 'Sampler' '(' sReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)?
+ (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' NUMBER)? ')'
- SHADER_VISIBILITY : 'SHADER_VISIBILITY_ALL' | 'SHADER_VISIBILITY_VERTEX' | 'SHADER_VISIBILITY_HULL' | 'SHADER_VISIBILITY_DOMAIN' | 'SHADER_VISIBILITY_GEOMETRY' | 'SHADER_VISIBILITY_PIXEL' | 'SHADER_VISIBILITY_AMPLIFICATION' | 'SHADER_VISIBILITY_MESH'
+ SHADER_VISIBILITY : 'SHADER_VISIBILITY_ALL' | 'SHADER_VISIBILITY_VERTEX' |
+ 'SHADER_VISIBILITY_HULL' | 'SHADER_VISIBILITY_DOMAIN' |
+ 'SHADER_VISIBILITY_GEOMETRY' | 'SHADER_VISIBILITY_PIXEL' |
+ 'SHADER_VISIBILITY_AMPLIFICATION' | 'SHADER_VISIBILITY_MESH'
DATA_FLAGS : 'DATA_STATIC_WHILE_SET_AT_EXECUTE' | 'DATA_VOLATILE'
DESCRIPTOR_RANGE_OFFSET : 'DESCRIPTOR_RANGE_OFFSET_APPEND' | NUMBER
- StaticSampler : 'StaticSampler' '(' sReg (',' 'filter' '=' FILTER)? (',' 'addressU' '=' TEXTURE_ADDRESS)? (',' 'addressV' '=' TEXTURE_ADDRESS)? (',' 'addressW' '=' TEXTURE_ADDRESS)? (',' 'mipLODBias' '=' NUMBER)? (',' 'maxAnisotropy' '=' NUMBER)? (',' 'comparisonFunc' '=' COMPARISON_FUNC)? (',' 'borderColor' '=' STATIC_BORDER_COLOR)? (',' 'minLOD' '=' NUMBER)? (',' 'maxLOD' '=' NUMBER)? (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
+ StaticSampler : 'StaticSampler' '(' sReg (',' 'filter' '=' FILTER)?
+ (',' 'addressU' '=' TEXTURE_ADDRESS)? (',' 'addressV' '=' TEXTURE_ADDRESS)?
+ (',' 'addressW' '=' TEXTURE_ADDRESS)? (',' 'mipLODBias' '=' NUMBER)?
+ (',' 'maxAnisotropy' '=' NUMBER)? (',' 'comparisonFunc' '=' COMPARISON_FUNC)?
+ (',' 'borderColor' '=' STATIC_BORDER_COLOR)? (',' 'minLOD' '=' NUMBER)?
+ (',' 'maxLOD' '=' NUMBER)? (',' 'space' '=' NUMBER)?
+ (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
bReg : 'b' NUMBER
@@ -93,13 +113,55 @@ Root Signature Grammar
sReg : 's' NUMBER
- FILTER : 'FILTER_MIN_MAG_MIP_POINT' | 'FILTER_MIN_MAG_POINT_MIP_LINEAR' | 'FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT' | 'FILTER_MIN_POINT_MAG_MIP_LINEAR' | 'FILTER_MIN_LINEAR_MAG_MIP_POINT' | 'FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR' | 'FILTER_MIN_MAG_LINEAR_MIP_POINT' | 'FILTER_MIN_MAG_MIP_LINEAR' | 'FILTER_ANISOTROPIC' | 'FILTER_COMPARISON_MIN_MAG_MIP_POINT' | 'FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR' | 'FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT' | 'FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR' | 'FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT' | 'FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR' | 'FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT' | 'FILTER_COMPARISON_MIN_MAG_MIP_LINEAR' | 'FILTER_COMPARISON_ANISOTROPIC' | 'FILTER_MINIMUM_MIN_MAG_MIP_POINT' | 'FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR' | 'FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT' | 'FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR' | 'FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT' | 'FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR' | 'FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT' | 'FILTER_MINIMUM_MIN_MAG_MIP_LINEAR' | 'FILTER_MINIMUM_ANISOTROPIC' | 'FILTER_MAXIMUM_MIN_MAG_MIP_POINT' | 'FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR' | 'FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT' | 'FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR' | 'FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT' | 'FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR' | 'FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT' | 'FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR' | 'FILTER_MAXIMUM_ANISOTROPIC'
-
- TEXTURE_ADDRESS : 'TEXTURE_ADDRESS_WRAP' | 'TEXTURE_ADDRESS_MIRROR' | 'TEXTURE_ADDRESS_CLAMP' | 'TEXTURE_ADDRESS_BORDER' | 'TEXTURE_ADDRESS_MIRROR_ONCE'
-
- COMPARISON_FUNC : 'COMPARISON_NEVER' | 'COMPARISON_LESS' | 'COMPARISON_EQUAL' | 'COMPARISON_LESS_EQUAL' | 'COMPARISON_GREATER' | 'COMPARISON_NOT_EQUAL' | 'COMPARISON_GREATER_EQUAL' | 'COMPARISON_ALWAYS'
-
- STATIC_BORDER_COLOR : 'STATIC_BORDER_COLOR_TRANSPARENT_BLACK' | 'STATIC_BORDER_COLOR_OPAQUE_BLACK' | 'STATIC_BORDER_COLOR_OPAQUE_WHITE'
+ FILTER : 'FILTER_MIN_MAG_MIP_POINT' |
+ 'FILTER_MIN_MAG_POINT_MIP_LINEAR' |
+ 'FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT' |
+ 'FILTER_MIN_POINT_MAG_MIP_LINEAR' |
+ 'FILTER_MIN_LINEAR_MAG_MIP_POINT' |
+ 'FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR' |
+ 'FILTER_MIN_MAG_LINEAR_MIP_POINT' |
+ 'FILTER_MIN_MAG_MIP_LINEAR' |
+ 'FILTER_ANISOTROPIC' |
+ 'FILTER_COMPARISON_MIN_MAG_MIP_POINT' |
+ 'FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR' |
+ 'FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT' |
+ 'FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR' |
+ 'FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT' |
+ 'FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR' |
+ 'FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT' |
+ 'FILTER_COMPARISON_MIN_MAG_MIP_LINEAR' |
+ 'FILTER_COMPARISON_ANISOTROPIC' |
+ 'FILTER_MINIMUM_MIN_MAG_MIP_POINT' |
+ 'FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR' |
+ 'FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT' |
+ 'FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR' |
+ 'FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT' |
+ 'FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR' |
+ 'FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT' |
+ 'FILTER_MINIMUM_MIN_MAG_MIP_LINEAR' |
+ 'FILTER_MINIMUM_ANISOTROPIC' |
+ 'FILTER_MAXIMUM_MIN_MAG_MIP_POINT' |
+ 'FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR' |
+ 'FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT' |
+ 'FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR' |
+ 'FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT' |
+ 'FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR' |
+ 'FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT' |
+ 'FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR' |
+ 'FILTER_MAXIMUM_ANISOTROPIC'
+
+ TEXTURE_ADDRESS : 'TEXTURE_ADDRESS_WRAP' |
+ 'TEXTURE_ADDRESS_MIRROR' | 'TEXTURE_ADDRESS_CLAMP' |
+ 'TEXTURE_ADDRESS_BORDER' | 'TEXTURE_ADDRESS_MIRROR_ONCE'
+
+ COMPARISON_FUNC : 'COMPARISON_NEVER' | 'COMPARISON_LESS' |
+ 'COMPARISON_EQUAL' | 'COMPARISON_LESS_EQUAL' |
+ 'COMPARISON_GREATER' | 'COMPARISON_NOT_EQUAL' |
+ 'COMPARISON_GREATER_EQUAL' | 'COMPARISON_ALWAYS'
+
+ STATIC_BORDER_COLOR : 'STATIC_BORDER_COLOR_TRANSPARENT_BLACK' |
+ 'STATIC_BORDER_COLOR_OPAQUE_BLACK' |
+ 'STATIC_BORDER_COLOR_OPAQUE_WHITE'
Serialized format
@@ -129,6 +191,7 @@ VersionedRootSignatureDesc is a struct that contains a RootSignatureVersion
and a RootSignatureDesc.
.. code-block:: c++
+
struct DescriptorRange {
DescriptorRangeType RangeType;
uint32_t NumDescriptors = 1;
>From b4cd39e536c4f33ddcb1b0405632f6a86dec7fa3 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Mon, 4 Mar 2024 18:29:51 -0800
Subject: [PATCH 03/19] More format fix.
---
clang/docs/HLSL/RootSignature.rst | 72 ++++++++++++++++++++-----------
1 file changed, 47 insertions(+), 25 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index bf6037dea8ea34..d6b4ddfb013b58 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -56,52 +56,71 @@ Root Signature Grammar
RootFlags : 'RootFlags' '(' (RootFlag(|RootFlag)?)? ')'
- RootFlag : 'ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT' | 'DENY_VERTEX_SHADER_ROOT_ACCESS'
+ RootFlag : 'ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT' |
+ 'DENY_VERTEX_SHADER_ROOT_ACCESS'
RootConstants : 'RootConstants' '(' 'num32BitConstants' '=' NUMBER ','
- bReg (',' 'space' '=' NUMBER)? (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
+ bReg (',' 'space' '=' NUMBER)?
+ (',' 'visibility' '=' SHADER_VISIBILITY)? ')'
RootCBV : 'CBV' '(' bReg (',' 'space' '=' NUMBER)?
- (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ (',' 'visibility' '=' SHADER_VISIBILITY)?
+ (',' 'flags' '=' DATA_FLAGS)? ')'
RootSRV : 'SRV' '(' tReg (',' 'space' '=' NUMBER)?
- (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ (',' 'visibility' '=' SHADER_VISIBILITY)?
+ (',' 'flags' '=' DATA_FLAGS)? ')'
RootUAV : 'UAV' '(' uReg (',' 'space' '=' NUMBER)?
- (',' 'visibility' '=' SHADER_VISIBILITY)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ (',' 'visibility' '=' SHADER_VISIBILITY)?
+ (',' 'flags' '=' DATA_FLAGS)? ')'
DescriptorTable : 'DescriptorTable' '(' (DTClause(|DTClause)?)?
(',' 'visibility' '=' SHADER_VISIBILITY)? ')'
DTClause : CBV | SRV | UAV | Sampler
- CBV : 'CBV' '(' bReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)?
- (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ CBV : 'CBV' '(' bReg (',' 'numDescriptors' '=' NUMBER)?
+ (',' 'space' '=' NUMBER)?
+ (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)?
+ (',' 'flags' '=' DATA_FLAGS)? ')'
- SRV : 'SRV' '(' tReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)?
- (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ SRV : 'SRV' '(' tReg (',' 'numDescriptors' '=' NUMBER)?
+ (',' 'space' '=' NUMBER)?
+ (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)?
+ (',' 'flags' '=' DATA_FLAGS)? ')'
- UAV : 'UAV' '(' uReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)?
- (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' DATA_FLAGS)? ')'
+ UAV : 'UAV' '(' uReg (',' 'numDescriptors' '=' NUMBER)?
+ (',' 'space' '=' NUMBER)?
+ (',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)?
+ (',' 'flags' '=' DATA_FLAGS)? ')'
- Sampler : 'Sampler' '(' sReg (',' 'numDescriptors' '=' NUMBER)? (',' 'space' '=' NUMBER)?
+ Sampler : 'Sampler' '(' sReg (',' 'numDescriptors' '=' NUMBER)?
+ (',' 'space' '=' NUMBER)?
(',' 'offset' '=' DESCRIPTOR_RANGE_OFFSET)? (',' 'flags' '=' NUMBER)? ')'
SHADER_VISIBILITY : 'SHADER_VISIBILITY_ALL' | 'SHADER_VISIBILITY_VERTEX' |
- 'SHADER_VISIBILITY_HULL' | 'SHADER_VISIBILITY_DOMAIN' |
- 'SHADER_VISIBILITY_GEOMETRY' | 'SHADER_VISIBILITY_PIXEL' |
- 'SHADER_VISIBILITY_AMPLIFICATION' | 'SHADER_VISIBILITY_MESH'
+ 'SHADER_VISIBILITY_HULL' |
+ 'SHADER_VISIBILITY_DOMAIN' |
+ 'SHADER_VISIBILITY_GEOMETRY' |
+ 'SHADER_VISIBILITY_PIXEL' |
+ 'SHADER_VISIBILITY_AMPLIFICATION' |
+ 'SHADER_VISIBILITY_MESH'
DATA_FLAGS : 'DATA_STATIC_WHILE_SET_AT_EXECUTE' | 'DATA_VOLATILE'
DESCRIPTOR_RANGE_OFFSET : 'DESCRIPTOR_RANGE_OFFSET_APPEND' | NUMBER
StaticSampler : 'StaticSampler' '(' sReg (',' 'filter' '=' FILTER)?
- (',' 'addressU' '=' TEXTURE_ADDRESS)? (',' 'addressV' '=' TEXTURE_ADDRESS)?
- (',' 'addressW' '=' TEXTURE_ADDRESS)? (',' 'mipLODBias' '=' NUMBER)?
- (',' 'maxAnisotropy' '=' NUMBER)? (',' 'comparisonFunc' '=' COMPARISON_FUNC)?
- (',' 'borderColor' '=' STATIC_BORDER_COLOR)? (',' 'minLOD' '=' NUMBER)?
+ (',' 'addressU' '=' TEXTURE_ADDRESS)?
+ (',' 'addressV' '=' TEXTURE_ADDRESS)?
+ (',' 'addressW' '=' TEXTURE_ADDRESS)?
+ (',' 'mipLODBias' '=' NUMBER)?
+ (',' 'maxAnisotropy' '=' NUMBER)?
+ (',' 'comparisonFunc' '=' COMPARISON_FUNC)?
+ (',' 'borderColor' '=' STATIC_BORDER_COLOR)?
+ (',' 'minLOD' '=' NUMBER)?
(',' 'maxLOD' '=' NUMBER)? (',' 'space' '=' NUMBER)?
(',' 'visibility' '=' SHADER_VISIBILITY)? ')'
@@ -258,16 +277,19 @@ HLSLRootSignatureAttr.
For case compile to a standalone root signature blob, the global variable will
be saved in the ASTContext.
-The global variable in AST will have a struct type that represents the root signature
-layout and a initializer that contains the values like space and
+The global variable in AST will have a struct type that represents the root
+signature layout and a initializer that contains the values like space and
numDescriptors of the root signature.
-In clang code generation, the global variable in AST will be translated into a global
-variable with cosntant initializer in LLVM IR.
+In clang code generation, the global variable in AST will be translated into
+a global variable with constant initializer in LLVM IR.
CGHLSLRuntime will generate metadata to link the global variable as root
signature for given entry function or just nullptr for the standalone root
signature blob case.
-In LLVM DirectX backend, the global variable will be serialized and save into the root
-signature part of dx container when emit DXIL.
+In LLVM DirectX backend, the global variable will be serialized and save into
+ the root signature part of dx container when emit DXIL.
+
+In DXIL validation, the root signature part will be deserialized and check if
+the resource binding in the root signature exists in the resource table.
>From f3504ff4e73ed9156ff5bb752dfcd5c6d4fa5e90 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Mon, 4 Mar 2024 18:37:29 -0800
Subject: [PATCH 04/19] Add example
---
clang/docs/HLSL/RootSignature.rst | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index d6b4ddfb013b58..c1a3e48fed4ddf 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -24,7 +24,24 @@ point):
.. code-block:: c++
- [RootSignature(MyRS1)]
+ #define RS "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
+ "DENY_VERTEX_SHADER_ROOT_ACCESS), " \
+ "CBV(b0, space = 1, flags = DATA_STATIC), " \
+ "SRV(t0), " \
+ "UAV(u0), " \
+ "DescriptorTable( CBV(b1), " \
+ " SRV(t1, numDescriptors = 8, " \
+ " flags = DESCRIPTORS_VOLATILE), " \
+ " UAV(u1, numDescriptors = unbounded, " \
+ " flags = DESCRIPTORS_VOLATILE)), " \
+ "DescriptorTable(Sampler(s0, space=1, numDescriptors = 4)), " \
+ "RootConstants(num32BitConstants=3, b10), " \
+ "StaticSampler(s1)," \
+ "StaticSampler(s2, " \
+ " addressU = TEXTURE_ADDRESS_CLAMP, " \
+ " filter = FILTER_MIN_MAG_MIP_LINEAR )"
+
+ [RootSignature(RS)]
float4 main(float4 coord : COORD) : SV_Target
{
…
>From 6c35d7308c310e725b1356a88317067fc5dab546 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Tue, 5 Mar 2024 12:45:11 -0800
Subject: [PATCH 05/19] Update per comment.
---
clang/docs/HLSL/RootSignature.rst | 98 +++++--------------------------
1 file changed, 16 insertions(+), 82 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index c1a3e48fed4ddf..8d894c50e51540 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -209,104 +209,38 @@ object in the Direct3D 12 API. The binary format is defined by the
<https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_signature_desc>`_
or `D3D12_ROOT_SIGNATURE_DESC1 (for rootsig_1_1)
<https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_signature_desc1>`_
-structure in the Direct3D 12 API.
-
+structure in the Direct3D 12 API. (With the pointers translated to offsets.)
+DXC implementation of the serialization could be find `here
+<https://github.com/microsoft/DirectXShaderCompiler/blob/main/lib/DxilRootSignature/DxilRootSignatureSerializer.cpp#L41>`_
Implementation Details
======================
-The root signature string will be parsed in the HLSL frontend.
+The root signature string will be parsed in Clang.
The parsing
will happened when build HLSLRootSignatureAttr or when build standalone root
signature blob.
-The root signature parsing will generate a VersionedRootSignatureDesc object
-that represents the root signature string.
-VersionedRootSignatureDesc is a struct that contains a RootSignatureVersion
-and a RootSignatureDesc.
+The root signature parsing will generate a HLSLRootSignatureAttr with member
+represents the root signature string and the parsed information for each
+resource in the root signature. It will bind to the entry function in the AST.
-.. code-block:: c++
+For case compile to a standalone root signature blob, the HLSLRootSignatureAttr
+will be bind to the TU.
- struct DescriptorRange {
- DescriptorRangeType RangeType;
- uint32_t NumDescriptors = 1;
- uint32_t BaseShaderRegister;
- uint32_t RegisterSpace = 0;
- DescriptorRangeFlags Flags = DescriptorRangeFlags::None;
- uint32_t OffsetInDescriptorsFromTableStart = DescriptorRangeOffsetAppend;
- };
-
- struct RootDescriptorTable {
- std::vector<DescriptorRange> DescriptorRanges;
- };
- struct RootConstants {
- uint32_t ShaderRegister;
- uint32_t RegisterSpace = 0;
- uint32_t Num32BitValues;
- };
-
- struct RootDescriptor {
- uint32_t ShaderRegister;
- uint32_t RegisterSpace = 0;
- RootDescriptorFlags Flags = RootDescriptorFlags::None;
- };
- struct RootParameter {
- RootParameterType ParameterType;
- std::variant<RootDescriptorTable, RootConstants, RootDescriptor>
- Parameter;
- ShaderVisibility ShaderVisibility = ShaderVisibility::All;
- };
-
- struct StaticSamplerDesc {
- Filter Filter = Filter::ANISOTROPIC;
- TextureAddressMode AddressU = TextureAddressMode::Wrap;
- TextureAddressMode AddressV = TextureAddressMode::Wrap;
- TextureAddressMode AddressW = TextureAddressMode::Wrap;
- float MipLODBias = 0.f;
- uint32_t MaxAnisotropy = 16;
- ComparisonFunc ComparisonFunc = ComparisonFunc::LessEqual;
- StaticBorderColor BorderColor = StaticBorderColor::OpaqueWhite;
- float MinLOD = 0.f;
- float MaxLOD = MaxLOD;
- uint32_t ShaderRegister;
- uint32_t RegisterSpace = 0;
- ShaderVisibility ShaderVisibility = ShaderVisibility::All;
- };
-
- struct RootSignatureDesc {
- std::vector<RootParameter> Parameters;
- std::vector<StaticSamplerDesc> StaticSamplers;
- RootSignatureFlags Flags;
- };
-
- struct VersionedRootSignatureDesc {
- RootSignatureVersion Version;
- RootSignatureDesc Desc;
- };
-
-Things like DescriptorRangeType and RootDescriptorFlags will be enums.
-
-After parsing, the VersionedRootSignatureDesc will be translated into a
-constant global variable in the clang AST and save to the
-HLSLRootSignatureAttr.
-
-For case compile to a standalone root signature blob, the global variable will
-be saved in the ASTContext.
-
-The global variable in AST will have a struct type that represents the root
-signature layout and a initializer that contains the values like space and
-numDescriptors of the root signature.
-
-In clang code generation, the global variable in AST will be translated into
-a global variable with constant initializer in LLVM IR.
+In clang code generation, the HLSLRootSignatureAttr in AST will be translated into
+a global variable with struct type to express the layout and a constant initializer
+to save things like space and NumDescriptors in LLVM IR.
CGHLSLRuntime will generate metadata to link the global variable as root
signature for given entry function or just nullptr for the standalone root
signature blob case.
-In LLVM DirectX backend, the global variable will be serialized and save into
- the root signature part of dx container when emit DXIL.
+In LLVM DirectX backend, the global variable will be serialized and saved as another
+global variable with section 'RTS0' with the serialized root signature as initializer.
+Then 'RTS0' global variable will be translated to the root signature part of dx
+container.
In DXIL validation, the root signature part will be deserialized and check if
the resource binding in the root signature exists in the resource table.
>From 1596854fd52af8db2bcac5b5a016953bbcb8c778 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Tue, 5 Mar 2024 12:48:32 -0800
Subject: [PATCH 06/19] Add MC ObjectWriter part.
---
clang/docs/HLSL/RootSignature.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 8d894c50e51540..8756a001f1b5d9 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -239,8 +239,8 @@ signature blob case.
In LLVM DirectX backend, the global variable will be serialized and saved as another
global variable with section 'RTS0' with the serialized root signature as initializer.
-Then 'RTS0' global variable will be translated to the root signature part of dx
-container.
+The MC ObjectWriter for DXContainer will take the global and write it to the correct
+part based on the section name given to the global.
In DXIL validation, the root signature part will be deserialized and check if
the resource binding in the root signature exists in the resource table.
>From a302b608cb59afec312b2a5d4b2274af06170701 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Tue, 5 Mar 2024 14:37:09 -0800
Subject: [PATCH 07/19] Add more detail about validation.
---
clang/docs/HLSL/RootSignature.rst | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 8756a001f1b5d9..0328d7848f534a 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -229,18 +229,28 @@ resource in the root signature. It will bind to the entry function in the AST.
For case compile to a standalone root signature blob, the HLSLRootSignatureAttr
will be bind to the TU.
-In clang code generation, the HLSLRootSignatureAttr in AST will be translated into
-a global variable with struct type to express the layout and a constant initializer
-to save things like space and NumDescriptors in LLVM IR.
+In clang code generation, the HLSLRootSignatureAttr in AST will be translated
+into a global variable with struct type to express the layout and a constant
+initializer to save things like space and NumDescriptors in LLVM IR.
CGHLSLRuntime will generate metadata to link the global variable as root
signature for given entry function or just nullptr for the standalone root
signature blob case.
-In LLVM DirectX backend, the global variable will be serialized and saved as another
-global variable with section 'RTS0' with the serialized root signature as initializer.
-The MC ObjectWriter for DXContainer will take the global and write it to the correct
-part based on the section name given to the global.
+In LLVM DirectX backend, the global variable will be serialized and saved as
+another global variable with section 'RTS0' with the serialized root signature
+as initializer.
+The MC ObjectWriter for DXContainer will take the global and write it to the
+correct part based on the section name given to the global.
In DXIL validation, the root signature part will be deserialized and check if
-the resource binding in the root signature exists in the resource table.
+resource used in the shader (the information is in pipeline state validation
+part) exists in the root signature.
+
+Same check could be done in Sema as well. But at AST level, it is impossible
+to identify unused resource which will be removed later. And the resource
+binding allocation is not done.
+So the only case could be caught in Sema is for resources that are known to be
+used for sure (like resources used in entry function and not under any control
+flow) and binded by user.
+If the resource is not in root signature, error should be reported in Sema.
>From 6764bb53803496109cf0d576c0ce2d84ee4cf50b Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Tue, 5 Mar 2024 14:47:31 -0800
Subject: [PATCH 08/19] Add TODO for detailed serialization format.
---
clang/docs/HLSL/RootSignature.rst | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 0328d7848f534a..c76ee8e73d1964 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -211,8 +211,9 @@ or `D3D12_ROOT_SIGNATURE_DESC1 (for rootsig_1_1)
<https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_signature_desc1>`_
structure in the Direct3D 12 API. (With the pointers translated to offsets.)
-DXC implementation of the serialization could be find `here
-<https://github.com/microsoft/DirectXShaderCompiler/blob/main/lib/DxilRootSignature/DxilRootSignatureSerializer.cpp#L41>`_
+TODO: replace the following link with actual serialized format.
+ DXC implementation of the serialization could be find `here
+ <https://github.com/microsoft/DirectXShaderCompiler/blob/main/lib/DxilRootSignature/DxilRootSignatureSerializer.cpp#L41>`_
Implementation Details
======================
>From 9df07446d45b810f8db036a2d0dea136b13d0b71 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Wed, 6 Mar 2024 12:55:17 -0800
Subject: [PATCH 09/19] Do the check in IR pass for DirectX backend. And add
empty entry for standalone root signature case.
---
clang/docs/HLSL/RootSignature.rst | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index c76ee8e73d1964..62497a628d08cc 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -228,15 +228,14 @@ represents the root signature string and the parsed information for each
resource in the root signature. It will bind to the entry function in the AST.
For case compile to a standalone root signature blob, the HLSLRootSignatureAttr
-will be bind to the TU.
+will be bind to a fake empty entry.
In clang code generation, the HLSLRootSignatureAttr in AST will be translated
into a global variable with struct type to express the layout and a constant
initializer to save things like space and NumDescriptors in LLVM IR.
CGHLSLRuntime will generate metadata to link the global variable as root
-signature for given entry function or just nullptr for the standalone root
-signature blob case.
+signature for given entry function.
In LLVM DirectX backend, the global variable will be serialized and saved as
another global variable with section 'RTS0' with the serialized root signature
@@ -244,9 +243,11 @@ as initializer.
The MC ObjectWriter for DXContainer will take the global and write it to the
correct part based on the section name given to the global.
-In DXIL validation, the root signature part will be deserialized and check if
-resource used in the shader (the information is in pipeline state validation
-part) exists in the root signature.
+In DXIL validation for DXC, the root signature part will be deserialized and
+check if resource used in the shader (the information is in pipeline state
+validation part) exists in the root signature.
+For LLVM DirectX backend, this could be done in IR pass before emit DXIL
+instead of validation.
Same check could be done in Sema as well. But at AST level, it is impossible
to identify unused resource which will be removed later. And the resource
>From a1b2a077859b1ee4b65d85024e7a16550b27a73f Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Thu, 7 Mar 2024 08:00:20 -0800
Subject: [PATCH 10/19] Add DXContainerGlobals for create 'RTS0' global.
---
clang/docs/HLSL/RootSignature.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 62497a628d08cc..61f81b848e271e 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -239,7 +239,7 @@ signature for given entry function.
In LLVM DirectX backend, the global variable will be serialized and saved as
another global variable with section 'RTS0' with the serialized root signature
-as initializer.
+as initializer in DXContainerGlobals pass.
The MC ObjectWriter for DXContainer will take the global and write it to the
correct part based on the section name given to the global.
>From 43834784772ad03bf554afbf9e9b72dc749ad811 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Mon, 18 Mar 2024 09:18:55 -0700
Subject: [PATCH 11/19] Add more details and link it to HLSLDocs.
---
clang/docs/HLSL/HLSLDocs.rst | 1 +
clang/docs/HLSL/RootSignature.rst | 111 ++++++++++++++++++++++++++++--
2 files changed, 107 insertions(+), 5 deletions(-)
diff --git a/clang/docs/HLSL/HLSLDocs.rst b/clang/docs/HLSL/HLSLDocs.rst
index 97b2425f013b34..13237103a300eb 100644
--- a/clang/docs/HLSL/HLSLDocs.rst
+++ b/clang/docs/HLSL/HLSLDocs.rst
@@ -16,3 +16,4 @@ HLSL Design and Implementation
ResourceTypes
EntryFunctions
FunctionCalls
+ RootSignature
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 61f81b848e271e..d120ed9f17fe54 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -226,20 +226,121 @@ signature blob.
The root signature parsing will generate a HLSLRootSignatureAttr with member
represents the root signature string and the parsed information for each
resource in the root signature. It will bind to the entry function in the AST.
+HLSLRootSignatureAttr will be something like this:
+Note, VersionedRootSignatureDesc is not D3D12_ROOT_SIGNATURE_DESC, it is just
+a simple struct to collect all the information in the root signature string.
-For case compile to a standalone root signature blob, the HLSLRootSignatureAttr
-will be bind to a fake empty entry.
+.. code-block:: c++
+
+ struct DescriptorRange {
+ DescriptorRangeType RangeType;
+ uint32_t NumDescriptors = 1;
+ uint32_t BaseShaderRegister;
+ uint32_t RegisterSpace = 0;
+ DescriptorRangeFlags Flags = DescriptorRangeFlags::None;
+ uint32_t OffsetInDescriptorsFromTableStart = DescriptorRangeOffsetAppend;
+ };
+
+ struct RootDescriptorTable {
+ std::vector<DescriptorRange> DescriptorRanges;
+ };
+ struct RootConstants {
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace = 0;
+ uint32_t Num32BitValues;
+ };
+
+ struct RootDescriptor {
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace = 0;
+ RootDescriptorFlags Flags = RootDescriptorFlags::None;
+ };
+ struct RootParameter {
+ RootParameterType ParameterType;
+ std::variant<RootDescriptorTable, RootConstants, RootDescriptor>
+ Parameter;
+ ShaderVisibility ShaderVisibility = ShaderVisibility::All;
+ };
+
+ struct StaticSamplerDesc {
+ Filter Filter = Filter::ANISOTROPIC;
+ TextureAddressMode AddressU = TextureAddressMode::Wrap;
+ TextureAddressMode AddressV = TextureAddressMode::Wrap;
+ TextureAddressMode AddressW = TextureAddressMode::Wrap;
+ float MipLODBias = 0.f;
+ uint32_t MaxAnisotropy = 16;
+ ComparisonFunc ComparisonFunc = ComparisonFunc::LessEqual;
+ StaticBorderColor BorderColor = StaticBorderColor::OpaqueWhite;
+ float MinLOD = 0.f;
+ float MaxLOD = MaxLOD;
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace = 0;
+ ShaderVisibility ShaderVisibility = ShaderVisibility::All;
+ };
+
+ struct RootSignatureDesc {
+ std::vector<RootParameter> Parameters;
+ std::vector<StaticSamplerDesc> StaticSamplers;
+ RootSignatureFlags Flags;
+ };
+
+ struct VersionedRootSignatureDesc {
+ RootSignatureVersion Version;
+ RootSignatureDesc Desc;
+ };
+
+ class HLSLRootSignatureAttr : public InheritableAttr {
+ protected:
+ std::string RootSignatureStr;
+ VersionedRootSignatureDesc RootSignature;
+ };
+
+
+.. code-block:: c++
+
+ def HLSLEntryRootSignature: HLSLRootSignatureAttr {
+ let Spellings = [GNU<"RootSignature">];
+ let Subjects = Subjects<[HLSLEntry]>;
+ let LangOpts = [HLSL];
+ let Args = [StringArgument<"InputString">];
+ }
+
+For case compile to a standalone root signature blob, the
+HLSLRootSignatureAttr will be bind to a fake empty entry.
In clang code generation, the HLSLRootSignatureAttr in AST will be translated
-into a global variable with struct type to express the layout and a constant
-initializer to save things like space and NumDescriptors in LLVM IR.
+into a global variable with struct type to express the layout and metadata to
+save things like static sampler, root flags, space and NumDescriptors in LLVM IR.
+The struct type will be look like this:
+
+.. code-block:: c++
+
+ %struct.TABLE0 = type { target("dx.rs.desc"),
+ target("dx.rs.sampler")}
+
+ %struct.RS = type { target("dx.rs.rootconstant", 4),
+ %struct.TABLE0,
+ target("dx.rs.rootdescriptor") }
+
+The metadata will be look like this:
+
+.. code-block:: c++
+
+ !1 = !{ data for static sampler } ; Save informations for single static
+ ; sampler
+ !2 = !{!1} ; All static samplers
+ !3 = !{ data for descriptors } ; Save informations for single descriptor
+ !4 = !{ !3 } ; All descriptors
+ !5 = !{void ()* @main, %struct.RS undef, i32 rootFlags, !2, !4}
+
CGHLSLRuntime will generate metadata to link the global variable as root
signature for given entry function.
In LLVM DirectX backend, the global variable will be serialized and saved as
another global variable with section 'RTS0' with the serialized root signature
-as initializer in DXContainerGlobals pass.
+as initializer in DXContainerGlobals pass. The serialized root signature is in
+exactly the format it will be written out to the DXContainer object.
The MC ObjectWriter for DXContainer will take the global and write it to the
correct part based on the section name given to the global.
>From ccb320738e272aeb71838c2682c58c0c269d98eb Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Tue, 26 Mar 2024 08:26:03 -0700
Subject: [PATCH 12/19] Add detail about the actual serialized format.
---
clang/docs/HLSL/RootSignature.rst | 75 +++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 4 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index d120ed9f17fe54..58305da9cc2399 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -209,11 +209,78 @@ object in the Direct3D 12 API. The binary format is defined by the
<https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_signature_desc>`_
or `D3D12_ROOT_SIGNATURE_DESC1 (for rootsig_1_1)
<https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_root_signature_desc1>`_
-structure in the Direct3D 12 API. (With the pointers translated to offsets.)
+structure in the Direct3D 12 API. (With the pointers translated to offsets.)
-TODO: replace the following link with actual serialized format.
- DXC implementation of the serialization could be find `here
- <https://github.com/microsoft/DirectXShaderCompiler/blob/main/lib/DxilRootSignature/DxilRootSignatureSerializer.cpp#L41>`_
+It will be look like this:
+
+.. code-block:: c++
+
+ struct DxilContainerRootDescriptor1 {
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace;
+ uint32_t Flags;
+ };
+
+ struct DxilContainerDescriptorRange {
+ uint32_t RangeType;
+ uint32_t NumDescriptors;
+ uint32_t BaseShaderRegister;
+ uint32_t RegisterSpace;
+ uint32_t OffsetInDescriptorsFromTableStart;
+ };
+
+ struct DxilContainerDescriptorRange1 {
+ uint32_t RangeType;
+ uint32_t NumDescriptors;
+ uint32_t BaseShaderRegister;
+ uint32_t RegisterSpace;
+ uint32_t Flags;
+ uint32_t OffsetInDescriptorsFromTableStart;
+ };
+
+ struct DxilContainerRootDescriptorTable {
+ uint32_t NumDescriptorRanges;
+ uint32_t DescriptorRangesOffset;
+ };
+
+ struct DxilContainerRootParameter {
+ uint32_t ParameterType;
+ uint32_t ShaderVisibility;
+ uint32_t PayloadOffset;
+ };
+
+ struct DxilContainerRootSignatureDesc {
+ uint32_t Version;
+ uint32_t NumParameters;
+ uint32_t RootParametersOffset;
+ uint32_t NumStaticSamplers;
+ uint32_t StaticSamplersOffset;
+ uint32_t Flags;
+ };
+
+
+The binary representation begins with a **DxilContainerRootSignatureDesc**
+object.
+
+The object will be followed by an array of
+**DxilContainerRootParameter/Parameter1** objects located at
+**DxilContainerRootSignatureDesc::RootParametersOffset**, which corresponds to
+the size of **DxilContainerRootSignatureDesc**.
+
+Subsequently, there will be detailed object (**DxilRootConstants**,
+**DxilContainerRootDescriptorTable**, or
+**DxilRootDescriptor/DxilContainerRootDescriptor1**, depending on the parameter
+type) for each **DxilContainerRootParameter** in the array. With
+**DxilContainerRootParameter.PayloadOffset** pointing to the detailed object.
+
+In cases where the detailed object is a **DxilContainerRootDescriptorTable**,
+it is succeeded by an array of
+**DxilContainerDescriptorRange/DxilContainerDescriptorRange1** at
+**DxilContainerRootDescriptorTable.DescriptorRangesOffset**.
+
+The binary representation is finalized with an array of
+**DxilStaticSamplerDesc** at
+**DxilContainerRootSignatureDesc::StaticSamplersOffset**.
Implementation Details
======================
>From aa30fb6d6e45314021fc8fcdac861eb86744c86d Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Wed, 27 Mar 2024 12:24:08 -0700
Subject: [PATCH 13/19] Fix clang-docs-html issue.
---
clang/docs/HLSL/RootSignature.rst | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 58305da9cc2399..90393d542f2042 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -22,7 +22,7 @@ possible to attach a root signature string to a particular shader via the
RootSignature attribute (in the following example, using the MyRS1 entry
point):
-.. code-block:: c++
+.. code-block:: hlsl
#define RS "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
"DENY_VERTEX_SHADER_ROOT_ACCESS), " \
@@ -44,7 +44,7 @@ point):
[RootSignature(RS)]
float4 main(float4 coord : COORD) : SV_Target
{
- …
+ "…"
}
The compiler will create and verify the root signature blob for the shader and
@@ -54,7 +54,7 @@ The other mechanism is to create a standalone root signature blob, perhaps to
reuse it with a large set of shaders, saving space. The name of the define
string is specified via the usual -E argument. For example:
-.. code-block:: c++
+.. code-block:: sh
dxc.exe -T rootsig_1_1 MyRS1.hlsl -E MyRS1 -Fo MyRS1.fxo
@@ -64,7 +64,7 @@ line, e.g, -D MyRS1=”…”.
Root Signature Grammar
======================
-.. code-block:: c++
+.. code-block:: peg
RootSignature : (RootElement(,RootElement)?)?
@@ -363,7 +363,7 @@ a simple struct to collect all the information in the root signature string.
};
-.. code-block:: c++
+.. code-block::
def HLSLEntryRootSignature: HLSLRootSignatureAttr {
let Spellings = [GNU<"RootSignature">];
@@ -380,7 +380,7 @@ into a global variable with struct type to express the layout and metadata to
save things like static sampler, root flags, space and NumDescriptors in LLVM IR.
The struct type will be look like this:
-.. code-block:: c++
+.. code-block:: llvm
%struct.TABLE0 = type { target("dx.rs.desc"),
target("dx.rs.sampler")}
@@ -391,7 +391,7 @@ The struct type will be look like this:
The metadata will be look like this:
-.. code-block:: c++
+.. code-block:: llvm
!1 = !{ data for static sampler } ; Save informations for single static
; sampler
>From 8dfceb7135cb29410c3448da3b6d4761c34609c2 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Wed, 27 Mar 2024 12:34:21 -0700
Subject: [PATCH 14/19] Remove llvm mark for illegal comment.
---
clang/docs/HLSL/RootSignature.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 90393d542f2042..0d98c71d38f41c 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -391,7 +391,7 @@ The struct type will be look like this:
The metadata will be look like this:
-.. code-block:: llvm
+.. code-block::
!1 = !{ data for static sampler } ; Save informations for single static
; sampler
>From d143b5273bd5893ff93364f5761c5febc7cf652b Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Wed, 27 Mar 2024 19:12:31 -0700
Subject: [PATCH 15/19] Add define for RootSignatureVersion.
---
clang/docs/HLSL/RootSignature.rst | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 0d98c71d38f41c..76e4601a24a278 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -44,7 +44,7 @@ point):
[RootSignature(RS)]
float4 main(float4 coord : COORD) : SV_Target
{
- "…"
+ …
}
The compiler will create and verify the root signature blob for the shader and
@@ -351,6 +351,12 @@ a simple struct to collect all the information in the root signature string.
RootSignatureFlags Flags;
};
+ enum class RootSignatureVersion {
+ Version_1 = 1,
+ Version_1_0 = 1,
+ Version_1_1 = 2
+ };
+
struct VersionedRootSignatureDesc {
RootSignatureVersion Version;
RootSignatureDesc Desc;
>From c6715d1de302d1151ab67e8c039630631057f821 Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Wed, 27 Mar 2024 19:36:09 -0700
Subject: [PATCH 16/19] Remove the hlsl tag which fail doc build.
---
clang/docs/HLSL/RootSignature.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 76e4601a24a278..aeb5a66349df8f 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -22,7 +22,7 @@ possible to attach a root signature string to a particular shader via the
RootSignature attribute (in the following example, using the MyRS1 entry
point):
-.. code-block:: hlsl
+.. code-block::
#define RS "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | " \
"DENY_VERTEX_SHADER_ROOT_ACCESS), " \
>From f8c2666a6618255cfc23449236d8019e1ac8794c Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Fri, 29 Mar 2024 06:28:31 -0700
Subject: [PATCH 17/19] Add places compiler needs access the root signature.
---
clang/docs/HLSL/RootSignature.rst | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index aeb5a66349df8f..a963bc38b02e3b 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -61,6 +61,28 @@ string is specified via the usual -E argument. For example:
Note that the root signature string define can also be passed on the command
line, e.g, -D MyRS1=”…”.
+
+Life of a Root Signature
+========================
+
+The root signature in a compiler begins with a string in the root signature
+attribute and ends with a serialized root signature in the DXContainer.
+
+To report errors as early as possible, root signature string parsing should
+occur in Sema.
+To prevent redundant work, this parsing should only be performed in Sema.
+Consequently, the parsed root signature information must be stored in the AST.
+
+To ensure that a used resource has a binding in the root signature, this
+information should be accessible in the backend to facilitate early error
+reporting.
+
+Since only the binding information is necessary for validation, one
+approach could be to store the binding information separately for backend
+verification and serialize the root signature information promptly, as it
+constitutes the final output and is not utilized by any compiler passes.
+
+
Root Signature Grammar
======================
>From 399d2ad48ee69b2aef6f16f70857e3686bfbfc8e Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Fri, 5 Apr 2024 08:32:58 -0700
Subject: [PATCH 18/19] Add ConstantStruct example.
---
clang/docs/HLSL/RootSignature.rst | 420 +++++++++++++++++++-----------
1 file changed, 264 insertions(+), 156 deletions(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index a963bc38b02e3b..0fae16ee0113d0 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -19,7 +19,7 @@ signature constituent components.
There are two mechanisms to compile an HLSL root signature. First, it is
possible to attach a root signature string to a particular shader via the
-RootSignature attribute (in the following example, using the MyRS1 entry
+RootSignature attribute (in the following example, using the main entry
point):
.. code-block::
@@ -41,7 +41,7 @@ point):
" addressU = TEXTURE_ADDRESS_CLAMP, " \
" filter = FILTER_MIN_MAG_MIP_LINEAR )"
- [RootSignature(RS)]
+ [RootSignature(MyRS)]
float4 main(float4 coord : COORD) : SV_Target
{
…
@@ -61,26 +61,22 @@ string is specified via the usual -E argument. For example:
Note that the root signature string define can also be passed on the command
line, e.g, -D MyRS1=”…”.
+Root signature could also used in form of StateObject like this:
-Life of a Root Signature
-========================
-
-The root signature in a compiler begins with a string in the root signature
-attribute and ends with a serialized root signature in the DXContainer.
-
-To report errors as early as possible, root signature string parsing should
-occur in Sema.
-To prevent redundant work, this parsing should only be performed in Sema.
-Consequently, the parsed root signature information must be stored in the AST.
+.. code-block::
-To ensure that a used resource has a binding in the root signature, this
-information should be accessible in the backend to facilitate early error
-reporting.
+ GlobalRootSignature MyGlobalRootSignature =
+ {
+ "DescriptorTable(UAV(u0))," // Output texture
+ "SRV(t0)," // Acceleration structure
+ "CBV(b0)," // Scene constants
+ "DescriptorTable(SRV(t1, numDescriptors = 2))" // Static index and vertex buffers.
+ };
-Since only the binding information is necessary for validation, one
-approach could be to store the binding information separately for backend
-verification and serialize the root signature information promptly, as it
-constitutes the final output and is not utilized by any compiler passes.
+ LocalRootSignature MyLocalRootSignature =
+ {
+ "RootConstants(num32BitConstants = 4, b1)" // Cube constants
+ };
Root Signature Grammar
@@ -237,48 +233,84 @@ It will be look like this:
.. code-block:: c++
- struct DxilContainerRootDescriptor1 {
- uint32_t ShaderRegister;
- uint32_t RegisterSpace;
- uint32_t Flags;
- };
-
- struct DxilContainerDescriptorRange {
- uint32_t RangeType;
- uint32_t NumDescriptors;
- uint32_t BaseShaderRegister;
- uint32_t RegisterSpace;
- uint32_t OffsetInDescriptorsFromTableStart;
- };
-
- struct DxilContainerDescriptorRange1 {
- uint32_t RangeType;
- uint32_t NumDescriptors;
- uint32_t BaseShaderRegister;
- uint32_t RegisterSpace;
- uint32_t Flags;
- uint32_t OffsetInDescriptorsFromTableStart;
- };
-
- struct DxilContainerRootDescriptorTable {
- uint32_t NumDescriptorRanges;
- uint32_t DescriptorRangesOffset;
- };
-
- struct DxilContainerRootParameter {
- uint32_t ParameterType;
- uint32_t ShaderVisibility;
- uint32_t PayloadOffset;
- };
-
- struct DxilContainerRootSignatureDesc {
- uint32_t Version;
- uint32_t NumParameters;
- uint32_t RootParametersOffset;
- uint32_t NumStaticSamplers;
- uint32_t StaticSamplersOffset;
- uint32_t Flags;
- };
+ namespace dxbc {
+ namespace SerializedRootSignature {
+ namespace v_1_0 {
+
+ struct DxilContainerDescriptorRange {
+ uint32_t RangeType;
+ uint32_t NumDescriptors;
+ uint32_t BaseShaderRegister;
+ uint32_t RegisterSpace;
+ uint32_t OffsetInDescriptorsFromTableStart;
+ };
+
+ struct ContainerRootDescriptor {
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace;
+ };
+ }
+ namespace v_1_1 {
+
+ struct ContainerDescriptorRange {
+ uint32_t RangeType;
+ uint32_t NumDescriptors;
+ uint32_t BaseShaderRegister;
+ uint32_t RegisterSpace;
+ uint32_t Flags;
+ uint32_t OffsetInDescriptorsFromTableStart;
+ };
+
+ struct ContainerRootDescriptor {
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace;
+ uint32_t Flags;
+ };
+ }
+
+ struct ContainerRootDescriptorTable {
+ uint32_t NumDescriptorRanges;
+ uint32_t DescriptorRangesOffset;
+ };
+
+ struct RootConstants {
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace = 0;
+ uint32_t Num32BitValues;
+ };
+
+ struct ContainerRootParameter {
+ uint32_t ParameterType;
+ uint32_t ShaderVisibility;
+ uint32_t PayloadOffset;
+ };
+
+ struct StaticSamplerDesc {
+ Filter Filter = Filter::ANISOTROPIC;
+ TextureAddressMode AddressU = TextureAddressMode::Wrap;
+ TextureAddressMode AddressV = TextureAddressMode::Wrap;
+ TextureAddressMode AddressW = TextureAddressMode::Wrap;
+ float MipLODBias = 0.f;
+ uint32_t MaxAnisotropy = 16;
+ ComparisonFunc ComparisonFunc = ComparisonFunc::LessEqual;
+ StaticBorderColor BorderColor = StaticBorderColor::OpaqueWhite;
+ float MinLOD = 0.f;
+ float MaxLOD = MaxLOD;
+ uint32_t ShaderRegister;
+ uint32_t RegisterSpace = 0;
+ ShaderVisibility ShaderVisibility = ShaderVisibility::All;
+ };
+
+ struct ContainerRootSignatureDesc {
+ uint32_t Version;
+ uint32_t NumParameters;
+ uint32_t RootParametersOffset;
+ uint32_t NumStaticSamplers;
+ uint32_t StaticSamplersOffset;
+ uint32_t Flags;
+ };
+ }
+ }
The binary representation begins with a **DxilContainerRootSignatureDesc**
@@ -289,6 +321,10 @@ The object will be followed by an array of
**DxilContainerRootSignatureDesc::RootParametersOffset**, which corresponds to
the size of **DxilContainerRootSignatureDesc**.
+Then it will be an array of
+**DxilStaticSamplerDesc** at
+**DxilContainerRootSignatureDesc::StaticSamplersOffset**.
+
Subsequently, there will be detailed object (**DxilRootConstants**,
**DxilContainerRootDescriptorTable**, or
**DxilRootDescriptor/DxilContainerRootDescriptor1**, depending on the parameter
@@ -300,137 +336,209 @@ it is succeeded by an array of
**DxilContainerDescriptorRange/DxilContainerDescriptorRange1** at
**DxilContainerRootDescriptorTable.DescriptorRangesOffset**.
-The binary representation is finalized with an array of
-**DxilStaticSamplerDesc** at
-**DxilContainerRootSignatureDesc::StaticSamplersOffset**.
+The layout could be look like this for the MyRS in above example:
+.. code-block:: c++
-Implementation Details
-======================
+ struct SerializedRS {
+ ContainerRootSignatureDesc RSDesc;
+ ContainerRootParameter rootParameters[6];
+ StaticSamplerDesc samplers[2];
-The root signature string will be parsed in Clang.
-The parsing
-will happened when build HLSLRootSignatureAttr or when build standalone root
-signature blob.
+ // Extra part for each RootParameter in rootParameters.
-The root signature parsing will generate a HLSLRootSignatureAttr with member
-represents the root signature string and the parsed information for each
-resource in the root signature. It will bind to the entry function in the AST.
-HLSLRootSignatureAttr will be something like this:
-Note, VersionedRootSignatureDesc is not D3D12_ROOT_SIGNATURE_DESC, it is just
-a simple struct to collect all the information in the root signature string.
+ // RootConstants/RootDescriptorTable/RootDescriptor dependent on ParameterType.
+ // For RootDescriptorTable, the extra part will be like
-.. code-block:: c++
+ // struct {
- struct DescriptorRange {
- DescriptorRangeType RangeType;
- uint32_t NumDescriptors = 1;
- uint32_t BaseShaderRegister;
- uint32_t RegisterSpace = 0;
- DescriptorRangeFlags Flags = DescriptorRangeFlags::None;
- uint32_t OffsetInDescriptorsFromTableStart = DescriptorRangeOffsetAppend;
- };
+ // RootDescriptorTable table;
- struct RootDescriptorTable {
- std::vector<DescriptorRange> DescriptorRanges;
- };
- struct RootConstants {
- uint32_t ShaderRegister;
- uint32_t RegisterSpace = 0;
- uint32_t Num32BitValues;
- };
+ // ContainerDescriptorRange ranges[NumDescriptorRangesForTheTable];
- struct RootDescriptor {
- uint32_t ShaderRegister;
- uint32_t RegisterSpace = 0;
- RootDescriptorFlags Flags = RootDescriptorFlags::None;
- };
- struct RootParameter {
- RootParameterType ParameterType;
- std::variant<RootDescriptorTable, RootConstants, RootDescriptor>
- Parameter;
- ShaderVisibility ShaderVisibility = ShaderVisibility::All;
- };
+ // };
- struct StaticSamplerDesc {
- Filter Filter = Filter::ANISOTROPIC;
- TextureAddressMode AddressU = TextureAddressMode::Wrap;
- TextureAddressMode AddressV = TextureAddressMode::Wrap;
- TextureAddressMode AddressW = TextureAddressMode::Wrap;
- float MipLODBias = 0.f;
- uint32_t MaxAnisotropy = 16;
- ComparisonFunc ComparisonFunc = ComparisonFunc::LessEqual;
- StaticBorderColor BorderColor = StaticBorderColor::OpaqueWhite;
- float MinLOD = 0.f;
- float MaxLOD = MaxLOD;
- uint32_t ShaderRegister;
- uint32_t RegisterSpace = 0;
- ShaderVisibility ShaderVisibility = ShaderVisibility::All;
- };
+ struct {
- struct RootSignatureDesc {
- std::vector<RootParameter> Parameters;
- std::vector<StaticSamplerDesc> StaticSamplers;
- RootSignatureFlags Flags;
- };
+ RootConstants b0;
- enum class RootSignatureVersion {
- Version_1 = 1,
- Version_1_0 = 1,
- Version_1_1 = 2
- };
+ ContainerRootDescriptor t1;
- struct VersionedRootSignatureDesc {
- RootSignatureVersion Version;
- RootSignatureDesc Desc;
- };
+ ContainerRootDescriptor u1;
+
+ struct {
+
+ ContainerRootDescriptor tab0;
+
+ ContainerDescriptorRange tab0Ranges[2];
+
+ } table0;
+
+ struct {
+
+ ContainerRootDescriptor tab1;
+
+ ContainerDescriptorRange tab1Ranges[1];
+
+ } table1;
+
+ RootConstants b10;
- class HLSLRootSignatureAttr : public InheritableAttr {
- protected:
- std::string RootSignatureStr;
- VersionedRootSignatureDesc RootSignature;
};
+ };
+
+
+Life of a Root Signature
+========================
+
+The root signature in a compiler begins with a string in the root signature
+attribute and ends with a serialized root signature in the DXContainer.
+
+To report errors as early as possible, root signature string parsing should
+occur in Sema.
+
+To ensure that a used resource has a binding in the root signature, this
+information should be accessible in the backend to make sure legal dxil is
+generated.
+
+
+Implementation Details
+======================
+
+The root signature string will be parsed in Clang.
+The parsing
+will happened when build HLSLRootSignatureAttr, standalone root signature blob
+or local/global root signature.
+
+A new AST node HLSLRootSignatureDecl will be added to represent the root
+signature in the AST.
+
+Assuming the cost to parse root signature string is cheap,
+HLSLRootSignatureDecl will follow common Clang approach which only save the
+string in the AST.
+A root signature will be parsed twice, once in Sema for diagnostic and once in
+clang code generation for generating the serialized root signature.
+The first parsing will check register overlap and run on all root signatures
+in the translation unit.
+The second parsing will calculate the offset for serialized root signature and
+only run on the root signature for the entry function or local/global root
+signature which used in SubobjectToExportsAssociation.
+
+HLSLRootSignatureDecl will have method to parse the string for diagnostic and
+generate the SerializedRS mentioned above.
+
+A HLSLRootSignatureAttr will be created when meet RootSignature attribute in
+HLSL.
+It will defined as below.
.. code-block::
- def HLSLEntryRootSignature: HLSLRootSignatureAttr {
+ def HLSLEntryRootSignature: InheriableAttr {
let Spellings = [GNU<"RootSignature">];
let Subjects = Subjects<[HLSLEntry]>;
let LangOpts = [HLSL];
- let Args = [StringArgument<"InputString">];
+ let Args = [StringArgument<"InputString">, DeclArgument<HLSLRootSignature, "RootSignature", 0, /*fake*/ 1>];
}
+Because the RootSignature attribute in hlsl only have the string, it is easier
+to add a StringArgument to save the string first.
+A HLSLRootSignatureDecl will be created for diagnostic and saved to the
+HLSLEntryRootSignatureAttr for clang code generation.
+The HLSLRootSignatureDecl will save StringLiteral instead StringRef for diagnostic.
+
+The AST for the attribute will be like this:
+
+.. code-block::
+
+ HLSLEntryRootSignatureAttr
+ "RootFlags( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | DENY_VERTEX_SHADER_ROOT_ACCESS),
+ CBV(b0, space = 1, flags = DATA_STATIC), SRV(t0), UAV(u0),
+ DescriptorTable( CBV(b1), SRV(t1, numDescriptors = 8,flags = DESCRIPTORS_VOLATILE),
+ UAV(u1, numDescriptors = unbounded, flags = DESCRIPTORS_VOLATILE)),
+ DescriptorTable(Sampler(s0, space=1, numDescriptors = 4)),
+ RootConstants(num32BitConstants=3, b10),
+ StaticSampler(s1),
+ StaticSampler(s2, addressU = TEXTURE_ADDRESS_CLAMP, filter = FILTER_MIN_MAG_MIP_LINEAR )"
+ HLSLRootSignature 'main.RS'
+
For case compile to a standalone root signature blob, the
HLSLRootSignatureAttr will be bind to a fake empty entry.
In clang code generation, the HLSLRootSignatureAttr in AST will be translated
into a global variable with struct type to express the layout and metadata to
save things like static sampler, root flags, space and NumDescriptors in LLVM IR.
-The struct type will be look like this:
+The global variable will be look like this for the example above:
.. code-block:: llvm
- %struct.TABLE0 = type { target("dx.rs.desc"),
- target("dx.rs.sampler")}
+ ; %0 is the type for the whole serialzed root signature.
+ %0 = type { %"dxbc::RootSignature::ContainerRootSignatureDesc",
+ [6 x %"dxbc::RootSignature::ContainerRootParameter"],
+ [2 x %"dxbc::RootSignature::StaticSamplerDesc"],
+ %1 }
+ ; %1 is the type for extra parameter information for each RootParameter in rootParameters.
+ %1 = type { %"dxbc::RootSignature::ContainerRootDescriptor",
+ %"dxbc::RootSignature::ContainerRootDescriptor",
+ %"dxbc::RootSignature::ContainerRootDescriptor",
+ %2,
+ %3,
+ %"dxbc::RootSignature::ContainerRootConstants" }
+ ; %2 is the type for first DescriptorTable in RootParameter.
+ %2 = type { %"dxbc::RootSignature::ContainerRootDescriptorTable", [3 x %"dxbc::RootSignature::ContainerDescriptorRange"] }
+ ; %3 is the type for second DescriptorTable in RootParameter.
+ %3 = type { %"dxbc::RootSignature::ContainerRootDescriptorTable", [1 x %"dxbc::RootSignature::ContainerDescriptorRange"] }
+
+ %"dxbc::RootSignature::ContainerRootSignatureDesc" = type { i32, i32, i32, i32, i32, i32 }
+ %"dxbc::RootSignature::ContainerRootParameter" = type { i32, i32, i32 }
+ %"dxbc::RootSignature::StaticSamplerDesc" = type { i32, i32, i32, i32, float, i32, i32, i32, float, float, i32, i32, i32 }
+ %"dxbc::RootSignature::ContainerRootDescriptor" = type { i32, i32, i32 }
+ %"dxbc::RootSignature::ContainerRootDescriptorTable" = type { i32, i32 }
+ %"dxbc::RootSignature::ContainerDescriptorRange" = type { i32, i32, i32, i32, i32, i32 }
+ %"dxbc::RootSignature::ContainerRootConstants" = type { i32, i32, i32 }
+ ; The global variable which save the serialized root signature ConstantStruct as init.
+ @RootSig = internal constant %0 {
+ %"dxbc::RootSignature::ContainerRootSignatureDesc" { i32 2, i32 0, i32 24, i32 0, i32 96, i32 3 },
+ [6 x %"dxbc::RootSignature::ContainerRootParameter"]
+ [%"dxbc::RootSignature::ContainerRootParameter" { i32 2, i32 0, i32 200 },
+ %"dxbc::RootSignature::ContainerRootParameter" { i32 3, i32 0, i32 212 },
+ %"dxbc::RootSignature::ContainerRootParameter" { i32 4, i32 0, i32 224 },
+ %"dxbc::RootSignature::ContainerRootParameter" { i32 0, i32 0, i32 236 },
+ %"dxbc::RootSignature::ContainerRootParameter" { i32 0, i32 0, i32 316 },
+ %"dxbc::RootSignature::ContainerRootParameter" { i32 1, i32 0, i32 348 }],
+ [2 x %"dxbc::RootSignature::StaticSamplerDesc"]
+ [%"dxbc::RootSignature::StaticSamplerDesc" { i32 85, i32 1, i32 1, i32 1, float 0.000000e+00, i32 16, i32 4, i32 2, float 0.000000e+00, float 0x47EFFFFFE0000000, i32 1, i32 0, i32 0 },
+ %"dxbc::RootSignature::StaticSamplerDesc" { i32 21, i32 3, i32 1, i32 1, float 0.000000e+00, i32 16, i32 4, i32 2, float 0.000000e+00, float 0x47EFFFFFE0000000, i32 2, i32 0, i32 0 }],
+ %1 {
+ %"dxbc::RootSignature::ContainerRootDescriptor" { i32 0, i32 1, i32 8 },
+ %"dxbc::RootSignature::ContainerRootDescriptor" zeroinitializer,
+ %"dxbc::RootSignature::ContainerRootDescriptor" zeroinitializer,
+ %2 { %"dxbc::RootSignature::ContainerRootDescriptorTable" { i32 3, i32 244 },
+ [3 x %"dxbc::RootSignature::ContainerDescriptorRange"]
+ [%"dxbc::RootSignature::ContainerDescriptorRange" { i32 2, i32 1, i32 1, i32 0, i32 0, i32 -1 },
+ %"dxbc::RootSignature::ContainerDescriptorRange" { i32 0, i32 8, i32 1, i32 0, i32 1, i32 -1 },
+ %"dxbc::RootSignature::ContainerDescriptorRange" { i32 1, i32 -1, i32 1, i32 0, i32 1, i32 -1 }] },
+ %3 { %"dxbc::RootSignature::ContainerRootDescriptorTable" { i32 1, i32 324 },
+ [1 x %"dxbc::RootSignature::ContainerDescriptorRange"]
+ [%"dxbc::RootSignature::ContainerDescriptorRange" { i32 3, i32 4, i32 0, i32 1, i32 0, i32 -1 }] },
+ %"dxbc::RootSignature::ContainerRootConstants" { i32 10, i32 0, i32 3 } } }
- %struct.RS = type { target("dx.rs.rootconstant", 4),
- %struct.TABLE0,
- target("dx.rs.rootdescriptor") }
-The metadata will be look like this:
+CGHLSLRuntime will generate metadata to link the global variable as root
+signature for given entry function.
.. code-block::
- !1 = !{ data for static sampler } ; Save informations for single static
- ; sampler
- !2 = !{!1} ; All static samplers
- !3 = !{ data for descriptors } ; Save informations for single descriptor
- !4 = !{ !3 } ; All descriptors
- !5 = !{void ()* @main, %struct.RS undef, i32 rootFlags, !2, !4}
-
+ ; named metadata for entry root signature
+ !hlsl.entry.rootsignatures = !{!2}
+ …
+ ; link the global variable to entry function
+ !2 = !{ptr @main, ptr @RootSig}
-CGHLSLRuntime will generate metadata to link the global variable as root
-signature for given entry function.
+To make sure the emitted DXIL is legal, the root signature information will be
+validated after all optimizations in the DXIL backend.
+For all resources used in the shader, the root signature will be checked to
+ensure that the resource is in the root signature.
+The binding information will be collected from the root signature ConstantStruct.
In LLVM DirectX backend, the global variable will be serialized and saved as
another global variable with section 'RTS0' with the serialized root signature
@@ -442,7 +550,7 @@ correct part based on the section name given to the global.
In DXIL validation for DXC, the root signature part will be deserialized and
check if resource used in the shader (the information is in pipeline state
validation part) exists in the root signature.
-For LLVM DirectX backend, this could be done in IR pass before emit DXIL
+For LLVM DirectX backend, this will be done in IR pass before emit DXIL
instead of validation.
Same check could be done in Sema as well. But at AST level, it is impossible
>From 2c0add0ae328f9c53dac25cdc2aeb5fa936e5dac Mon Sep 17 00:00:00 2001
From: Xiang Li <python3kgae at outlook.com>
Date: Fri, 5 Apr 2024 13:43:44 -0400
Subject: [PATCH 19/19] Apply suggestions from code review
Co-authored-by: Damyan Pepper <damyanp at microsoft.com>
---
clang/docs/HLSL/RootSignature.rst | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/docs/HLSL/RootSignature.rst b/clang/docs/HLSL/RootSignature.rst
index 0fae16ee0113d0..8a09cbf2b84b5f 100644
--- a/clang/docs/HLSL/RootSignature.rst
+++ b/clang/docs/HLSL/RootSignature.rst
@@ -337,6 +337,7 @@ it is succeeded by an array of
**DxilContainerRootDescriptorTable.DescriptorRangesOffset**.
The layout could be look like this for the MyRS in above example:
+
.. code-block:: c++
struct SerializedRS {
@@ -433,7 +434,7 @@ It will defined as below.
.. code-block::
- def HLSLEntryRootSignature: InheriableAttr {
+ def HLSLEntryRootSignature: InheritableAttr {
let Spellings = [GNU<"RootSignature">];
let Subjects = Subjects<[HLSLEntry]>;
let LangOpts = [HLSL];
More information about the cfe-commits
mailing list