Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
61 changes: 31 additions & 30 deletions include/dxc/DXIL/DxilConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,35 +487,35 @@ inline bool IsFeedbackTexture(DXIL::ResourceKind ResourceKind) {
// Enumeration for operations specified by DXIL
enum class OpCode : unsigned {
//
Reserved0 = 226, // Reserved
Reserved1 = 227, // Reserved
Reserved10 = 236, // Reserved
Reserved11 = 237, // Reserved
Reserved2 = 228, // Reserved
Reserved3 = 229, // Reserved
Reserved4 = 230, // Reserved
Reserved5 = 231, // Reserved
Reserved6 = 232, // Reserved
Reserved7 = 233, // Reserved
Reserved8 = 234, // Reserved
Reserved9 = 235, // Reserved
ReservedA0 = 259, // reserved
ReservedA1 = 260, // reserved
ReservedA2 = 261, // reserved
ReservedB28 = 290, // reserved
ReservedB29 = 291, // reserved
ReservedB30 = 292, // reserved
ReservedB6 = 268, // reserved
ReservedC0 = 293, // reserved
ReservedC1 = 294, // reserved
ReservedC2 = 295, // reserved
ReservedC3 = 296, // reserved
ReservedC4 = 297, // reserved
ReservedC5 = 298, // reserved
ReservedC6 = 299, // reserved
ReservedC7 = 300, // reserved
ReservedC8 = 301, // reserved
ReservedC9 = 302, // reserved
MaybeReorderThread = 268, // Reorders the current thread
Reserved0 = 226, // Reserved
Reserved1 = 227, // Reserved
Reserved10 = 236, // Reserved
Reserved11 = 237, // Reserved
Reserved2 = 228, // Reserved
Reserved3 = 229, // Reserved
Reserved4 = 230, // Reserved
Reserved5 = 231, // Reserved
Reserved6 = 232, // Reserved
Reserved7 = 233, // Reserved
Reserved8 = 234, // Reserved
Reserved9 = 235, // Reserved
ReservedA0 = 259, // reserved
ReservedA1 = 260, // reserved
ReservedA2 = 261, // reserved
ReservedB28 = 290, // reserved
ReservedB29 = 291, // reserved
ReservedB30 = 292, // reserved
ReservedC0 = 293, // reserved
ReservedC1 = 294, // reserved
ReservedC2 = 295, // reserved
ReservedC3 = 296, // reserved
ReservedC4 = 297, // reserved
ReservedC5 = 298, // reserved
ReservedC6 = 299, // reserved
ReservedC7 = 300, // reserved
ReservedC8 = 301, // reserved
ReservedC9 = 302, // reserved

// Amplification shader instructions
DispatchMesh = 173, // Amplification shader intrinsic DispatchMesh
Expand Down Expand Up @@ -1072,6 +1072,7 @@ enum class OpCode : unsigned {
// Groups for DXIL operations with equivalent function templates
enum class OpCodeClass : unsigned {
//
MaybeReorderThread,
Reserved,

// Amplification shader instructions
Expand Down Expand Up @@ -1384,7 +1385,7 @@ enum class OpCodeClass : unsigned {
NumOpClasses_Dxil_1_7 = 153,
NumOpClasses_Dxil_1_8 = 174,

NumOpClasses = 189 // exclusive last value of enumeration
NumOpClasses = 190 // exclusive last value of enumeration
};
// OPCODECLASS-ENUM:END

Expand Down
37 changes: 37 additions & 0 deletions include/dxc/DXIL/DxilInstructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -9104,6 +9104,43 @@ struct DxilInst_HitObject_Invoke {
void set_payload(llvm::Value *val) { Instr->setOperand(2, val); }
};

/// This instruction Reorders the current thread
struct DxilInst_MaybeReorderThread {
llvm::Instruction *Instr;
// Construction and identification
DxilInst_MaybeReorderThread(llvm::Instruction *pInstr) : Instr(pInstr) {}
operator bool() const {
return hlsl::OP::IsDxilOpFuncCallInst(Instr,
hlsl::OP::OpCode::MaybeReorderThread);
}
// Validation support
bool isAllowed() const { return true; }
bool isArgumentListValid() const {
if (4 != llvm::dyn_cast<llvm::CallInst>(Instr)->getNumArgOperands())
return false;
return true;
}
// Metadata
bool requiresUniformInputs() const { return false; }
// Operand indexes
enum OperandIdx {
arg_hitObject = 1,
arg_coherenceHint = 2,
arg_numCoherenceHintBitsFromLSB = 3,
};
// Accessors
llvm::Value *get_hitObject() const { return Instr->getOperand(1); }
void set_hitObject(llvm::Value *val) { Instr->setOperand(1, val); }
llvm::Value *get_coherenceHint() const { return Instr->getOperand(2); }
void set_coherenceHint(llvm::Value *val) { Instr->setOperand(2, val); }
llvm::Value *get_numCoherenceHintBitsFromLSB() const {
return Instr->getOperand(3);
}
void set_numCoherenceHintBitsFromLSB(llvm::Value *val) {
Instr->setOperand(3, val);
}
};

/// This instruction Returns `true` if the HitObject represents a miss
struct DxilInst_HitObject_IsMiss {
llvm::Instruction *Instr;
Expand Down
21 changes: 15 additions & 6 deletions lib/DXIL/DxilOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2354,10 +2354,11 @@ const OP::OpCodeProperty OP::m_OpCodeProps[(unsigned)OP::OpCode::NumOpCodes] = {
{{0x100}},
{{0x0}}}, // Overloads: u

{OC::ReservedB6,
"ReservedB6",
OCC::Reserved,
"reserved",
//
{OC::MaybeReorderThread,
"MaybeReorderThread",
OCC::MaybeReorderThread,
"maybeReorderThread",
Attribute::None,
0,
{},
Expand Down Expand Up @@ -3179,6 +3180,11 @@ void OP::GetMinShaderModelAndMask(OpCode C, bool bWithTranslation,
SFLAG(Amplification) | SFLAG(Mesh) | SFLAG(Node);
return;
}
// Instructions: MaybeReorderThread=268
if (op == 268) {
mask = SFLAG(Library) | SFLAG(RayGeneration);
return;
}
// Instructions: RenderTargetGetSamplePosition=76,
// RenderTargetGetSampleCount=77, Discard=82, EvalSnapped=87,
// EvalSampleIndex=88, EvalCentroid=89, SampleIndex=90, Coverage=91,
Expand Down Expand Up @@ -5692,9 +5698,12 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) {
break;

//
case OpCode::ReservedB6:
case OpCode::MaybeReorderThread:
A(pV);
A(pI32);
A(pHit);
A(pI32);
A(pI32);
break;

// Shader Execution Reordering
Expand Down Expand Up @@ -6158,7 +6167,7 @@ llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) {
case OpCode::HitObject_FromRayQuery:
case OpCode::HitObject_MakeMiss:
case OpCode::HitObject_MakeNop:
case OpCode::ReservedB6:
case OpCode::MaybeReorderThread:
case OpCode::HitObject_SetShaderTableIndex:
case OpCode::HitObject_LoadLocalRootTableConstant:
case OpCode::ReservedB28:
Expand Down
24 changes: 24 additions & 0 deletions lib/DxilValidation/DxilValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1886,6 +1886,30 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
{"CreateHandleForLib", "Library"});
}
break;

// Shader Execution Reordering
case DXIL::OpCode::MaybeReorderThread: {
Value *HitObject = CI->getArgOperand(1);
Value *CoherenceHintBits = CI->getArgOperand(2);
Value *NumCoherenceHintBits = CI->getArgOperand(3);

if (isa<UndefValue>(HitObject))
ValCtx.EmitInstrError(CI, ValidationRule::InstrUndefHitObject);

if (isa<UndefValue>(NumCoherenceHintBits))
ValCtx.EmitInstrError(
CI, ValidationRule::InstrMayReorderThreadUndefCoherenceHintParam);

ConstantInt *NumCoherenceHintBitsConst =
dyn_cast<ConstantInt>(NumCoherenceHintBits);
const bool HasCoherenceHint =
NumCoherenceHintBitsConst &&
NumCoherenceHintBitsConst->getLimitedValue() != 0;
if (HasCoherenceHint && isa<UndefValue>(CoherenceHintBits))
ValCtx.EmitInstrError(
CI, ValidationRule::InstrMayReorderThreadUndefCoherenceHintParam);
} break;

case DXIL::OpCode::AtomicBinOp:
case DXIL::OpCode::AtomicCompareExchange: {
Type *pOverloadType = OP::GetOverloadType(Opcode, CI->getCalledFunction());
Expand Down
60 changes: 60 additions & 0 deletions tools/clang/test/LitDXILValidation/ser_maybereorder_failing.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
; REQUIRES: dxil-1-9
; RUN: not %dxv %s 2>&1 | FileCheck %s

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* }

; CHECK: Function: ?main@@YAXXZ: error: Use of undef coherence hint or num coherence hint bits in MaybeReorderThread.
; CHECK-NEXT: note: at 'call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 1, i32 undef)'

; CHECK: Function: ?main@@YAXXZ: error: Use of undef coherence hint or num coherence hint bits in MaybeReorderThread.
; CHECK-NEXT: note: at 'call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 undef, i32 1)'

; CHECK: Function: ?main@@YAXXZ: error: HitObject is undef.
; CHECK-NEXT: note: at 'call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject undef, i32 11, i32 0)'

; CHECK: Validation failed.

; Function Attrs: nounwind
define void @"\01?main@@YAXXZ"() #0 {
%nop = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) ; HitObject_MakeNop()

; Validate that hit object is not undef.
call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject undef, i32 11, i32 0) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB)

; Validate that coherence hint is not undef while numCoherenceHintBitsFromLSB is not 0.
call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 undef, i32 1) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB)

; Validate that num coherence hint bits from LSB is not undef.
call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 1, i32 undef) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB)
ret void
}

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

; Function Attrs: nounwind
declare void @dx.op.maybeReorderThread(i32, %dx.types.HitObject, i32, i32) #0

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

!dx.version = !{!0}
!dx.valver = !{!0}
!dx.shaderModel = !{!1}
!dx.typeAnnotations = !{!2}
!dx.entryPoints = !{!6, !8}

!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 = !{}
!6 = !{null, !"", null, null, !7}
!7 = !{i32 0, i64 0}
!8 = !{void ()* @"\01?main@@YAXXZ", !"\01?main@@YAXXZ", null, null, !9}
!9 = !{i32 8, i32 7, i32 5, !10}
!10 = !{i32 0}
46 changes: 46 additions & 0 deletions tools/clang/test/LitDXILValidation/ser_maybereorder_passing.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
; REQUIRES: dxil-1-9
; 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 {
%nop = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) ; HitObject_MakeNop()
call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 241, i32 3) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB)

; Coherence hint disabled, accept 'undef' coherence hint bits.
call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 undef, i32 0) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB)
ret void
}

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

; Function Attrs: nounwind
declare void @dx.op.maybeReorderThread(i32, %dx.types.HitObject, i32, i32) #0

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

!dx.version = !{!0}
!dx.valver = !{!0}
!dx.shaderModel = !{!1}
!dx.typeAnnotations = !{!2}
!dx.entryPoints = !{!6, !8}

!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 = !{}
!6 = !{null, !"", null, null, !7}
!7 = !{i32 0, i64 0}
!8 = !{void ()* @"\01?main@@YAXXZ", !"\01?main@@YAXXZ", null, null, !9}
!9 = !{i32 8, i32 7, i32 5, !10}
!10 = !{i32 0}
36 changes: 35 additions & 1 deletion utils/hct/hctdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,11 @@ def populate_categories_and_models(self):
"closesthit",
"miss",
)
for i in ("MaybeReorderThread").split(","):
self.name_idx[i].shader_stages = (
Comment thread
tex3d marked this conversation as resolved.
"library",
"raygeneration",
)

def populate_llvm_instructions(self):
# Add instructions that map to LLVM instructions.
Expand Down Expand Up @@ -5904,7 +5909,26 @@ def UFI(name, **mappings):
)
next_op_idx += 1

next_op_idx = self.reserve_dxil_op_range("ReservedB", next_op_idx, 1, 6)
self.add_dxil_op(
"MaybeReorderThread",
next_op_idx,
"MaybeReorderThread",
"Reorders the current thread",
"v",
"",
[
retvoid_param,
db_dxil_param(2, "hit_object", "hitObject", "hit"),
db_dxil_param(3, "i32", "coherenceHint", "Coherence hint"),
db_dxil_param(
4,
"i32",
"numCoherenceHintBitsFromLSB",
"Num coherence hint bits from LSB",
),
],
)
next_op_idx += 1

self.add_dxil_op(
"HitObject_IsMiss",
Expand Down Expand Up @@ -8267,6 +8291,16 @@ def build_valrules(self):
"Invalid use of completed record handle.",
)

# Shader Execution Reordering
self.add_valrule(
"Instr.UndefHitObject",
"HitObject is undef.",
)
self.add_valrule(
"Instr.MayReorderThreadUndefCoherenceHintParam",
"Use of undef coherence hint or num coherence hint bits in MaybeReorderThread.",
)

# Some legacy rules:
# - space is only supported for shader targets 5.1 and higher
# - multiple rules regarding derivatives, which isn't a supported feature for DXIL
Expand Down
Loading