Skip to content

Commit 8d87631

Browse files
authored
Add separate experimental DXIL op table using high OpCode bit (#7947)
Implements: https://github.com/microsoft/hlsl-specs/blob/main/proposals/0052-experimental-dxil-ops.md This change adds support for an experimental DXIL operation table, which provides an independent numeric space from the main OpCode set. It adds support for indexing into OpCode tables using the high 16-bits as the table index, and the low 16-bits as the index into the OpCode table. While the fundamental change could support more tables for individual experimental features or extensions, it's currently limited to tables `0` for `CoreOps` and `0x8000` for `ExperimentalOps` without additional work to unlock more tables. This maps to the existing opcodes for `CoreOps` and opcodes with the high bit set for `ExperimentalOps`. Now, db_dxil_op_table manages dxil op lists, and DXIL ops are built using table methods.
1 parent f687155 commit 8d87631

File tree

14 files changed

+703
-164
lines changed

14 files changed

+703
-164
lines changed

docs/DXIL.rst

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2111,6 +2111,8 @@ Opcodes are defined on a dense range and will be provided as enum in a header fi
21112111
.. <py::lines('OPCODES-RST')>hctdb_instrhelp.get_opcodes_rst()</py>
21122112
.. OPCODES-RST:BEGIN
21132113
2114+
Opcode Table CoreOps, id=0: Core DXIL operations
2115+
21142116
=== ===================================================== =======================================================================================================================================================================================================================
21152117
ID Name Description
21162118
=== ===================================================== =======================================================================================================================================================================================================================
@@ -3055,6 +3057,18 @@ Given width, offset:
30553057
ushr dest, src2, offset
30563058
}
30573059
3060+
3061+
3062+
3063+
Opcode Table ExperimentalOps, id=32768: Experimental DXIL operations
3064+
3065+
========== =============== ================
3066+
ID Name Description
3067+
========== =============== ================
3068+
2147483648 ExperimentalNop nop does nothing
3069+
========== =============== ================
3070+
3071+
30583072
.. OPCODES-RST:END
30593073
30603074
@@ -3134,10 +3148,11 @@ INSTR.CREATEHANDLEIMMRANGEID Local resource mus
31343148
INSTR.DXILSTRUCTUSER Dxil struct types should only be used by ExtractValue.
31353149
INSTR.DXILSTRUCTUSEROUTOFBOUND Index out of bound when extract value from dxil struct types.
31363150
INSTR.EVALINTERPOLATIONMODE Interpolation mode on %0 used with eval_* instruction must be linear, linear_centroid, linear_noperspective, linear_noperspective_centroid, linear_sample or linear_noperspective_sample.
3151+
INSTR.EXPDXILOPCODEREQUIRESEXPSM Use of experimental DXILOpCode requires an experimental shader model.
31373152
INSTR.EXTRACTVALUE ExtractValue should only be used on dxil struct types and cmpxchg.
31383153
INSTR.FAILTORESLOVETGSMPOINTER TGSM pointers must originate from an unambiguous TGSM global variable.
31393154
INSTR.HANDLENOTFROMCREATEHANDLE Resource handle should returned by createHandle.
3140-
INSTR.ILLEGALDXILOPCODE DXILOpCode must be [0..%0]. %1 specified.
3155+
INSTR.ILLEGALDXILOPCODE DXILOpCode must be valid or a supported experimental opcode.
31413156
INSTR.ILLEGALDXILOPFUNCTION '%0' is not a DXILOpFuncition for DXILOpcode '%1'.
31423157
INSTR.IMMBIASFORSAMPLEB bias amount for sample_b must be in the range [%0,%1], but %2 was specified as an immediate.
31433158
INSTR.INBOUNDSACCESS Access to out-of-bounds memory is disallowed.

include/dxc/DXIL/DxilConstants.h

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,10 +490,44 @@ inline bool IsFeedbackTexture(DXIL::ResourceKind ResourceKind) {
490490
ResourceKind == DXIL::ResourceKind::FeedbackTexture2DArray;
491491
}
492492

493+
// clang-format off
494+
// Python lines need to be not formatted.
495+
/* <py::lines('OPCODETABLE-ENUM')>hctdb_instrhelp.get_enum_decl("OpCodeTableID")</py>*/
496+
// clang-format on
497+
// OPCODETABLE-ENUM:BEGIN
498+
// Enumeration for DXIL opcode tables
499+
enum class OpCodeTableID : unsigned {
500+
CoreOps = 0, // Core DXIL operations
501+
ExperimentalOps = 32768, // Experimental DXIL operations
502+
};
503+
// OPCODETABLE-ENUM:END
504+
505+
// clang-format off
506+
// Python lines need to be not formatted.
507+
/* <py::lines('EXTOPCODES-ENUM')>hctdb_instrhelp.get_extended_table_opcode_enum_decls()</py>*/
508+
// clang-format on
509+
// EXTOPCODES-ENUM:BEGIN
510+
namespace ExperimentalOps {
511+
static const OpCodeTableID TableID = OpCodeTableID::ExperimentalOps;
512+
// Enumeration for ExperimentalOps DXIL operations
513+
enum class OpCode : unsigned {
514+
// No-op
515+
ExperimentalNop = 0, // nop does nothing
516+
517+
NumOpCodes = 1, // exclusive last value of enumeration
518+
};
519+
} // namespace ExperimentalOps
520+
static const unsigned NumOpCodeTables = 2;
521+
// EXTOPCODES-ENUM:END
522+
523+
#define EXP_OPCODE(feature, opcode) \
524+
opcode = \
525+
(((unsigned)feature::TableID << 16) | (unsigned)feature::OpCode::opcode)
526+
493527
// TODO: change opcodes.
494528
/* <py::lines('OPCODE-ENUM')>hctdb_instrhelp.get_enum_decl("OpCode")</py>*/
495529
// OPCODE-ENUM:BEGIN
496-
// Enumeration for operations specified by DXIL
530+
// Enumeration for CoreOps DXIL operations
497531
enum class OpCode : unsigned {
498532
//
499533
Reserved0 = 226, // reserved
@@ -1089,9 +1123,23 @@ enum class OpCode : unsigned {
10891123
NumOpCodes_Dxil_1_8 = 258,
10901124
NumOpCodes_Dxil_1_9 = 312,
10911125

1092-
NumOpCodes = 312 // exclusive last value of enumeration
1126+
NumOpCodes = 312, // exclusive last value of enumeration
1127+
Invalid = 0xFFFFFFFF, // stable invalid OpCode value
1128+
1129+
// OpCodes for extended tables follow.
1130+
1131+
// OpCodeTableID = 32768
1132+
// ExperimentalOps
1133+
EXP_OPCODE(ExperimentalOps, ExperimentalNop), // nop does nothing
10931134
};
10941135
// OPCODE-ENUM:END
1136+
#undef EXP_OPCODE
1137+
1138+
// Create Core namespace for consistency with other opcode groups
1139+
namespace CoreOps {
1140+
static const OpCodeTableID TableID = OpCodeTableID::CoreOps;
1141+
using OpCode = hlsl::DXIL::OpCode;
1142+
} // namespace CoreOps
10951143

10961144
// clang-format off
10971145
// Python lines need to be not formatted.
@@ -1244,6 +1292,9 @@ enum class OpCodeClass : unsigned {
12441292
StorePrimitiveOutput,
12451293
StoreVertexOutput,
12461294

1295+
// No-op
1296+
Nop,
1297+
12471298
// Other
12481299
CycleCounterLegacy,
12491300

@@ -1414,7 +1465,7 @@ enum class OpCodeClass : unsigned {
14141465
NodeOutputIsValid,
14151466
OutputComplete,
14161467

1417-
NumOpClasses = 196 // exclusive last value of enumeration
1468+
NumOpClasses = 197, // exclusive last value of enumeration
14181469
};
14191470
// OPCODECLASS-ENUM:END
14201471

include/dxc/DXIL/DxilInstructions.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10231,5 +10231,25 @@ struct DxilInst_FDot {
1023110231
llvm::Value *get_b() const { return Instr->getOperand(2); }
1023210232
void set_b(llvm::Value *val) { Instr->setOperand(2, val); }
1023310233
};
10234+
10235+
/// This instruction nop does nothing
10236+
struct DxilInst_ExperimentalNop {
10237+
llvm::Instruction *Instr;
10238+
// Construction and identification
10239+
DxilInst_ExperimentalNop(llvm::Instruction *pInstr) : Instr(pInstr) {}
10240+
operator bool() const {
10241+
return hlsl::OP::IsDxilOpFuncCallInst(Instr,
10242+
hlsl::OP::OpCode::ExperimentalNop);
10243+
}
10244+
// Validation support
10245+
bool isAllowed() const { return true; }
10246+
bool isArgumentListValid() const {
10247+
if (1 != llvm::dyn_cast<llvm::CallInst>(Instr)->getNumArgOperands())
10248+
return false;
10249+
return true;
10250+
}
10251+
// Metadata
10252+
bool requiresUniformInputs() const { return false; }
10253+
};
1023410254
// INSTR-HELPER:END
1023510255
} // namespace hlsl

include/dxc/DXIL/DxilOperations.h

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class OP {
3737
public:
3838
using OpCode = DXIL::OpCode;
3939
using OpCodeClass = DXIL::OpCodeClass;
40+
using OpCodeTableID = DXIL::OpCodeTableID;
4041

4142
public:
4243
OP() = delete;
@@ -131,6 +132,7 @@ class OP {
131132
llvm::Constant *GetFloatConst(float v);
132133
llvm::Constant *GetDoubleConst(double v);
133134

135+
static OP::OpCode getOpCode(unsigned OpCode);
134136
static OP::OpCode getOpCode(const llvm::Instruction *I);
135137
static llvm::Type *GetOverloadType(OpCode OpCode, llvm::Function *F);
136138
static OpCode GetDxilOpFuncCallInst(const llvm::Instruction *I);
@@ -226,8 +228,7 @@ class OP {
226228
std::unordered_map<const llvm::Function *, OpCodeClass> m_FunctionToOpClass;
227229
void UpdateCache(OpCodeClass opClass, llvm::Type *Ty, llvm::Function *F);
228230

229-
private:
230-
// Static properties.
231+
public:
231232
struct OverloadMask {
232233
// mask of type slot bits as (1 << TypeSlot)
233234
uint16_t SlotMask;
@@ -255,7 +256,31 @@ class OP {
255256
// AllowedOverloads[n][TS_Vector] is true.
256257
OverloadMask AllowedVectorElements[DXIL::kDxilMaxOloadDims];
257258
};
258-
static const OpCodeProperty m_OpCodeProps[(unsigned)OpCode::NumOpCodes];
259+
struct OpCodeTable {
260+
OpCodeTableID ID;
261+
const OpCodeProperty *Table;
262+
unsigned Count;
263+
};
264+
265+
// Look up table using high 16-bits as table ID, low 16-bits as OpCode.
266+
// Return true if valid.
267+
// unsigned versions are for use with whatever value was in a DXIL Op
268+
// instruction.
269+
// OpIndex is the low 16-bits, for index lookup within the table.
270+
static bool DecodeOpCode(unsigned EncodedOpCode, OpCodeTableID &TableID,
271+
unsigned &OpIndex,
272+
unsigned *OptTableIndex = nullptr);
273+
static bool DecodeOpCode(OpCode EncodedOpCode, OpCodeTableID &TableID,
274+
unsigned &OpIndex,
275+
unsigned *OptTableIndex = nullptr);
276+
static bool IsValidOpCode(unsigned EncodedOpCode);
277+
static bool IsValidOpCode(OpCode EncodedOpCode);
278+
279+
private:
280+
// Static properties.
281+
static OpCodeTable g_OpCodeTables[DXIL::NumOpCodeTables];
282+
static const OpCodeProperty &GetOpCodeProps(unsigned opCode);
283+
static const OpCodeProperty &GetOpCodeProps(OpCode opCode);
259284

260285
static const char *m_OverloadTypeName[TS_BasicCount];
261286
static const char *m_NamePrefix;

include/dxc/DXIL/DxilShaderModel.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ class ShaderModel {
6666
bool IsSMAtLeast(unsigned Major, unsigned Minor) const {
6767
return m_Major > Major || (m_Major == Major && m_Minor >= Minor);
6868
}
69+
bool IsPreReleaseShaderModel() const {
70+
return IsPreReleaseShaderModel(m_Major, m_Minor);
71+
}
6972
bool IsSM50Plus() const { return IsSMAtLeast(5, 0); }
7073
bool IsSM51Plus() const { return IsSMAtLeast(5, 1); }
7174
bool AllowDerivatives(DXIL::ShaderKind sk) const;

0 commit comments

Comments
 (0)