1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
|
===============
Root Signatures
===============
.. contents::
:local:
.. toctree::
:hidden:
Overview
========
A root signature is used to describe what resources a shader needs access to
and how they're organized and bound in the pipeline. The DirectX Container
(DXContainer) contains a root signature part (RTS0), which stores this
information in a binary format. To assist with the construction of, and
interaction with, a root signature is represented as metadata
(``dx.rootsignatures`` ) in the LLVM IR. The metadata can then be converted to
its binary form, as defined in
`llvm/include/llvm/llvm/Frontend/HLSL/RootSignatureMetadata.h
<https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h>`_.
This document serves as a reference for the metadata representation of a root
signature for users to interface with.
Metadata Representation
=======================
Consider the reference root signature, then the following sections describe the
metadata representation of this root signature and the corresponding operands.
.. code-block:: HLSL
RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT),
RootConstants(b0, space = 1, num32Constants = 3),
CBV(b1, flags = 0),
StaticSampler(
filter = FILTER_MIN_MAG_POINT_MIP_LINEAR,
addressU = TEXTURE_ADDRESS_BORDER,
),
DescriptorTable(
visibility = VISIBILITY_ALL,
SRV(t0, flags = DATA_STATIC_WHILE_SET_AT_EXECUTE),
UAV(
numDescriptors = 5, u1, space = 10, offset = 5,
flags = DATA_VOLATILE
)
)
.. note::
A root signature does not necessarily have a unique metadata representation.
Futher, a malformed root signature can be represented in the metadata format,
(eg. mixing Sampler and non-Sampler descriptor ranges), and so it is the
user's responsibility to verify that it is a well-formed root signature.
Named Root Signature Table
==========================
.. code-block:: LLVM
!dx.rootsignatures = !{!0}
A named metadata node, ``dx.rootsignatures``` is used to identify the root
signature table. The table itself is a list of references to function/root
signature pairs.
Function/Root Signature Pair
============================
.. code-block:: LLVM
!1 = !{ptr @main, !2, i32 2 }
The function/root signature associates a function (the first operand) with a
reference to a root signature (the second operand). The root signature version
(the third operand) used for validation logic and binary format follows.
Root Signature
==============
.. code-block:: LLVM
!2 = !{ !3, !4, !5, !6, !7 }
The root signature itself simply consists of a list of references to its root
signature elements.
Root Signature Element
======================
A root signature element is identified by the first operand, which is a string.
The following root signature elements are defined:
================= ======================
Identifier String Root Signature Element
================= ======================
"RootFlags" Root Flags
"RootConstants" Root Constants
"RootCBV" Root Descriptor
"RootSRV" Root Descriptor
"RootUAV" Root Descriptor
"StaticSampler" Static Sampler
"DescriptorTable" Descriptor Table
================= ======================
Below is listed the representation for each type of root signature element.
Root Flags
==========
.. code-block:: LLVM
!3 = { !"RootFlags", i32 1 }
======================= ====
Description Type
======================= ====
`Root Signature Flags`_ i32
======================= ====
.. _Root Signature Flags: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_root_signature_flags
Root Constants
==============
.. code-block:: LLVM
!4 = { !"RootConstants", i32 0, i32 1, i32 2, i32 3 }
==================== ====
Description Type
==================== ====
`Shader Visibility`_ i32
Shader Register i32
Register Space i32
Number 32-bit Values i32
==================== ====
.. _Shader Visibility: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_shader_visibility
Root Descriptor
===============
As noted in the table above, the first operand will denote the type of
root descriptor.
.. code-block:: LLVM
!5 = { !"RootCBV", i32 0, i32 1, i32 0, i32 0 }
======================== ====
Description Type
======================== ====
`Shader Visibility`_ i32
Shader Register i32
Register Space i32
`Root Descriptor Flags`_ i32
======================== ====
.. _Root Descriptor Flags: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_root_descriptor_flags
Static Sampler
==============
.. code-block:: LLVM
!6 = !{ !"StaticSampler", i32 1, i32 4, ... }; remaining operands omitted for space
==================== =====
Description Type
==================== =====
`Filter`_ i32
`AddressU`_ i32
`AddressV`_ i32
`AddressW`_ i32
MipLODBias float
MaxAnisotropy i32
`ComparisonFunc`_ i32
`BorderColor`_ i32
MinLOD float
MaxLOD float
ShaderRegister i32
RegisterSpace i32
`Shader Visibility`_ i32
==================== =====
.. _Filter: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_filter
.. _AddressU: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode
.. _AddressV: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode
.. _AddressW: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_texture_address_mode
.. _ComparisonFunc: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_comparison_func>
.. _BorderColor: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_static_border_color>
Descriptor Table
================
A descriptor table consists of a visibility and the remaining operands are a
list of references to its descriptor ranges.
.. note::
The term Descriptor Table Clause is synonymous with Descriptor Range when
referencing the implementation details.
.. code-block:: LLVM
!7 = { !"DescriptorTable", i32 0, !8, !9 }
========================= ================
Description Type
========================= ================
`Shader Visibility`_ i32
Descriptor Range Elements Descriptor Range
========================= ================
Descriptor Range
================
Similar to a root descriptor, the first operand will denote the type of
descriptor range. It is one of the following types:
- "CBV"
- "SRV"
- "UAV"
- "Sampler"
.. code-block:: LLVM
!8 = !{ !"SRV", i32 1, i32 0, i32 0, i32 -1, i32 4 }
!9 = !{ !"UAV", i32 5, i32 1, i32 10, i32 5, i32 2 }
============================== ====
Description Type
============================== ====
Number of Descriptors in Range i32
Shader Register i32
Register Space i32
`Offset`_ i32
`Descriptor Range Flags`_ i32
============================== ====
.. _Offset: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_descriptor_range
.. _Descriptor Range Flags: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_descriptor_range_flags
|