161 lines
7.2 KiB
ReStructuredText
161 lines
7.2 KiB
ReStructuredText
==============================================================
|
|
Specification of DXIL Operations using TableGen Representation
|
|
==============================================================
|
|
.. contents::
|
|
:local:
|
|
|
|
.. toctree
|
|
:hidden
|
|
|
|
Introduction
|
|
============
|
|
|
|
`DirectXShaderCompiler <https://github.com/microsoft/DirectXShaderCompiler>`_
|
|
encapsulates, among other information, various DXIL Operations in
|
|
`hctdb.py <https://github.com/microsoft/DirectXShaderCompiler/blob/main/utils/hct/hctdb.py>`_.
|
|
DXIL Operations are represented in one of the following `two ways
|
|
<https://github.com/microsoft/DirectXShaderCompiler/blob/130877392c263888ef06bab768856d3dab1f1c9a/docs/DXIL.rst#L1978>`_:
|
|
|
|
#. Using LLVM instructions.
|
|
#. Using LLVM External functions. These are represented in LLVM IR as follows:
|
|
* "Standard" LLVM intrinsics (e.g., ``llvm.sin.*``) and
|
|
* HLSL intrinsics (defined as LLVM intrinsics in ``llvm/include/llvm/IR/IntrinsicsDirectX.td``, e.g., ``llvm.dx.*``)
|
|
|
|
These are collectively referred to as `LLVM Intrinsics` in this note.
|
|
|
|
Following is the complete list of properties of DXIL Ops with the corresponding field name
|
|
as used in ``hctdb.py``. A DXIL Op is represented by a set of associated properties. These
|
|
are categorized into two groups - viz., those that are (1) consumed in DXIL backend passes
|
|
and (2) consumed in other usage scenarios such as validation, DXIL reader, etc.
|
|
|
|
A. Properties consumed in DXIL backend passes
|
|
|
|
1. Name of operation (``dxil_op``)
|
|
2. The generic or HLSL-specific intrinsic that maps to the operation (``llvm_name``).
|
|
3. Unique Integer ID (``dxil_opid``)
|
|
4. Operation Class signifying the name and function signature of the operation (``dxil_class``).
|
|
This string is an integral part of the DXIL Op function name and is constructed in
|
|
the format ``dx.op.<class-name>.<overload-type>``. The DXIL validator checks for any
|
|
deviation from this for each of the DXIL Op call.
|
|
5. List of valid overload types for the operation (``oload_types``).
|
|
6. Required DXIL Version with support for the operation.
|
|
7. A string that documents the operation (``doc``) - This is not strictly necessary but is included
|
|
for readability and documentation of the operation.
|
|
|
|
B. Properties consumed in other usage scenarios
|
|
|
|
1. Required minimum Shader Model (``shader_model``).
|
|
2. Minimum shader model required with translation by linker (``shader_model_translated``)
|
|
3. List of shader stages applicable to (``shader_stages``), empty for all.
|
|
4. Memory access attributes of the operation (``fn_attr``).
|
|
5. Boolean attributes of operation to indicate if it
|
|
|
|
* is some kind of a derivative (``is_derivative``)
|
|
* requires gradient calculation (``is_gradient``)
|
|
* is a sampler feedback (``is_feedback``)
|
|
* requires in-wave, cross-lane functionality (``is_wave``)
|
|
* requires that all of its inputs are uniform across the wave (``requires_uniform_inputs``).
|
|
* is a barrier operation (``is_barrier``).
|
|
|
|
Motivation
|
|
==========
|
|
|
|
DXIL backend passes depend on various properties of DXIL Operations. For example, ``DXILLowering``
|
|
pass will need information such as the DXIL operation an LLVM intrinsic is to be lowered to,
|
|
along with valid overload and parameter types etc. The TableGen file -
|
|
``llvm/lib/Target/DirectX/DXIL.td`` - is used to represent DXIL Operations
|
|
by specifying their properties listed above. ``DXIL.td`` is designed to be the single source
|
|
of reference of DXIL Operations for DXIL backend implementation in ``llvm-project`` repo -
|
|
analogous to ``hctdb.py`` for ``DirectXShadeCompiler`` repo. It needs to have a rich
|
|
representation capabilities that TableGen backends (such as ``DXILEmitter``) can rely on.
|
|
Additionally, the DXIL Op specification should be easy to read and comprehend.
|
|
|
|
This note focuses on specification of the set of properties consumed by DXIL backend
|
|
passes identified above in category A. Any of the properties from category B are expected to be
|
|
included as deemed necessary during implementation.
|
|
|
|
Design
|
|
======
|
|
|
|
1. Each DXIL Operation is represented as a TableGen record. The name of each of the records
|
|
signifies operation name.
|
|
2. The LLVM Intrinsic that maps to the operation is represented using ``Intrinsic::*``.
|
|
3. The unique operation id is represented by an integer.
|
|
4. DXIL Operation Class is represented as follows
|
|
|
|
.. code-block::
|
|
|
|
// Abstraction of DXIL Operation class.
|
|
// It encapsulates an associated function signature viz.,
|
|
// returnTy(param1Ty, param2Ty, ...) represented as a list of LLVMTypes.
|
|
// DXIL Ops that belong to a DXILOpClass record the signature of that DXILOpClass
|
|
|
|
class DXILOpClass<list<LLVMType> OpSig> {
|
|
list<LLVMType> OpSignature = OpSig;
|
|
}
|
|
|
|
Concrete operation classes, such as ``unary`` are defined inheriting from ``DXILOpClass``.
|
|
5. Valid overload types are represented as a list of ``LLVMType``.
|
|
6. Concrete records of DXIL versions and are defined by inheriting from the class
|
|
|
|
.. code-block::
|
|
|
|
// Abstract class to represent major and minor version values
|
|
class Version<int major, int minor> {
|
|
int Major = major;
|
|
int Minor = minor;
|
|
}
|
|
|
|
7. A documentation string for the operation.
|
|
|
|
|
|
A DXIL Operation is represented by the following TableGen class by encapsulating the various
|
|
TableGen representations of its properties described above.
|
|
|
|
.. code-block::
|
|
|
|
// Abstraction DXIL Operation
|
|
class DXILOpPropertiesBase {
|
|
int OpCode = 0; // Opcode of DXIL Operation
|
|
DXILOpClass OpClass = UnknownOpClass; // Class of DXIL Operation.
|
|
Intrinsic LLVMIntrinsic = ?; // LLVM Intrinsic DXIL Operation maps to
|
|
list<LLVMType> OpOverloadTypes = ?; // Valid overload type
|
|
// of DXIL Operation
|
|
Version DXILVer = ?; // Min DXIL version
|
|
string Doc = ""; // A short description of the operation
|
|
}
|
|
|
|
|
|
The following convenience class, definitions of ``unary`` and ``DXVer1_0`` are used to
|
|
illustrate the definitions of ``Sin`` and ``Cos`` operations:
|
|
|
|
.. code-block::
|
|
|
|
class DXILOpProperties<int opCode,
|
|
Intrinsic intrinsic,
|
|
list<LLVMType> overloadTypes,
|
|
string doc> : DXILOpPropertiesBase {
|
|
int OpCode = opCode;
|
|
Intrinsic LLVMIntrinsic = intrinsic;
|
|
list<LLVMType> OpOverloadTypes = overloadTypes;
|
|
string Doc = doc;
|
|
}
|
|
|
|
def unary : DXILOpClass<[llvm_any_ty, LLVMMatchType<0>]>;
|
|
def DXVer1_0 : Version<1, 0>;
|
|
|
|
let OpClass = unary, DXILVer = DXVer1_0 in {
|
|
def Cos : DXILOpProperties<12, int_cos, [llvm_half_ty, llvm_float_ty],
|
|
"Returns cosine(theta) for theta in radians.">;
|
|
def Sin : DXILOpProperties<13, int_sin, [llvm_half_ty, llvm_float_ty],
|
|
"Returns sine(theta) for theta in radians.">;
|
|
}
|
|
|
|
Summary
|
|
=======
|
|
|
|
This note sketches the design of a readable and maintainable TableGen specification of
|
|
DXIL Ops in ``DXIL.td`` intended to serve as a single source of reference for TableGen
|
|
backends (such as ``DXILEmitter``) that generates C++ representations used in DXIL
|
|
backend passes.
|