@@ -14,147 +14,274 @@ Introduction
14
14
encapsulates, among other information, various DXIL Operations in
15
15
`hctdb.py <https://github.com/microsoft/DirectXShaderCompiler/blob/main/utils/hct/hctdb.py >`_.
16
16
DXIL Operations are represented in one of the following `two ways
17
- <https://github.com/microsoft/DirectXShaderCompiler/blob/130877392c263888ef06bab768856d3dab1f1c9a /docs/DXIL.rst#L1978 > `_:
17
+ <https://github.com/microsoft/DirectXShaderCompiler/blob/main /docs/DXIL.rst#operations > `_:
18
18
19
19
#. Using LLVM instructions.
20
20
#. Using LLVM External functions. These are represented in LLVM IR as follows:
21
+
21
22
* "Standard" LLVM intrinsics (e.g., ``llvm.sin.* ``) and
22
23
* HLSL intrinsics (defined as LLVM intrinsics in ``llvm/include/llvm/IR/IntrinsicsDirectX.td ``, e.g., ``llvm.dx.* ``)
23
24
24
25
These are collectively referred to as `LLVM Intrinsics ` in this note.
25
26
26
- Following is the complete list of properties of DXIL Ops with the corresponding field name
27
- as used in ``hctdb.py ``. A DXIL Op is represented by a set of associated properties . These
28
- are categorized into two groups - viz., those that are (1) consumed in DXIL backend passes
29
- and (2) consumed in other usage scenarios such as validation, DXIL reader, etc.
27
+ Following is the complete list of attributes of DXIL Ops with the corresponding field name
28
+ as used in ``hctdb.py ``. A DXIL Op is represented by a set of associated attributes . These
29
+ are consumed in DXIL backend passes as well as in other usage scenarios such as validation,
30
+ DXIL reader, etc.
30
31
31
- A. Properties consumed in DXIL backend passes
32
+ A. Attributes consumed in DXIL backend passes
32
33
33
34
1. Name of operation (``dxil_op ``)
34
- 2. The generic or HLSL-specific intrinsic that maps to the operation (``llvm_name ``).
35
- 3. Unique Integer ID (``dxil_opid ``)
36
- 4. Operation Class signifying the name and function signature of the operation (``dxil_class ``).
37
- This string is an integral part of the DXIL Op function name and is constructed in
38
- the format ``dx.op.<class-name>.<overload-type> ``. The DXIL validator checks for any
39
- deviation from this for each of the DXIL Op call.
40
- 5. List of valid overload types for the operation (``oload_types ``).
41
- 6. Required DXIL Version with support for the operation.
42
- 7. A string that documents the operation (``doc ``) - This is not strictly necessary but is included
35
+ 2. A string that documents the operation (``doc ``) - This is not strictly necessary but is included
43
36
for readability and documentation of the operation.
44
-
45
- B. Properties consumed in other usage scenarios
46
-
47
- 1. Required minimum Shader Model (``shader_model ``).
48
- 2. Minimum shader model required with translation by linker (``shader_model_translated ``)
49
- 3. List of shader stages applicable to (``shader_stages ``), empty for all.
50
- 4. Memory access attributes of the operation (``fn_attr ``).
51
- 5. Boolean attributes of operation to indicate if it
52
-
53
- * is some kind of a derivative (``is_derivative ``)
54
- * requires gradient calculation (``is_gradient ``)
55
- * is a sampler feedback (``is_feedback ``)
56
- * requires in-wave, cross-lane functionality (``is_wave ``)
57
- * requires that all of its inputs are uniform across the wave (``requires_uniform_inputs ``).
58
- * is a barrier operation (``is_barrier ``).
37
+ 3. The generic or HLSL-specific intrinsic that maps to the operation (``llvm_name ``).
38
+ 4. Unique Integer ID (``dxil_opid ``)
39
+ 5. Operation Class signifying the name and function signature of the operation (``dxil_class ``).
40
+ This string is an integral part of the DXIL Op function name and is constructed in
41
+ the format ``dx.op.<class-name>.<overload-type> ``. Each DXIL Op call target function name
42
+ is required to conform to this format per existing contract with the driver.
43
+ 6. List of valid overload types for the operation (``oload_types ``).
44
+ 7. Required DXIL Version with support for the operation.
45
+ 8. Required minimum Shader Model (``shader_model ``).
46
+ 9. Minimum shader model required with translation by linker (``shader_model_translated ``)
47
+ 10. List of shader stages applicable to (``shader_stages ``), empty, if applicable to all stages.
48
+ 11. Memory access attributes of the operation (``fn_attr ``).
49
+ 12. Boolean attributes of operation to indicate if it
50
+
51
+ * is some kind of a derivative (``is_derivative ``)
52
+ * requires gradient calculation (``is_gradient ``)
53
+ * is a sampler feedback (``is_feedback ``)
54
+ * requires in-wave, cross-lane functionality (``is_wave ``)
55
+ * requires that all of its inputs are uniform across the wave (``requires_uniform_inputs ``).
56
+ * is a barrier operation (``is_barrier ``).
59
57
60
58
Motivation
61
59
==========
62
60
63
- DXIL backend passes depend on various properties of DXIL Operations. For example, ``DXILLowering ``
61
+ DXIL backend passes depend on various attributes of DXIL Operations. For example, ``DXILOpLowering ``
64
62
pass will need information such as the DXIL operation an LLVM intrinsic is to be lowered to,
65
63
along with valid overload and parameter types etc. The TableGen file -
66
64
``llvm/lib/Target/DirectX/DXIL.td `` - is used to represent DXIL Operations
67
- by specifying their properties listed above. ``DXIL.td `` is designed to be the single source
68
- of reference of DXIL Operations for DXIL backend implementation in ``llvm-project `` repo -
69
- analogous to ``hctdb.py `` for ``DirectXShadeCompiler `` repo. It needs to have a rich
70
- representation capabilities that TableGen backends (such as ``DXILEmitter ``) can rely on.
71
- Additionally, the DXIL Op specification should be easy to read and comprehend.
65
+ by specifying their attributes listed above. ``DXIL.td `` is designed to be the single source
66
+ of reference of DXIL Operations primarily for the implementation of passes in DXIL backend in
67
+ ``llvm-project `` repo - analogous to ``hctdb.py `` for ``DirectXShadeCompiler `` repo. However,
68
+ the current design does not intend to encapsulate various validation rules, present in ``hctdb.py ``,
69
+ but do not pertain to DXIL Operations. It needs to have a rich representation capabilities that
70
+ TableGen backends (such as ``DXILEmitter ``) can rely on. Additionally, the DXIL Op specification
71
+ should be easy to read and comprehend.
72
72
73
- This note focuses on specification of the set of properties consumed by DXIL backend
74
- passes identified above in category A. Any of the properties from category B are expected to be
75
- included as deemed necessary during implementation.
73
+ This note provides the design of the specification DXIL Ops as TableGen class ``DXILOp ``
74
+ by specifying its attributes identified above.
76
75
77
- Design
78
- ======
76
+ DXIL Operation Specification
77
+ ============================
78
+
79
+ The DXIL Operation is represented using the TableGen class ``DXILOp ``. The DXIL operation
80
+ attributes are specified as fields of the ``DXILOp `` class as described below.
79
81
80
82
1. Each DXIL Operation is represented as a TableGen record. The name of each of the records
81
83
signifies operation name.
82
- 2. The LLVM Intrinsic that maps to the operation is represented using ``Intrinsic::* ``.
83
- 3. The unique operation id is represented by an integer.
84
- 4. DXIL Operation Class is represented as follows
84
+ 2. A documentation string for the operation.
85
+ 3. The LLVM Intrinsic that maps to the operation is represented as ``Intrinsic `` defined in
86
+ `Intrinsics.td <https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/Intrinsics.td >`_.
87
+ 4. The unique operation id is represented by an integer.
88
+ 5. DXIL Operation Class is represented as follows
85
89
86
90
.. code-block ::
87
91
88
92
// Abstraction of DXIL Operation class.
89
- // It encapsulates an associated function signature viz.,
90
- // returnTy(param1Ty, param2Ty, ...) represented as a list of LLVMTypes.
91
- // DXIL Ops that belong to a DXILOpClass record the signature of that DXILOpClass
92
-
93
- class DXILOpClass<list<LLVMType> OpSig> {
94
- list<LLVMType> OpSignature = OpSig;
95
- }
93
+ class DXILOpClass;
96
94
97
- Concrete operation classes, such as ``unary `` are defined inheriting from ``DXILOpClass ``.
98
- 5. Valid overload types are represented as a list of ``LLVMType ``.
99
- 6. Concrete records of DXIL versions and are defined by inheriting from the class
95
+ Concrete operation records, such as ``unary `` are defined by inheriting from ``DXILOpClass ``.
96
+ 6. Return and argument types of the operation are represented as ``dag``s using the
97
+ special markers ``out `` and ``ins ``. An overload type, if supported by the operation, is
98
+ denoted as the positional type ``dxil_overload_ty `` in the argument or in the result, where
99
+ ``dxil_overload_ty `` is defined to be synonymous to ``llvm_any_ty ``.
100
100
101
101
.. code-block ::
102
102
103
- // Abstract class to represent major and minor version values
104
- class Version<int major, int minor> {
105
- int Major = major;
106
- int Minor = minor;
107
- }
103
+ defvar dxil_overload_ty = llvm_any_ty
108
104
109
- 7. A documentation string for the operation.
110
105
106
+ 7. Valid overload types and shader stages predicated on Shader Model version are specified
107
+ as a list of ``Constraint `` records. Representation of ``Constraints `` class is described
108
+ a later section.
109
+ 8. Various attributes of the DXIL Operation that are not predicated on Shader Model version
110
+ are represented as a ``dag `` using the special marker ``attrs ``. Representation of ``Attributes ``
111
+ class is described in a later section.
111
112
112
113
A DXIL Operation is represented by the following TableGen class by encapsulating the various
113
- TableGen representations of its properties described above.
114
+ TableGen representations of its attributes described above.
114
115
115
116
.. code-block ::
116
117
117
- // Abstraction DXIL Operation
118
- class DXILOpPropertiesBase {
119
- int OpCode = 0; // Opcode of DXIL Operation
120
- DXILOpClass OpClass = UnknownOpClass; // Class of DXIL Operation.
121
- Intrinsic LLVMIntrinsic = ?; // LLVM Intrinsic DXIL Operation maps to
122
- list<LLVMType> OpOverloadTypes = ?; // Valid overload type
123
- // of DXIL Operation
124
- Version DXILVer = ?; // Min DXIL version
125
- string Doc = ""; // A short description of the operation
126
- }
118
+ // Abstraction DXIL Operation
119
+ class DXILOp {
120
+ // A short description of the operation
121
+ string Doc = "";
122
+
123
+ // Opcode of DXIL Operation
124
+ int OpCode = 0;
125
+
126
+ // Class of DXIL Operation.
127
+ DXILOpClass OpClass = UnknownOpClass;
128
+
129
+ // LLVM Intrinsic DXIL Operation maps to
130
+ Intrinsic LLVMIntrinsic = ?;
127
131
132
+ // Dag containing the arguments of the op. Default to 0 arguments.
133
+ dag arguments = (ins);
128
134
129
- The following convenience class, definitions of `` unary `` and `` DXVer1_0 `` are used to
130
- illustrate the definitions of `` Sin `` and `` Cos `` operations:
135
+ // Results of the op. Default to 0 results.
136
+ dag result = (out);
131
137
132
- .. code-block ::
138
+ // List of constraints predicated on Shader Model version
139
+ list<SMVersionConstraints> sm_constraints;
133
140
134
- class DXILOpProperties<int opCode,
135
- Intrinsic intrinsic,
136
- list<LLVMType> overloadTypes,
137
- string doc> : DXILOpPropertiesBase {
138
- int OpCode = opCode;
139
- Intrinsic LLVMIntrinsic = intrinsic;
140
- list<LLVMType> OpOverloadTypes = overloadTypes;
141
- string Doc = doc;
142
- }
141
+ // Non-predicated operation attributes
142
+ dag attrtibutes = (attrs);
143
+ Version DXILVersion = ?;
144
+ }
143
145
144
- def unary : DXILOpClass<[llvm_any_ty, LLVMMatchType<0>]>;
145
- def DXVer1_0 : Version<1, 0>;
146
+ Constraint Specification
147
+ ========================
148
+
149
+ DXIL Operation attributes such as valid overload types and valid shader stages are
150
+ predicated on Shader Model version. These are represented as list of constrained
151
+ attributes.
152
+
153
+ Following is the definition of a generic constraint and the associated predicate
154
+
155
+ .. code-block ::
156
+
157
+ // Primitive predicate
158
+ class Pred;
159
+
160
+ // Generic constraint
161
+ class Constraint<Pred pred> {
162
+ Pred predicate = pred;
163
+ }
164
+
165
+ Shader Model version is represented as follows:
166
+
167
+ .. code-block ::
168
+
169
+ // Abstract class to represent major and minor version values
170
+ class Version<int major, int minor> {
171
+ int Major = major;
172
+ int Minor = minor;
173
+ }
174
+
175
+ // Valid Shader model version records
176
+
177
+ // Definition of Shader Model 6.0 - 6.8 and DXIL Version 1.0 - 1.8
178
+ foreach i = 0...8 in {
179
+ def SM6_#i : Version<6, i>;
180
+ def DX1_#i : Version<1, i>;
181
+ }
182
+
183
+ A shader model version predicate class is defined as
184
+
185
+ .. code-block ::
186
+
187
+ class SMVersion<Version ver> : Pred {
188
+ Version SMVersion = ver;
189
+ }
190
+
191
+ A constraint class to represent overload types and shader stages predicated on shader
192
+ model version is defined as
193
+
194
+ .. code-block ::
146
195
147
- let OpClass = unary, DXILVer = DXVer1_0 in {
148
- def Cos : DXILOpProperties<12, int_cos, [llvm_half_ty, llvm_float_ty],
149
- "Returns cosine(theta) for theta in radians.">;
150
- def Sin : DXILOpProperties<13, int_sin, [llvm_half_ty, llvm_float_ty],
151
- "Returns sine(theta) for theta in radians.">;
152
- }
196
+ class SMVersionConstraints<SMVersion smver, dag oloads, dag stages> : Constraint<smver> {
197
+ dag overload_types = oloads;
198
+ dag stage_kinds = stages;
199
+ }
200
+
201
+ The ``dag overload_types `` and ``dag shader_kinds `` use a special markers ``overloads ``
202
+ and ``stages ``, respectively.
203
+
204
+ Examples of Constraints
205
+ -----------------------
206
+
207
+ Consider a DXIL Operation that is valid in Shader Model 6.2 and later,
208
+
209
+ 1. with valid overload types ``half ``, ``float ``, ``i16 `` and ``i32 ``
210
+ 2. is valid for stages ``pixel `` and ``compute ``
211
+ 3. with valid overload types ``double `` and ``i614 `` if Shader Model version 6.3 and later
212
+ 4. is valid for all stages if Shader Model version 6.3 and later
213
+
214
+ This is represented as
215
+
216
+ .. code-block ::
217
+
218
+ [SMVersionConstraints<SMVersion<SM6_2>,
219
+ (overloads llvm_half_ty, llvm_float_ty, llvm_i16_ty, llvm_i32_ty),
220
+ (stages pixel, compute)>,
221
+ SMVersionConstraints<SMVersion<SM6_3>,
222
+ (overloads llvm_half_ty, llvm_float_ty, llvm_double_ty,
223
+ llvm_i16_ty, llvm_i32_ty, llvm_i64_ty),
224
+ (stages allKinds)>];
225
+
226
+ Consider a DXIL operation that is valid in Shader Model version 6.2 and later,
227
+
228
+ 1. with no overload types, i.e., all argument typess and result type are fixed.
229
+ 2. is valid for all stages.
230
+
231
+ This is represented as
232
+
233
+ .. code-block ::
234
+
235
+ [SMVersionConstraints<SMVersion<SM6_2>, (overloads), (stages allKinds)>];
236
+
237
+
238
+ Specifying attributes predicated on Shader Model version using the single field
239
+ ``sm_constraints `` not only allows for all of them to be specified together but
240
+ also allows for a single place to specify minimum shader model version that supports
241
+ the operation. Thus, a separate fiels is not needed to specify minimum shader model
242
+ version.
243
+
244
+ Attribute Specification
245
+ =======================
246
+
247
+ DXIL Operation attributes that are not predicated on any constraint, are represented as
248
+ a ``dag `` of Attribute records of the following abstract ``DXILAttributes `` class.
249
+
250
+ .. code-block ::
251
+
252
+ class DXILAttributes;
253
+
254
+ Following example records represent memory attributes
255
+
256
+ .. code-block ::
257
+
258
+ def ReadOnly : DXILOpAttributes;
259
+ def ReadNone : DXILOpAttributes;
260
+
261
+ DXIL Operation Specification Example
262
+ ====================================
263
+ Following illustrates the specification of the DXIL Op ``Sin ``
264
+
265
+ .. code-block ::
266
+
267
+ def Sin : DXILOp {
268
+ let Doc ="Returns sine(theta) for theta in radians.";
269
+ let OpCode = 13;
270
+ let OpClass = unary;
271
+ let LLVMIntrinsic = int_sin;
272
+ let arguments = (ins LLVMMatchType<0>);
273
+ let result = (out dxil_overload_ty);
274
+ let sm_constraints = [SMVersionConstraints<SMVersion<SM6_0>,
275
+ (overloads llvm_half_ty, llvm_float_ty),
276
+ (stages allKinds)>];
277
+ let attributes = (attrs ReadNone);
278
+ let DXILVersion = DX1_0;
279
+ }
153
280
154
281
Summary
155
282
=======
156
283
157
284
This note sketches the design of a readable and maintainable TableGen specification of
158
285
DXIL Ops in ``DXIL.td `` intended to serve as a single source of reference for TableGen
159
- backends (such as ``DXILEmitter ``) that generates C++ representations used in DXIL
286
+ backends (such as ``DXILEmitter ``) that generate C++ representations used in DXIL
160
287
backend passes.
0 commit comments