Skip to content

Commit 0393884

Browse files
joaosaffranjoaosaffran
authored andcommitted
[HLSL] Adding support for Root Constants in LLVM Metadata (llvm#135085)
- Closes [llvm#126637](llvm#126637) --------- Co-authored-by: joaosaffran <[email protected]>
1 parent 7bc735c commit 0393884

11 files changed

+256
-19
lines changed

llvm/lib/Target/DirectX/DXILRootSignature.cpp

Lines changed: 109 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,66 @@ static bool reportError(LLVMContext *Ctx, Twine Message,
4040
return true;
4141
}
4242

43+
static bool reportValueError(LLVMContext *Ctx, Twine ParamName,
44+
uint32_t Value) {
45+
Ctx->diagnose(DiagnosticInfoGeneric(
46+
"Invalid value for " + ParamName + ": " + Twine(Value), DS_Error));
47+
return true;
48+
}
49+
50+
static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
51+
unsigned int OpId) {
52+
if (auto *CI =
53+
mdconst::dyn_extract<ConstantInt>(Node->getOperand(OpId).get()))
54+
return CI->getZExtValue();
55+
return std::nullopt;
56+
}
57+
4358
static bool parseRootFlags(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
4459
MDNode *RootFlagNode) {
4560

4661
if (RootFlagNode->getNumOperands() != 2)
4762
return reportError(Ctx, "Invalid format for RootFlag Element");
4863

49-
auto *Flag = mdconst::extract<ConstantInt>(RootFlagNode->getOperand(1));
50-
RSD.Flags = Flag->getZExtValue();
64+
if (std::optional<uint32_t> Val = extractMdIntValue(RootFlagNode, 1))
65+
RSD.Flags = *Val;
66+
else
67+
return reportError(Ctx, "Invalid value for RootFlag");
68+
69+
return false;
70+
}
71+
72+
static bool parseRootConstants(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
73+
MDNode *RootConstantNode) {
74+
75+
if (RootConstantNode->getNumOperands() != 5)
76+
return reportError(Ctx, "Invalid format for RootConstants Element");
77+
78+
mcdxbc::RootParameter NewParameter;
79+
NewParameter.Header.ParameterType =
80+
llvm::to_underlying(dxbc::RootParameterType::Constants32Bit);
81+
82+
if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 1))
83+
NewParameter.Header.ShaderVisibility = *Val;
84+
else
85+
return reportError(Ctx, "Invalid value for ShaderVisibility");
86+
87+
if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 2))
88+
NewParameter.Constants.ShaderRegister = *Val;
89+
else
90+
return reportError(Ctx, "Invalid value for ShaderRegister");
91+
92+
if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 3))
93+
NewParameter.Constants.RegisterSpace = *Val;
94+
else
95+
return reportError(Ctx, "Invalid value for RegisterSpace");
96+
97+
if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 4))
98+
NewParameter.Constants.Num32BitValues = *Val;
99+
else
100+
return reportError(Ctx, "Invalid value for Num32BitValues");
101+
102+
RSD.Parameters.push_back(NewParameter);
51103

52104
return false;
53105
}
@@ -62,12 +114,16 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
62114
RootSignatureElementKind ElementKind =
63115
StringSwitch<RootSignatureElementKind>(ElementText->getString())
64116
.Case("RootFlags", RootSignatureElementKind::RootFlags)
117+
.Case("RootConstants", RootSignatureElementKind::RootConstants)
65118
.Default(RootSignatureElementKind::Error);
66119

67120
switch (ElementKind) {
68121

69122
case RootSignatureElementKind::RootFlags:
70123
return parseRootFlags(Ctx, RSD, Element);
124+
case RootSignatureElementKind::RootConstants:
125+
return parseRootConstants(Ctx, RSD, Element);
126+
break;
71127
case RootSignatureElementKind::Error:
72128
return reportError(Ctx, "Invalid Root Signature Element: " +
73129
ElementText->getString());
@@ -94,10 +150,29 @@ static bool parse(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
94150

95151
static bool verifyRootFlag(uint32_t Flags) { return (Flags & ~0xfff) == 0; }
96152

153+
static bool verifyVersion(uint32_t Version) {
154+
return (Version == 1 || Version == 2);
155+
}
156+
97157
static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
158+
159+
if (!verifyVersion(RSD.Version)) {
160+
return reportValueError(Ctx, "Version", RSD.Version);
161+
}
162+
98163
if (!verifyRootFlag(RSD.Flags)) {
99-
return reportError(Ctx, "Invalid Root Signature flag value");
164+
return reportValueError(Ctx, "RootFlags", RSD.Flags);
165+
}
166+
167+
for (const mcdxbc::RootParameter &P : RSD.Parameters) {
168+
if (!dxbc::isValidShaderVisibility(P.Header.ShaderVisibility))
169+
return reportValueError(Ctx, "ShaderVisibility",
170+
P.Header.ShaderVisibility);
171+
172+
assert(dxbc::isValidParameterType(P.Header.ParameterType) &&
173+
"Invalid value for ParameterType");
100174
}
175+
101176
return false;
102177
}
103178

@@ -166,6 +241,10 @@ analyzeModule(Module &M) {
166241
}
167242

168243
mcdxbc::RootSignatureDesc RSD;
244+
// Clang emits the root signature data in dxcontainer following a specific
245+
// sequence. First the header, then the root parameters. So the header
246+
// offset will always equal to the header size.
247+
RSD.RootParameterOffset = sizeof(dxbc::RootSignatureHeader);
169248

170249
if (parse(Ctx, RSD, RootElementListNode) || validate(Ctx, RSD)) {
171250
return RSDMap;
@@ -192,7 +271,6 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
192271
SmallDenseMap<const Function *, mcdxbc::RootSignatureDesc> &RSDMap =
193272
AM.getResult<RootSignatureAnalysis>(M);
194273

195-
const size_t RSHSize = sizeof(dxbc::RootSignatureHeader);
196274
OS << "Root Signature Definitions"
197275
<< "\n";
198276
uint8_t Space = 0;
@@ -205,14 +283,33 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
205283

206284
// start root signature header
207285
Space++;
208-
OS << indent(Space) << "Flags: " << format_hex(RS.Flags, 8) << ":\n";
209-
OS << indent(Space) << "Version: " << RS.Version << ":\n";
210-
OS << indent(Space) << "NumParameters: " << RS.Parameters.size() << ":\n";
211-
OS << indent(Space) << "RootParametersOffset: " << RSHSize << ":\n";
212-
OS << indent(Space) << "NumStaticSamplers: " << 0 << ":\n";
213-
OS << indent(Space)
214-
<< "StaticSamplersOffset: " << RSHSize + RS.Parameters.size_in_bytes()
215-
<< ":\n";
286+
OS << indent(Space) << "Flags: " << format_hex(RS.Flags, 8) << "\n";
287+
OS << indent(Space) << "Version: " << RS.Version << "\n";
288+
OS << indent(Space) << "RootParametersOffset: " << RS.RootParameterOffset
289+
<< "\n";
290+
OS << indent(Space) << "NumParameters: " << RS.Parameters.size() << "\n";
291+
Space++;
292+
for (auto const &P : RS.Parameters) {
293+
OS << indent(Space) << "- Parameter Type: " << P.Header.ParameterType
294+
<< "\n";
295+
OS << indent(Space + 2)
296+
<< "Shader Visibility: " << P.Header.ShaderVisibility << "\n";
297+
switch (P.Header.ParameterType) {
298+
case llvm::to_underlying(dxbc::RootParameterType::Constants32Bit):
299+
OS << indent(Space + 2)
300+
<< "Register Space: " << P.Constants.RegisterSpace << "\n";
301+
OS << indent(Space + 2)
302+
<< "Shader Register: " << P.Constants.ShaderRegister << "\n";
303+
OS << indent(Space + 2)
304+
<< "Num 32 Bit Values: " << P.Constants.Num32BitValues << "\n";
305+
break;
306+
}
307+
}
308+
Space--;
309+
OS << indent(Space) << "NumStaticSamplers: " << 0 << "\n";
310+
OS << indent(Space) << "StaticSamplersOffset: " << RS.StaticSamplersOffset
311+
<< "\n";
312+
216313
Space--;
217314
// end root signature header
218315
}

llvm/lib/Target/DirectX/DXILRootSignature.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@
2424
namespace llvm {
2525
namespace dxil {
2626

27-
enum class RootSignatureElementKind { Error = 0, RootFlags = 1 };
27+
enum class RootSignatureElementKind {
28+
Error = 0,
29+
RootFlags = 1,
30+
RootConstants = 2
31+
};
2832
class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
2933
friend AnalysisInfoMixin<RootSignatureAnalysis>;
3034
static AnalysisKey Key;

llvm/test/CodeGen/DirectX/ContainerData/RootSignature-Flags.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
2323
; DXC-NEXT: RootSignature:
2424
; DXC-NEXT: Version: 2
2525
; DXC-NEXT: NumRootParameters: 0
26-
; DXC-NEXT: RootParametersOffset: 0
26+
; DXC-NEXT: RootParametersOffset: 24
2727
; DXC-NEXT: NumStaticSamplers: 0
2828
; DXC-NEXT: StaticSamplersOffset: 0
2929
; DXC-NEXT: Parameters: []

llvm/test/CodeGen/DirectX/ContainerData/RootSignature-MultipleEntryFunctions.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
2626
; CHECK-LABEL: Definition for 'main':
2727
; CHECK-NEXT: Flags: 0x000001
2828
; CHECK-NEXT: Version: 2
29-
; CHECK-NEXT: NumParameters: 0
3029
; CHECK-NEXT: RootParametersOffset: 24
30+
; CHECK-NEXT: NumParameters: 0
3131
; CHECK-NEXT: NumStaticSamplers: 0
32-
; CHECK-NEXT: StaticSamplersOffset: 24
32+
; CHECK-NEXT: StaticSamplersOffset: 0
3333

3434
; CHECK-LABEL: Definition for 'anotherMain':
3535
; CHECK-NEXT: Flags: 0x000002
3636
; CHECK-NEXT: Version: 2
37-
; CHECK-NEXT: NumParameters: 0
3837
; CHECK-NEXT: RootParametersOffset: 24
38+
; CHECK-NEXT: NumParameters: 0
3939
; CHECK-NEXT: NumStaticSamplers: 0
40-
; CHECK-NEXT: StaticSamplersOffset: 24
40+
; CHECK-NEXT: StaticSamplersOffset: 0
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
2+
3+
; CHECK: error: Invalid value for ShaderVisibility: 255
4+
; CHECK-NOT: Root Signature Definitions
5+
6+
target triple = "dxil-unknown-shadermodel6.0-compute"
7+
8+
9+
define void @main() #0 {
10+
entry:
11+
ret void
12+
}
13+
14+
attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
15+
16+
17+
!dx.rootsignatures = !{!2} ; list of function/root signature pairs
18+
!2 = !{ ptr @main, !3 } ; function, root signature
19+
!3 = !{ !5 } ; list of root signature elements
20+
!5 = !{ !"RootConstants", i32 255, i32 1, i32 2, i32 3 }
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; RUN: opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
2+
3+
target triple = "dxil-unknown-shadermodel6.0-compute"
4+
5+
6+
define void @main() #0 {
7+
entry:
8+
ret void
9+
}
10+
11+
attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
12+
13+
!dx.rootsignatures = !{!2} ; list of function/root signature pairs
14+
!2 = !{ ptr @main, !3 } ; function, root signature
15+
!3 = !{ !4, !5 } ; list of root signature elements
16+
!4 = !{ !"RootFlags", i32 1 } ; 1 = allow_input_assembler_input_layout
17+
!5 = !{ !"RootConstants", i32 0, i32 1, i32 2, i32 3 }
18+
19+
;CHECK-LABEL: Definition for 'main':
20+
;CHECK-NEXT: Flags: 0x000001
21+
;CHECK-NEXT: Version: 2
22+
;CHECK-NEXT: RootParametersOffset: 24
23+
;CHECK-NEXT: NumParameters: 1
24+
;CHECK-NEXT: - Parameter Type: 1
25+
;CHECK-NEXT: Shader Visibility: 0
26+
;CHECK-NEXT: Register Space: 2
27+
;CHECK-NEXT: Shader Register: 1
28+
;CHECK-NEXT: Num 32 Bit Values: 3
29+
;CHECK-NEXT: NumStaticSamplers: 0
30+
;CHECK-NEXT: StaticSamplersOffset: 0
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
2+
3+
target triple = "dxil-unknown-shadermodel6.0-compute"
4+
5+
; CHECK: error: Invalid value for Num32BitValues
6+
; CHECK-NOT: Root Signature Definitions
7+
8+
define void @main() {
9+
entry:
10+
ret void
11+
}
12+
13+
!dx.rootsignatures = !{!2} ; list of function/root signature pairs
14+
!2 = !{ ptr @main, !3 } ; function, root signature
15+
!3 = !{ !5 } ; list of root signature elements
16+
!5 = !{ !"RootConstants", i32 0, i32 1, i32 2, !"Invalid" }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
2+
3+
target triple = "dxil-unknown-shadermodel6.0-compute"
4+
5+
; CHECK: error: Invalid value for RegisterSpace
6+
; CHECK-NOT: Root Signature Definitions
7+
8+
define void @main() #0 {
9+
entry:
10+
ret void
11+
}
12+
attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
13+
14+
15+
!dx.rootsignatures = !{!2} ; list of function/root signature pairs
16+
!2 = !{ ptr @main, !3 } ; function, root signature
17+
!3 = !{ !5 } ; list of root signature elements
18+
!5 = !{ !"RootConstants", i32 0, i32 1, !"Invalid", i32 3 }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
2+
3+
target triple = "dxil-unknown-shadermodel6.0-compute"
4+
5+
; CHECK: error: Invalid value for ShaderRegister
6+
; CHECK-NOT: Root Signature Definitions
7+
8+
define void @main() #0 {
9+
entry:
10+
ret void
11+
}
12+
attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
13+
14+
15+
!dx.rootsignatures = !{!2} ; list of function/root signature pairs
16+
!2 = !{ ptr @main, !3 } ; function, root signature
17+
!3 = !{ !5 } ; list of root signature elements
18+
!5 = !{ !"RootConstants", i32 0, !"Invalid", i32 2, i32 3 }
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; RUN: opt %s -dxil-embed -dxil-globals -S -o - | FileCheck %s
2+
; RUN: llc %s --filetype=obj -o - | obj2yaml | FileCheck %s --check-prefix=DXC
3+
4+
target triple = "dxil-unknown-shadermodel6.0-compute"
5+
6+
; CHECK: @dx.rts0 = private constant [48 x i8] c"{{.*}}", section "RTS0", align 4
7+
8+
define void @main() #0 {
9+
entry:
10+
ret void
11+
}
12+
attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
13+
14+
15+
!dx.rootsignatures = !{!2} ; list of function/root signature pairs
16+
!2 = !{ ptr @main, !3 } ; function, root signature
17+
!3 = !{ !5 } ; list of root signature elements
18+
!5 = !{ !"RootConstants", i32 0, i32 1, i32 2, i32 3 }
19+
20+
; DXC: - Name: RTS0
21+
; DXC-NEXT: Size: 48
22+
; DXC-NEXT: RootSignature:
23+
; DXC-NEXT: Version: 2
24+
; DXC-NEXT: NumRootParameters: 1
25+
; DXC-NEXT: RootParametersOffset: 24
26+
; DXC-NEXT: NumStaticSamplers: 0
27+
; DXC-NEXT: StaticSamplersOffset: 0
28+
; DXC-NEXT: Parameters:
29+
; DXC-NEXT: - ParameterType: 1
30+
; DXC-NEXT: ShaderVisibility: 0
31+
; DXC-NEXT: Constants:
32+
; DXC-NEXT: Num32BitValues: 3
33+
; DXC-NEXT: RegisterSpace: 2
34+
; DXC-NEXT: ShaderRegister: 1

0 commit comments

Comments
 (0)