Skip to content

Commit f556b08

Browse files
committed
[SER] MaybeReorderThread DXIL opcode and validation
- DXIL opcodes for MaybeReorderThread - Validator rules - DXV validation test (passing & expected failures) Specification: https://github.com/microsoft/hlsl-specs/blob/main/proposals/0027-shader-execution-reordering.md DXC SER implementation tracker: microsoft#7214
1 parent 33bc44a commit f556b08

File tree

7 files changed

+252
-65
lines changed

7 files changed

+252
-65
lines changed

include/dxc/DXIL/DxilConstants.h

+57-55
Original file line numberDiff line numberDiff line change
@@ -482,60 +482,61 @@ inline bool IsFeedbackTexture(DXIL::ResourceKind ResourceKind) {
482482
// Enumeration for operations specified by DXIL
483483
enum class OpCode : unsigned {
484484
//
485-
Reserved0 = 226, // Reserved
486-
Reserved1 = 227, // Reserved
487-
Reserved10 = 236, // Reserved
488-
Reserved11 = 237, // Reserved
489-
Reserved2 = 228, // Reserved
490-
Reserved3 = 229, // Reserved
491-
Reserved4 = 230, // Reserved
492-
Reserved5 = 231, // Reserved
493-
Reserved6 = 232, // Reserved
494-
Reserved7 = 233, // Reserved
495-
Reserved8 = 234, // Reserved
496-
Reserved9 = 235, // Reserved
497-
ReservedA0 = 259, // reserved
498-
ReservedA1 = 260, // reserved
499-
ReservedA2 = 261, // reserved
500-
ReservedB0 = 262, // reserved
501-
ReservedB1 = 263, // reserved
502-
ReservedB10 = 272, // reserved
503-
ReservedB11 = 273, // reserved
504-
ReservedB12 = 274, // reserved
505-
ReservedB13 = 275, // reserved
506-
ReservedB14 = 276, // reserved
507-
ReservedB15 = 277, // reserved
508-
ReservedB16 = 278, // reserved
509-
ReservedB17 = 279, // reserved
510-
ReservedB18 = 280, // reserved
511-
ReservedB19 = 281, // reserved
512-
ReservedB2 = 264, // reserved
513-
ReservedB20 = 282, // reserved
514-
ReservedB21 = 283, // reserved
515-
ReservedB22 = 284, // reserved
516-
ReservedB23 = 285, // reserved
517-
ReservedB24 = 286, // reserved
518-
ReservedB25 = 287, // reserved
519-
ReservedB26 = 288, // reserved
520-
ReservedB27 = 289, // reserved
521-
ReservedB28 = 290, // reserved
522-
ReservedB29 = 291, // reserved
523-
ReservedB30 = 292, // reserved
524-
ReservedB5 = 267, // reserved
525-
ReservedB6 = 268, // reserved
526-
ReservedB7 = 269, // reserved
527-
ReservedB8 = 270, // reserved
528-
ReservedB9 = 271, // reserved
529-
ReservedC0 = 293, // reserved
530-
ReservedC1 = 294, // reserved
531-
ReservedC2 = 295, // reserved
532-
ReservedC3 = 296, // reserved
533-
ReservedC4 = 297, // reserved
534-
ReservedC5 = 298, // reserved
535-
ReservedC6 = 299, // reserved
536-
ReservedC7 = 300, // reserved
537-
ReservedC8 = 301, // reserved
538-
ReservedC9 = 302, // reserved
485+
MaybeReorderThread = 268, // Reorders the current thread. Optionally accepts a
486+
// HitObject arg, or undef
487+
Reserved0 = 226, // Reserved
488+
Reserved1 = 227, // Reserved
489+
Reserved10 = 236, // Reserved
490+
Reserved11 = 237, // Reserved
491+
Reserved2 = 228, // Reserved
492+
Reserved3 = 229, // Reserved
493+
Reserved4 = 230, // Reserved
494+
Reserved5 = 231, // Reserved
495+
Reserved6 = 232, // Reserved
496+
Reserved7 = 233, // Reserved
497+
Reserved8 = 234, // Reserved
498+
Reserved9 = 235, // Reserved
499+
ReservedA0 = 259, // reserved
500+
ReservedA1 = 260, // reserved
501+
ReservedA2 = 261, // reserved
502+
ReservedB0 = 262, // reserved
503+
ReservedB1 = 263, // reserved
504+
ReservedB10 = 272, // reserved
505+
ReservedB11 = 273, // reserved
506+
ReservedB12 = 274, // reserved
507+
ReservedB13 = 275, // reserved
508+
ReservedB14 = 276, // reserved
509+
ReservedB15 = 277, // reserved
510+
ReservedB16 = 278, // reserved
511+
ReservedB17 = 279, // reserved
512+
ReservedB18 = 280, // reserved
513+
ReservedB19 = 281, // reserved
514+
ReservedB2 = 264, // reserved
515+
ReservedB20 = 282, // reserved
516+
ReservedB21 = 283, // reserved
517+
ReservedB22 = 284, // reserved
518+
ReservedB23 = 285, // reserved
519+
ReservedB24 = 286, // reserved
520+
ReservedB25 = 287, // reserved
521+
ReservedB26 = 288, // reserved
522+
ReservedB27 = 289, // reserved
523+
ReservedB28 = 290, // reserved
524+
ReservedB29 = 291, // reserved
525+
ReservedB30 = 292, // reserved
526+
ReservedB6 = 267, // reserved
527+
ReservedB7 = 269, // reserved
528+
ReservedB8 = 270, // reserved
529+
ReservedB9 = 271, // reserved
530+
ReservedC0 = 293, // reserved
531+
ReservedC1 = 294, // reserved
532+
ReservedC2 = 295, // reserved
533+
ReservedC3 = 296, // reserved
534+
ReservedC4 = 297, // reserved
535+
ReservedC5 = 298, // reserved
536+
ReservedC6 = 299, // reserved
537+
ReservedC7 = 300, // reserved
538+
ReservedC8 = 301, // reserved
539+
ReservedC9 = 302, // reserved
539540

540541
// Amplification shader instructions
541542
DispatchMesh = 173, // Amplification shader intrinsic DispatchMesh
@@ -1051,6 +1052,7 @@ enum class OpCode : unsigned {
10511052
// Groups for DXIL operations with equivalent function templates
10521053
enum class OpCodeClass : unsigned {
10531054
//
1055+
MaybeReorderThread,
10541056
Reserved,
10551057

10561058
// Amplification shader instructions
@@ -1351,7 +1353,7 @@ enum class OpCodeClass : unsigned {
13511353
NumOpClasses_Dxil_1_7 = 153,
13521354
NumOpClasses_Dxil_1_8 = 174,
13531355

1354-
NumOpClasses = 177 // exclusive last value of enumeration
1356+
NumOpClasses = 178 // exclusive last value of enumeration
13551357
};
13561358
// OPCODECLASS-ENUM:END
13571359

include/dxc/DXIL/DxilInstructions.h

+38
Original file line numberDiff line numberDiff line change
@@ -8887,5 +8887,43 @@ struct DxilInst_HitObject_MakeNop {
88878887
// Metadata
88888888
bool requiresUniformInputs() const { return false; }
88898889
};
8890+
8891+
/// This instruction Reorders the current thread. Optionally accepts a HitObject
8892+
/// arg, or undef
8893+
struct DxilInst_MaybeReorderThread {
8894+
llvm::Instruction *Instr;
8895+
// Construction and identification
8896+
DxilInst_MaybeReorderThread(llvm::Instruction *pInstr) : Instr(pInstr) {}
8897+
operator bool() const {
8898+
return hlsl::OP::IsDxilOpFuncCallInst(Instr,
8899+
hlsl::OP::OpCode::MaybeReorderThread);
8900+
}
8901+
// Validation support
8902+
bool isAllowed() const { return true; }
8903+
bool isArgumentListValid() const {
8904+
if (4 != llvm::dyn_cast<llvm::CallInst>(Instr)->getNumArgOperands())
8905+
return false;
8906+
return true;
8907+
}
8908+
// Metadata
8909+
bool requiresUniformInputs() const { return false; }
8910+
// Operand indexes
8911+
enum OperandIdx {
8912+
arg_hitObject = 1,
8913+
arg_coherenceHint = 2,
8914+
arg_numCoherenceHintBitsFromLSB = 3,
8915+
};
8916+
// Accessors
8917+
llvm::Value *get_hitObject() const { return Instr->getOperand(1); }
8918+
void set_hitObject(llvm::Value *val) { Instr->setOperand(1, val); }
8919+
llvm::Value *get_coherenceHint() const { return Instr->getOperand(2); }
8920+
void set_coherenceHint(llvm::Value *val) { Instr->setOperand(2, val); }
8921+
llvm::Value *get_numCoherenceHintBitsFromLSB() const {
8922+
return Instr->getOperand(3);
8923+
}
8924+
void set_numCoherenceHintBitsFromLSB(llvm::Value *val) {
8925+
Instr->setOperand(3, val);
8926+
}
8927+
};
88908928
// INSTR-HELPER:END
88918929
} // namespace hlsl

lib/DXIL/DxilOperations.cpp

+17-9
Original file line numberDiff line numberDiff line change
@@ -2694,19 +2694,19 @@ const OP::OpCodeProperty OP::m_OpCodeProps[(unsigned)OP::OpCode::NumOpCodes] = {
26942694

26952695
// void, h, f, d, i1, i8, i16, i32, i64, udt, obj , function attribute
26962696
{
2697-
OC::ReservedB5,
2698-
"ReservedB5",
2697+
OC::ReservedB6,
2698+
"ReservedB6",
26992699
OCC::Reserved,
27002700
"reserved",
27012701
{true, false, false, false, false, false, false, false, false, false,
27022702
false},
27032703
Attribute::None,
27042704
},
27052705
{
2706-
OC::ReservedB6,
2707-
"ReservedB6",
2708-
OCC::Reserved,
2709-
"reserved",
2706+
OC::MaybeReorderThread,
2707+
"MaybeReorderThread",
2708+
OCC::MaybeReorderThread,
2709+
"maybeReorderThread",
27102710
{true, false, false, false, false, false, false, false, false, false,
27112711
false},
27122712
Attribute::None,
@@ -3486,6 +3486,11 @@ void OP::GetMinShaderModelAndMask(OpCode C, bool bWithTranslation,
34863486
SFLAG(Amplification) | SFLAG(Mesh) | SFLAG(Node);
34873487
return;
34883488
}
3489+
// Instructions: MaybeReorderThread=268
3490+
if (op == 268) {
3491+
mask = SFLAG(Library) | SFLAG(RayGeneration);
3492+
return;
3493+
}
34893494
// Instructions: RenderTargetGetSamplePosition=76,
34903495
// RenderTargetGetSampleCount=77, Discard=82, EvalSnapped=87,
34913496
// EvalSampleIndex=88, EvalCentroid=89, SampleIndex=90, Coverage=91,
@@ -5909,13 +5914,16 @@ Function *OP::GetOpFunc(OpCode opCode, Type *pOverloadType) {
59095914
break;
59105915

59115916
//
5912-
case OpCode::ReservedB5:
5917+
case OpCode::ReservedB6:
59135918
A(pV);
59145919
A(pI32);
59155920
break;
5916-
case OpCode::ReservedB6:
5921+
case OpCode::MaybeReorderThread:
59175922
A(pV);
59185923
A(pI32);
5924+
A(pHit);
5925+
A(pI32);
5926+
A(pI32);
59195927
break;
59205928
case OpCode::ReservedB7:
59215929
A(pV);
@@ -6320,8 +6328,8 @@ llvm::Type *OP::GetOverloadType(OpCode opCode, llvm::Function *F) {
63206328
case OpCode::ReservedB2:
63216329
case OpCode::HitObject_MakeMiss:
63226330
case OpCode::HitObject_MakeNop:
6323-
case OpCode::ReservedB5:
63246331
case OpCode::ReservedB6:
6332+
case OpCode::MaybeReorderThread:
63256333
case OpCode::ReservedB7:
63266334
case OpCode::ReservedB8:
63276335
case OpCode::ReservedB9:

lib/DxilValidation/DxilValidation.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,19 @@ static void ValidateDxilOperationCallInProfile(CallInst *CI,
18621862
{"CreateHandleForLib", "Library"});
18631863
}
18641864
break;
1865+
1866+
// Shader Execution Reordering
1867+
case DXIL::OpCode::MaybeReorderThread: {
1868+
Value *CoherenceHintBits = CI->getArgOperand(2);
1869+
Value *NumCoherenceHintBits = CI->getArgOperand(3);
1870+
1871+
if (isa<UndefValue>(CoherenceHintBits) ||
1872+
isa<UndefValue>(NumCoherenceHintBits)) {
1873+
ValCtx.EmitInstrError(
1874+
CI, ValidationRule::InstrMayReorderThreadUndefCoherenceHintParam);
1875+
}
1876+
} break;
1877+
18651878
case DXIL::OpCode::AtomicBinOp:
18661879
case DXIL::OpCode::AtomicCompareExchange: {
18671880
Type *pOverloadType = OP::GetOverloadType(opcode, CI->getCalledFunction());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
; RUN: not %dxv %s 2>&1 | FileCheck %s
2+
3+
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"
4+
target triple = "dxil-ms-dx"
5+
6+
%dx.types.HitObject = type { i8* }
7+
8+
; Function Attrs: nounwind
9+
define void @"\01?main@@YAXXZ"() #0 {
10+
%nop = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) ; HitObject_MakeNop()
11+
12+
; Validate that coherence hint is not undef.
13+
call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 undef, i32 0) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB)
14+
; CHECK: Function: ?main@@YAXXZ: error: Use of undef coherence hint or num coherence hint bits in MaybeReorderThread.
15+
; CHECK-NEXT: note: at 'call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 undef, i32 0)'
16+
17+
; Validate that num coherence hint bits from LSB is not undef.
18+
call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 1, i32 undef) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB)
19+
; CHECK-NEXT: Function: ?main@@YAXXZ: error: Use of undef coherence hint or num coherence hint bits in MaybeReorderThread.
20+
; CHECK-NEXT: note: at 'call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 1, i32 undef)'
21+
ret void
22+
}
23+
; CHECK-NEXT: Validation failed.
24+
25+
; Function Attrs: nounwind readnone
26+
declare %dx.types.HitObject @dx.op.hitObject_MakeNop(i32) #1
27+
28+
; Function Attrs: nounwind
29+
declare void @dx.op.maybeReorderThread(i32, %dx.types.HitObject, i32, i32) #0
30+
31+
attributes #0 = { nounwind }
32+
attributes #1 = { nounwind readnone }
33+
34+
!dx.version = !{!0}
35+
!dx.valver = !{!0}
36+
!dx.shaderModel = !{!1}
37+
!dx.typeAnnotations = !{!2}
38+
!dx.entryPoints = !{!6, !8}
39+
40+
!0 = !{i32 1, i32 9}
41+
!1 = !{!"lib", i32 6, i32 9}
42+
!2 = !{i32 1, void ()* @"\01?main@@YAXXZ", !3}
43+
!3 = !{!4}
44+
!4 = !{i32 1, !5, !5}
45+
!5 = !{}
46+
!6 = !{null, !"", null, null, !7}
47+
!7 = !{i32 0, i64 0}
48+
!8 = !{void ()* @"\01?main@@YAXXZ", !"\01?main@@YAXXZ", null, null, !9}
49+
!9 = !{i32 8, i32 7, i32 5, !10}
50+
!10 = !{i32 0}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; RUN: %dxv %s | FileCheck %s
2+
3+
; CHECK: Validation succeeded.
4+
5+
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"
6+
target triple = "dxil-ms-dx"
7+
8+
%dx.types.HitObject = type { i8* }
9+
10+
; Function Attrs: nounwind
11+
define void @"\01?main@@YAXXZ"() #0 {
12+
%nop = call %dx.types.HitObject @dx.op.hitObject_MakeNop(i32 266) ; HitObject_MakeNop()
13+
call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject %nop, i32 241, i32 3) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB)
14+
call void @dx.op.maybeReorderThread(i32 268, %dx.types.HitObject undef, i32 242, i32 7) ; MaybeReorderThread(hitObject,coherenceHint,numCoherenceHintBitsFromLSB)
15+
ret void
16+
}
17+
18+
; Function Attrs: nounwind readnone
19+
declare %dx.types.HitObject @dx.op.hitObject_MakeNop(i32) #1
20+
21+
; Function Attrs: nounwind
22+
declare void @dx.op.maybeReorderThread(i32, %dx.types.HitObject, i32, i32) #0
23+
24+
attributes #0 = { nounwind }
25+
attributes #1 = { nounwind readnone }
26+
27+
!dx.version = !{!0}
28+
!dx.valver = !{!0}
29+
!dx.shaderModel = !{!1}
30+
!dx.typeAnnotations = !{!2}
31+
!dx.entryPoints = !{!6, !8}
32+
33+
!0 = !{i32 1, i32 9}
34+
!1 = !{!"lib", i32 6, i32 9}
35+
!2 = !{i32 1, void ()* @"\01?main@@YAXXZ", !3}
36+
!3 = !{!4}
37+
!4 = !{i32 1, !5, !5}
38+
!5 = !{}
39+
!6 = !{null, !"", null, null, !7}
40+
!7 = !{i32 0, i64 0}
41+
!8 = !{void ()* @"\01?main@@YAXXZ", !"\01?main@@YAXXZ", null, null, !9}
42+
!9 = !{i32 8, i32 7, i32 5, !10}
43+
!10 = !{i32 0}

0 commit comments

Comments
 (0)