Skip to content

Commit ad6575f

Browse files
joaosaffranjoaosaffran
andauthored
[HLSL] Adding support for root descriptors in root signature metadata representation (#139781)
- adds parsing from metadata into dxcontainer binary - adds validations as described in the spec - adds testing scenarios closes: [#126638](llvm/llvm-project#126638) --------- Co-authored-by: joaosaffran <joao.saffran@microsoft.com>
1 parent b194cf1 commit ad6575f

9 files changed

+263
-9
lines changed

llvm/lib/Target/DirectX/DXILRootSignature.cpp

Lines changed: 126 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
5555
return std::nullopt;
5656
}
5757

58+
static std::optional<StringRef> extractMdStringValue(MDNode *Node,
59+
unsigned int OpId) {
60+
MDString *NodeText = dyn_cast<MDString>(Node->getOperand(OpId));
61+
if (NodeText == nullptr)
62+
return std::nullopt;
63+
return NodeText->getString();
64+
}
65+
5866
static bool parseRootFlags(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
5967
MDNode *RootFlagNode) {
6068

@@ -107,17 +115,79 @@ static bool parseRootConstants(LLVMContext *Ctx, mcdxbc::RootSignatureDesc &RSD,
107115
return false;
108116
}
109117

118+
static bool parseRootDescriptors(LLVMContext *Ctx,
119+
mcdxbc::RootSignatureDesc &RSD,
120+
MDNode *RootDescriptorNode,
121+
RootSignatureElementKind ElementKind) {
122+
assert(ElementKind == RootSignatureElementKind::SRV ||
123+
ElementKind == RootSignatureElementKind::UAV ||
124+
ElementKind == RootSignatureElementKind::CBV &&
125+
"parseRootDescriptors should only be called with RootDescriptor "
126+
"element kind.");
127+
if (RootDescriptorNode->getNumOperands() != 5)
128+
return reportError(Ctx, "Invalid format for Root Descriptor Element");
129+
130+
dxbc::RTS0::v1::RootParameterHeader Header;
131+
switch (ElementKind) {
132+
case RootSignatureElementKind::SRV:
133+
Header.ParameterType = llvm::to_underlying(dxbc::RootParameterType::SRV);
134+
break;
135+
case RootSignatureElementKind::UAV:
136+
Header.ParameterType = llvm::to_underlying(dxbc::RootParameterType::UAV);
137+
break;
138+
case RootSignatureElementKind::CBV:
139+
Header.ParameterType = llvm::to_underlying(dxbc::RootParameterType::CBV);
140+
break;
141+
default:
142+
llvm_unreachable("invalid Root Descriptor kind");
143+
break;
144+
}
145+
146+
if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 1))
147+
Header.ShaderVisibility = *Val;
148+
else
149+
return reportError(Ctx, "Invalid value for ShaderVisibility");
150+
151+
dxbc::RTS0::v2::RootDescriptor Descriptor;
152+
if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 2))
153+
Descriptor.ShaderRegister = *Val;
154+
else
155+
return reportError(Ctx, "Invalid value for ShaderRegister");
156+
157+
if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 3))
158+
Descriptor.RegisterSpace = *Val;
159+
else
160+
return reportError(Ctx, "Invalid value for RegisterSpace");
161+
162+
if (RSD.Version == 1) {
163+
RSD.ParametersContainer.addParameter(Header, Descriptor);
164+
return false;
165+
}
166+
assert(RSD.Version > 1);
167+
168+
if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 4))
169+
Descriptor.Flags = *Val;
170+
else
171+
return reportError(Ctx, "Invalid value for Root Descriptor Flags");
172+
173+
RSD.ParametersContainer.addParameter(Header, Descriptor);
174+
return false;
175+
}
176+
110177
static bool parseRootSignatureElement(LLVMContext *Ctx,
111178
mcdxbc::RootSignatureDesc &RSD,
112179
MDNode *Element) {
113-
MDString *ElementText = cast<MDString>(Element->getOperand(0));
114-
if (ElementText == nullptr)
180+
std::optional<StringRef> ElementText = extractMdStringValue(Element, 0);
181+
if (!ElementText.has_value())
115182
return reportError(Ctx, "Invalid format for Root Element");
116183

117184
RootSignatureElementKind ElementKind =
118-
StringSwitch<RootSignatureElementKind>(ElementText->getString())
185+
StringSwitch<RootSignatureElementKind>(*ElementText)
119186
.Case("RootFlags", RootSignatureElementKind::RootFlags)
120187
.Case("RootConstants", RootSignatureElementKind::RootConstants)
188+
.Case("RootCBV", RootSignatureElementKind::CBV)
189+
.Case("RootSRV", RootSignatureElementKind::SRV)
190+
.Case("RootUAV", RootSignatureElementKind::UAV)
121191
.Default(RootSignatureElementKind::Error);
122192

123193
switch (ElementKind) {
@@ -126,10 +196,12 @@ static bool parseRootSignatureElement(LLVMContext *Ctx,
126196
return parseRootFlags(Ctx, RSD, Element);
127197
case RootSignatureElementKind::RootConstants:
128198
return parseRootConstants(Ctx, RSD, Element);
129-
break;
199+
case RootSignatureElementKind::CBV:
200+
case RootSignatureElementKind::SRV:
201+
case RootSignatureElementKind::UAV:
202+
return parseRootDescriptors(Ctx, RSD, Element, ElementKind);
130203
case RootSignatureElementKind::Error:
131-
return reportError(Ctx, "Invalid Root Signature Element: " +
132-
ElementText->getString());
204+
return reportError(Ctx, "Invalid Root Signature Element: " + *ElementText);
133205
}
134206

135207
llvm_unreachable("Unhandled RootSignatureElementKind enum.");
@@ -157,6 +229,18 @@ static bool verifyVersion(uint32_t Version) {
157229
return (Version == 1 || Version == 2);
158230
}
159231

232+
static bool verifyRegisterValue(uint32_t RegisterValue) {
233+
return RegisterValue != ~0U;
234+
}
235+
236+
// This Range is reserverved, therefore invalid, according to the spec
237+
// https://github.com/llvm/wg-hlsl/blob/main/proposals/0002-root-signature-in-clang.md#all-the-values-should-be-legal
238+
static bool verifyRegisterSpace(uint32_t RegisterSpace) {
239+
return !(RegisterSpace >= 0xFFFFFFF0 && RegisterSpace <= 0xFFFFFFFF);
240+
}
241+
242+
static bool verifyDescriptorFlag(uint32_t Flags) { return (Flags & ~0xE) == 0; }
243+
160244
static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
161245

162246
if (!verifyVersion(RSD.Version)) {
@@ -174,6 +258,28 @@ static bool validate(LLVMContext *Ctx, const mcdxbc::RootSignatureDesc &RSD) {
174258

175259
assert(dxbc::isValidParameterType(Info.Header.ParameterType) &&
176260
"Invalid value for ParameterType");
261+
262+
switch (Info.Header.ParameterType) {
263+
264+
case llvm::to_underlying(dxbc::RootParameterType::CBV):
265+
case llvm::to_underlying(dxbc::RootParameterType::UAV):
266+
case llvm::to_underlying(dxbc::RootParameterType::SRV): {
267+
const dxbc::RTS0::v2::RootDescriptor &Descriptor =
268+
RSD.ParametersContainer.getRootDescriptor(Info.Location);
269+
if (!verifyRegisterValue(Descriptor.ShaderRegister))
270+
return reportValueError(Ctx, "ShaderRegister",
271+
Descriptor.ShaderRegister);
272+
273+
if (!verifyRegisterSpace(Descriptor.RegisterSpace))
274+
return reportValueError(Ctx, "RegisterSpace", Descriptor.RegisterSpace);
275+
276+
if (RSD.Version > 1) {
277+
if (!verifyDescriptorFlag(Descriptor.Flags))
278+
return reportValueError(Ctx, "DescriptorFlag", Descriptor.Flags);
279+
}
280+
break;
281+
}
282+
}
177283
}
178284

179285
return false;
@@ -313,6 +419,20 @@ PreservedAnalyses RootSignatureAnalysisPrinter::run(Module &M,
313419
<< "Shader Register: " << Constants.ShaderRegister << "\n";
314420
OS << indent(Space + 2)
315421
<< "Num 32 Bit Values: " << Constants.Num32BitValues << "\n";
422+
break;
423+
}
424+
case llvm::to_underlying(dxbc::RootParameterType::CBV):
425+
case llvm::to_underlying(dxbc::RootParameterType::UAV):
426+
case llvm::to_underlying(dxbc::RootParameterType::SRV): {
427+
const dxbc::RTS0::v2::RootDescriptor &Descriptor =
428+
RS.ParametersContainer.getRootDescriptor(Loc);
429+
OS << indent(Space + 2)
430+
<< "Register Space: " << Descriptor.RegisterSpace << "\n";
431+
OS << indent(Space + 2)
432+
<< "Shader Register: " << Descriptor.ShaderRegister << "\n";
433+
if (RS.Version > 1)
434+
OS << indent(Space + 2) << "Flags: " << Descriptor.Flags << "\n";
435+
break;
316436
}
317437
}
318438
Space--;

llvm/lib/Target/DirectX/DXILRootSignature.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ namespace dxil {
2727
enum class RootSignatureElementKind {
2828
Error = 0,
2929
RootFlags = 1,
30-
RootConstants = 2
30+
RootConstants = 2,
31+
SRV = 3,
32+
UAV = 4,
33+
CBV = 5,
3134
};
3235
class RootSignatureAnalysis : public AnalysisInfoMixin<RootSignatureAnalysis> {
3336
friend AnalysisInfoMixin<RootSignatureAnalysis>;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
2+
3+
; CHECK: error: Invalid format for Root Element
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+
!dx.rootsignatures = !{!0}
17+
!0 = !{ ptr @main, !1 }
18+
!1 = !{ !2 }
19+
!2 = !{ i32 0 }

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,25 @@ attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
1212

1313
!dx.rootsignatures = !{!2} ; list of function/root signature pairs
1414
!2 = !{ ptr @main, !3 } ; function, root signature
15-
!3 = !{ !4, !5 } ; list of root signature elements
15+
!3 = !{ !4, !5, !6 } ; list of root signature elements
1616
!4 = !{ !"RootFlags", i32 1 } ; 1 = allow_input_assembler_input_layout
1717
!5 = !{ !"RootConstants", i32 0, i32 1, i32 2, i32 3 }
18+
!6 = !{ !"RootSRV", i32 1, i32 4, i32 5, i32 6 }
1819

1920
;CHECK-LABEL: Definition for 'main':
2021
;CHECK-NEXT: Flags: 0x000001
2122
;CHECK-NEXT: Version: 2
2223
;CHECK-NEXT: RootParametersOffset: 24
23-
;CHECK-NEXT: NumParameters: 1
24+
;CHECK-NEXT: NumParameters: 2
2425
;CHECK-NEXT: - Parameter Type: 1
2526
;CHECK-NEXT: Shader Visibility: 0
2627
;CHECK-NEXT: Register Space: 2
2728
;CHECK-NEXT: Shader Register: 1
2829
;CHECK-NEXT: Num 32 Bit Values: 3
30+
;CHECK-NEXT: - Parameter Type: 3
31+
;CHECK-NEXT: Shader Visibility: 1
32+
;CHECK-NEXT: Register Space: 5
33+
;CHECK-NEXT: Shader Register: 4
34+
;CHECK-NEXT: Flags: 6
2935
;CHECK-NEXT: NumStaticSamplers: 0
3036
;CHECK-NEXT: StaticSamplersOffset: 0
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+
6+
; CHECK: error: Invalid value for DescriptorFlag: 3
7+
; CHECK-NOT: Root Signature Definitions
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 = !{ !"RootCBV", i32 0, i32 1, i32 2, 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+
6+
; CHECK: error: Invalid Root Signature Element: Invalid
7+
; CHECK-NOT: Root Signature Definitions
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 = !{ !"Invalid", i32 0, i32 1, i32 2, 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+
6+
; CHECK: error: Invalid value for RegisterSpace: 4294967280
7+
; CHECK-NOT: Root Signature Definitions
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 = !{ !"RootCBV", i32 0, i32 1, i32 4294967280, i32 0 }
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+
6+
; CHECK: error: Invalid value for ShaderRegister: 4294967295
7+
; CHECK-NOT: Root Signature Definitions
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 = !{ !"RootCBV", i32 0, i32 4294967295, 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 = !{ !"RootCBV", i32 0, i32 1, i32 2, i32 8 }
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: 2
30+
; DXC-NEXT: ShaderVisibility: 0
31+
; DXC-NEXT: Descriptor:
32+
; DXC-NEXT: RegisterSpace: 2
33+
; DXC-NEXT: ShaderRegister: 1
34+
; DXC-NEXT: DATA_STATIC: true

0 commit comments

Comments
 (0)