Skip to content

[SER] HitObject_MakeNop|Miss DXIL opcodes and verification tests #7201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions include/dxc/DXIL/DxilConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,9 +520,7 @@ enum class OpCode : unsigned {
ReservedB27 = 289, // reserved
ReservedB28 = 290, // reserved
ReservedB29 = 291, // reserved
ReservedB3 = 265, // reserved
ReservedB30 = 292, // reserved
ReservedB4 = 266, // reserved
ReservedB5 = 267, // reserved
ReservedB6 = 268, // reserved
ReservedB7 = 269, // reserved
Expand Down Expand Up @@ -909,6 +907,10 @@ enum class OpCode : unsigned {
WriteSamplerFeedbackLevel = 176, // updates a feedback texture for a sampling
// operation with a mipmap-level offset

// Shader Execution Reordering
HitObject_MakeMiss = 265, // Creates a new HitObject representing a miss
HitObject_MakeNop = 266, // Creates an empty nop HitObject

// Synchronization
AtomicBinOp = 78, // performs an atomic operation on two operands
AtomicCompareExchange = 79, // atomic compare and exchange to memory
Expand Down Expand Up @@ -1281,6 +1283,10 @@ enum class OpCodeClass : unsigned {
WriteSamplerFeedbackGrad,
WriteSamplerFeedbackLevel,

// Shader Execution Reordering
HitObject_MakeMiss,
HitObject_MakeNop,

// Synchronization
AtomicBinOp,
AtomicCompareExchange,
Expand Down Expand Up @@ -1345,7 +1351,7 @@ enum class OpCodeClass : unsigned {
NumOpClasses_Dxil_1_7 = 153,
NumOpClasses_Dxil_1_8 = 174,

NumOpClasses = 175 // exclusive last value of enumeration
NumOpClasses = 177 // exclusive last value of enumeration
};
// OPCODECLASS-ENUM:END

Expand Down
74 changes: 74 additions & 0 deletions include/dxc/DXIL/DxilInstructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -8813,5 +8813,79 @@ struct DxilInst_AllocateRayQuery2 {
llvm::APInt(32, (uint64_t)val)));
}
};

/// This instruction Creates a new HitObject representing a miss
struct DxilInst_HitObject_MakeMiss {
llvm::Instruction *Instr;
// Construction and identification
DxilInst_HitObject_MakeMiss(llvm::Instruction *pInstr) : Instr(pInstr) {}
operator bool() const {
return hlsl::OP::IsDxilOpFuncCallInst(Instr,
hlsl::OP::OpCode::HitObject_MakeMiss);
}
// Validation support
bool isAllowed() const { return true; }
bool isArgumentListValid() const {
if (11 != llvm::dyn_cast<llvm::CallInst>(Instr)->getNumArgOperands())
return false;
return true;
}
// Metadata
bool requiresUniformInputs() const { return false; }
// Operand indexes
enum OperandIdx {
arg_RayFlags = 1,
arg_MissShaderIndex = 2,
arg_Origin_X = 3,
arg_Origin_Y = 4,
arg_Origin_Z = 5,
arg_TMin = 6,
arg_Direction_X = 7,
arg_Direction_Y = 8,
arg_Direction_Z = 9,
arg_TMax = 10,
};
// Accessors
llvm::Value *get_RayFlags() const { return Instr->getOperand(1); }
void set_RayFlags(llvm::Value *val) { Instr->setOperand(1, val); }
llvm::Value *get_MissShaderIndex() const { return Instr->getOperand(2); }
void set_MissShaderIndex(llvm::Value *val) { Instr->setOperand(2, val); }
llvm::Value *get_Origin_X() const { return Instr->getOperand(3); }
void set_Origin_X(llvm::Value *val) { Instr->setOperand(3, val); }
llvm::Value *get_Origin_Y() const { return Instr->getOperand(4); }
void set_Origin_Y(llvm::Value *val) { Instr->setOperand(4, val); }
llvm::Value *get_Origin_Z() const { return Instr->getOperand(5); }
void set_Origin_Z(llvm::Value *val) { Instr->setOperand(5, val); }
llvm::Value *get_TMin() const { return Instr->getOperand(6); }
void set_TMin(llvm::Value *val) { Instr->setOperand(6, val); }
llvm::Value *get_Direction_X() const { return Instr->getOperand(7); }
void set_Direction_X(llvm::Value *val) { Instr->setOperand(7, val); }
llvm::Value *get_Direction_Y() const { return Instr->getOperand(8); }
void set_Direction_Y(llvm::Value *val) { Instr->setOperand(8, val); }
llvm::Value *get_Direction_Z() const { return Instr->getOperand(9); }
void set_Direction_Z(llvm::Value *val) { Instr->setOperand(9, val); }
llvm::Value *get_TMax() const { return Instr->getOperand(10); }
void set_TMax(llvm::Value *val) { Instr->setOperand(10, val); }
};

/// This instruction Creates an empty nop HitObject
struct DxilInst_HitObject_MakeNop {
llvm::Instruction *Instr;
// Construction and identification
DxilInst_HitObject_MakeNop(llvm::Instruction *pInstr) : Instr(pInstr) {}
operator bool() const {
return hlsl::OP::IsDxilOpFuncCallInst(Instr,
hlsl::OP::OpCode::HitObject_MakeNop);
}
// Validation support
bool isAllowed() const { return true; }
bool isArgumentListValid() const {
if (1 != llvm::dyn_cast<llvm::CallInst>(Instr)->getNumArgOperands())
return false;
return true;
}
// Metadata
bool requiresUniformInputs() const { return false; }
};
// INSTR-HELPER:END
} // namespace hlsl
2 changes: 2 additions & 0 deletions include/dxc/DXIL/DxilOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class OP {
void RemoveFunction(llvm::Function *F);
llvm::LLVMContext &GetCtx() { return m_Ctx; }
llvm::Type *GetHandleType() const;
llvm::Type *GetHitObjectType() const;
llvm::Type *GetNodeHandleType() const;
llvm::Type *GetNodeRecordHandleType() const;
llvm::Type *GetResourcePropertiesType() const;
Expand Down Expand Up @@ -146,6 +147,7 @@ class OP {
llvm::Module *m_pModule;

llvm::Type *m_pHandleType;
llvm::Type *m_pHitObjectType;
llvm::Type *m_pNodeHandleType;
llvm::Type *m_pNodeRecordHandleType;
llvm::Type *m_pResourcePropertiesType;
Expand Down
64 changes: 48 additions & 16 deletions lib/DXIL/DxilOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2670,24 +2670,29 @@ const OP::OpCodeProperty OP::m_OpCodeProps[(unsigned)OP::OpCode::NumOpCodes] = {
false},
Attribute::None,
},

// Shader Execution Reordering void, h, f, d, i1, i8, i16,
// i32, i64, udt, obj , function attribute
{
OC::ReservedB3,
"ReservedB3",
OCC::Reserved,
"reserved",
OC::HitObject_MakeMiss,
"HitObject_MakeMiss",
OCC::HitObject_MakeMiss,
"hitObject_MakeMiss",
{true, false, false, false, false, false, false, false, false, false,
false},
Attribute::None,
Attribute::ReadNone,
},
{
OC::ReservedB4,
"ReservedB4",
OCC::Reserved,
"reserved",
OC::HitObject_MakeNop,
"HitObject_MakeNop",
OCC::HitObject_MakeNop,
"hitObject_MakeNop",
{true, false, false, false, false, false, false, false, false, false,
false},
Attribute::None,
Attribute::ReadNone,
},

// void, h, f, d, i1, i8, i16, i32, i64, udt, obj , function attribute
{
OC::ReservedB5,
"ReservedB5",
Expand Down Expand Up @@ -3750,6 +3755,14 @@ void OP::GetMinShaderModelAndMask(OpCode C, bool bWithTranslation,
minor = 9;
return;
}
// Instructions: HitObject_MakeMiss=265, HitObject_MakeNop=266
if ((265 <= op && op <= 266)) {
major = 6;
minor = 9;
mask =
SFLAG(Library) | SFLAG(RayGeneration) | SFLAG(ClosestHit) | SFLAG(Miss);
return;
}
// OPCODE-SMMASK:END
}

Expand Down Expand Up @@ -3851,6 +3864,8 @@ OP::OP(LLVMContext &Ctx, Module *pModule)

m_pHandleType = GetOrCreateStructType(m_Ctx, Type::getInt8PtrTy(m_Ctx),
"dx.types.Handle", pModule);
m_pHitObjectType = GetOrCreateStructType(m_Ctx, Type::getInt8PtrTy(m_Ctx),
"dx.types.HitObject", pModule);
m_pNodeHandleType = GetOrCreateStructType(m_Ctx, Type::getInt8PtrTy(m_Ctx),
"dx.types.NodeHandle", pModule);
m_pNodeRecordHandleType = GetOrCreateStructType(
Expand Down Expand Up @@ -3993,6 +4008,7 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) {
Type *pF64 = Type::getDoubleTy(m_Ctx);
Type *pSDT = GetSplitDoubleType(); // Split double type.
Type *p4I32 = GetFourI32Type(); // 4 i32s in a struct.
Type *pHit = GetHitObjectType();

Type *udt = pOverloadType;
Type *obj = pOverloadType;
Expand Down Expand Up @@ -5871,14 +5887,28 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) {
A(pV);
A(pI32);
break;
case OpCode::ReservedB3:
A(pV);

// Shader Execution Reordering
case OpCode::HitObject_MakeMiss:
A(pHit);
A(pI32);
A(pI32);
A(pI32);
A(pF32);
A(pF32);
A(pF32);
A(pF32);
A(pF32);
A(pF32);
A(pF32);
A(pF32);
break;
case OpCode::ReservedB4:
A(pV);
case OpCode::HitObject_MakeNop:
A(pHit);
A(pI32);
break;

//
case OpCode::ReservedB5:
A(pV);
A(pI32);
Expand Down Expand Up @@ -6288,8 +6318,8 @@ llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) {
case OpCode::ReservedB0:
case OpCode::ReservedB1:
case OpCode::ReservedB2:
case OpCode::ReservedB3:
case OpCode::ReservedB4:
case OpCode::HitObject_MakeMiss:
case OpCode::HitObject_MakeNop:
case OpCode::ReservedB5:
case OpCode::ReservedB6:
case OpCode::ReservedB7:
Expand Down Expand Up @@ -6431,6 +6461,8 @@ Type *OP::GetHandleType() const { return m_pHandleType; }

Type *OP::GetNodeHandleType() const { return m_pNodeHandleType; }

Type *OP::GetHitObjectType() const { return m_pHitObjectType; }

Type *OP::GetNodeRecordHandleType() const { return m_pNodeRecordHandleType; }

Type *OP::GetResourcePropertiesType() const {
Expand Down
46 changes: 46 additions & 0 deletions tools/clang/test/DXILValidation/ser_hitobject_make_passing.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
; RUN: %dxv %s | FileCheck %s

; CHECK: Validation succeeded.

target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
target triple = "dxil-ms-dx"

%dx.types.HitObject = type { i8* }

; Function Attrs: nounwind
define void @"\01?main@@YAXXZ"() #0 {
; Test HitObject_MakeMiss (opcode 265)
%r265 = call %dx.types.HitObject @dx.op.hitObject_MakeMiss(i32 265, i32 4, i32 0, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 0.000000e+00, float 1.000000e+00, float 0.000000e+00, float 0.000000e+00, float 9.999000e+03) ; HitObject_MakeMiss(RayFlags,MissShaderIndex,Origin_X,Origin_Y,Origin_Z,TMin,Direction_X,Direction_Y,Direction_Z,TMax)

; Test HitObject_MakeNop (opcode 266)
%r266 = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) ; HitObject_MakeNop()

ret void
}

; Function Attrs: nounwind readnone
declare %dx.types.HitObject @dx.op.hitObject_MakeMiss(i32, i32, i32, float, float, float, float, float, float, float, float) #1

; Function Attrs: nounwind readnone
declare %dx.types.HitObject @dx.op.hitObject_MakeNop(i32) #1

attributes #0 = { nounwind }
attributes #1 = { nounwind readnone }

!dx.version = !{!0}
!dx.valver = !{!0}
!dx.shaderModel = !{!1}
!dx.typeAnnotations = !{!2}
!dx.entryPoints = !{!9, !11}

!0 = !{i32 1, i32 9}
!1 = !{!"lib", i32 6, i32 9}
!2 = !{i32 1, void ()* @"\01?main@@YAXXZ", !3}
!3 = !{!4}
!4 = !{i32 1, !5, !5}
!5 = !{}
!9 = !{null, !"", null, null, !10}
!10 = !{i32 0, i64 0}
!11 = !{void ()* @"\01?main@@YAXXZ", !"\01?main@@YAXXZ", null, null, !12}
!12 = !{i32 8, i32 7, i32 5, !13}
!13 = !{i32 0}
53 changes: 50 additions & 3 deletions utils/hct/hctdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,15 @@ def populate_categories_and_models(self):
self.name_idx[i].category = "Extended Command Information"
self.name_idx[i].shader_stages = ("vertex",)
self.name_idx[i].shader_model = 6, 8
for i in ("HitObject_MakeMiss,HitObject_MakeNop").split(","):
self.name_idx[i].category = "Shader Execution Reordering"
self.name_idx[i].shader_model = 6, 9
self.name_idx[i].shader_stages = (
"library",
"raygeneration",
"closesthit",
"miss",
)

def populate_llvm_instructions(self):
# Add instructions that map to LLVM instructions.
Expand Down Expand Up @@ -5550,7 +5559,43 @@ def UFI(name, **mappings):
next_op_idx = self.reserve_dxil_op_range("ReservedA", next_op_idx, 3)

# Shader Execution Reordering
next_op_idx = self.reserve_dxil_op_range("ReservedB", next_op_idx, 31)
next_op_idx = self.reserve_dxil_op_range("ReservedB", next_op_idx, 3)

self.add_dxil_op(
"HitObject_MakeMiss",
next_op_idx,
"HitObject_MakeMiss",
"Creates a new HitObject representing a miss",
"v",
"rn",
[
db_dxil_param(0, "hit_object", "", "HitObject with a committed miss"),
db_dxil_param(2, "i32", "RayFlags", "ray flags"),
db_dxil_param(3, "i32", "MissShaderIndex", "Miss shader index"),
db_dxil_param(4, "f", "Origin_X", "Origin x of the ray"),
db_dxil_param(5, "f", "Origin_Y", "Origin y of the ray"),
db_dxil_param(6, "f", "Origin_Z", "Origin z of the ray"),
db_dxil_param(7, "f", "TMin", "Tmin of the ray"),
db_dxil_param(8, "f", "Direction_X", "Direction x of the ray"),
db_dxil_param(9, "f", "Direction_Y", "Direction y of the ray"),
db_dxil_param(10, "f", "Direction_Z", "Direction z of the ray"),
db_dxil_param(11, "f", "TMax", "Tmax of the ray"),
],
)
next_op_idx += 1

self.add_dxil_op(
"HitObject_MakeNop",
next_op_idx,
"HitObject_MakeNop",
"Creates an empty nop HitObject",
"v",
"rn",
[db_dxil_param(0, "hit_object", "", "Empty nop HitObject")],
)
next_op_idx += 1

next_op_idx = self.reserve_dxil_op_range("ReservedB", next_op_idx, 26, 5)

# Reserved block C
next_op_idx = self.reserve_dxil_op_range("ReservedC", next_op_idx, 10)
Expand Down Expand Up @@ -8145,10 +8190,12 @@ def add_dxil_op_reserved(self, name, code_id):
)
self.instr.append(i)

def reserve_dxil_op_range(self, group_name, start_id, count):
def reserve_dxil_op_range(self, group_name, start_id, count, start_reserved_id=0):
"Reserve a range of dxil opcodes for future use; returns next id"
for i in range(0, count):
self.add_dxil_op_reserved("{0}{1}".format(group_name, i), start_id + i)
self.add_dxil_op_reserved(
"{0}{1}".format(group_name, start_reserved_id + i), start_id + i
)
return start_id + count

def get_instr_by_llvm_name(self, llvm_name):
Expand Down
1 change: 1 addition & 0 deletions utils/hct/hctdb_instrhelp.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,7 @@ def print_opfunc_table(self):
"noderecordhandle": "A(pNodeRecordHandle);",
"nodeproperty": "A(nodeProperty);",
"noderecordproperty": "A(nodeRecordProperty);",
"hit_object": "A(pHit);",
}
last_category = None
for i in self.instrs:
Expand Down