Skip to content

Commit 4f54d71

Browse files
authored
[HLSL][DirectX] Move handling of resource element types into the frontend
Rather than shepherding a type name all the way to the backend as a string and attempting to parse it, get the element type out of the AST and store that in the resource annotation metadata directly. Pull Request: #75674
1 parent 4123b95 commit 4f54d71

File tree

11 files changed

+204
-138
lines changed

11 files changed

+204
-138
lines changed

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,8 @@ void CGHLSLRuntime::finishCodeGen() {
182182
llvm::hlsl::ResourceKind RK = Buf.IsCBuffer
183183
? llvm::hlsl::ResourceKind::CBuffer
184184
: llvm::hlsl::ResourceKind::TBuffer;
185-
std::string TyName =
186-
Buf.Name.str() + (Buf.IsCBuffer ? ".cb." : ".tb.") + "ty";
187-
addBufferResourceAnnotation(GV, TyName, RC, RK, /*IsROV=*/false,
188-
Buf.Binding);
185+
addBufferResourceAnnotation(GV, RC, RK, /*IsROV=*/false,
186+
llvm::hlsl::ElementType::Invalid, Buf.Binding);
189187
}
190188
}
191189

@@ -194,10 +192,10 @@ CGHLSLRuntime::Buffer::Buffer(const HLSLBufferDecl *D)
194192
Binding(D->getAttr<HLSLResourceBindingAttr>()) {}
195193

196194
void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV,
197-
llvm::StringRef TyName,
198195
llvm::hlsl::ResourceClass RC,
199196
llvm::hlsl::ResourceKind RK,
200197
bool IsROV,
198+
llvm::hlsl::ElementType ET,
201199
BufferResBinding &Binding) {
202200
llvm::Module &M = CGM.getModule();
203201

@@ -216,15 +214,62 @@ void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV,
216214
assert(false && "Unsupported buffer type!");
217215
return;
218216
}
219-
220217
assert(ResourceMD != nullptr &&
221218
"ResourceMD must have been set by the switch above.");
222219

223220
llvm::hlsl::FrontendResource Res(
224-
GV, TyName, RK, IsROV, Binding.Reg.value_or(UINT_MAX), Binding.Space);
221+
GV, RK, ET, IsROV, Binding.Reg.value_or(UINT_MAX), Binding.Space);
225222
ResourceMD->addOperand(Res.getMetadata());
226223
}
227224

225+
static llvm::hlsl::ElementType
226+
calculateElementType(const ASTContext &Context, const clang::Type *ResourceTy) {
227+
using llvm::hlsl::ElementType;
228+
229+
// TODO: We may need to update this when we add things like ByteAddressBuffer
230+
// that don't have a template parameter (or, indeed, an element type).
231+
const auto *TST = ResourceTy->getAs<TemplateSpecializationType>();
232+
assert(TST && "Resource types must be template specializations");
233+
ArrayRef<TemplateArgument> Args = TST->template_arguments();
234+
assert(!Args.empty() && "Resource has no element type");
235+
236+
// At this point we have a resource with an element type, so we can assume
237+
// that it's valid or we would have diagnosed the error earlier.
238+
QualType ElTy = Args[0].getAsType();
239+
240+
// We should either have a basic type or a vector of a basic type.
241+
if (const auto *VecTy = ElTy->getAs<clang::VectorType>())
242+
ElTy = VecTy->getElementType();
243+
244+
if (ElTy->isSignedIntegerType()) {
245+
switch (Context.getTypeSize(ElTy)) {
246+
case 16:
247+
return ElementType::I16;
248+
case 32:
249+
return ElementType::I32;
250+
case 64:
251+
return ElementType::I64;
252+
}
253+
} else if (ElTy->isUnsignedIntegerType()) {
254+
switch (Context.getTypeSize(ElTy)) {
255+
case 16:
256+
return ElementType::U16;
257+
case 32:
258+
return ElementType::U32;
259+
case 64:
260+
return ElementType::U64;
261+
}
262+
} else if (ElTy->isSpecificBuiltinType(BuiltinType::Half))
263+
return ElementType::F16;
264+
else if (ElTy->isSpecificBuiltinType(BuiltinType::Float))
265+
return ElementType::F32;
266+
else if (ElTy->isSpecificBuiltinType(BuiltinType::Double))
267+
return ElementType::F64;
268+
269+
// TODO: We need to handle unorm/snorm float types here once we support them
270+
llvm_unreachable("Invalid element type for resource");
271+
}
272+
228273
void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) {
229274
const Type *Ty = D->getType()->getPointeeOrArrayElementType();
230275
if (!Ty)
@@ -239,10 +284,10 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) {
239284
llvm::hlsl::ResourceClass RC = Attr->getResourceClass();
240285
llvm::hlsl::ResourceKind RK = Attr->getResourceKind();
241286
bool IsROV = Attr->getIsROV();
287+
llvm::hlsl::ElementType ET = calculateElementType(CGM.getContext(), Ty);
242288

243-
QualType QT(Ty, 0);
244289
BufferResBinding Binding(D->getAttr<HLSLResourceBindingAttr>());
245-
addBufferResourceAnnotation(GV, QT.getAsString(), RC, RK, IsROV, Binding);
290+
addBufferResourceAnnotation(GV, RC, RK, IsROV, ET, Binding);
246291
}
247292

248293
CGHLSLRuntime::BufferResBinding::BufferResBinding(

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ class CGHLSLRuntime {
9090

9191
private:
9292
void addBufferResourceAnnotation(llvm::GlobalVariable *GV,
93-
llvm::StringRef TyName,
9493
llvm::hlsl::ResourceClass RC,
9594
llvm::hlsl::ResourceKind RK, bool IsROV,
95+
llvm::hlsl::ElementType ET,
9696
BufferResBinding &Binding);
9797
void addConstant(VarDecl *D, Buffer &CB);
9898
void addBufferDecls(const DeclContext *DC, Buffer &CB);

clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
22

33
RWBuffer<float> Buffer1;
44
RWBuffer<vector<float, 4> > BufferArray[4];
@@ -16,9 +16,9 @@ void main() {
1616
}
1717

1818
// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]], ![[SingleAllocated:[0-9]+]], ![[ArrayAllocated:[0-9]+]], ![[SingleSpace:[0-9]+]], ![[ArraySpace:[0-9]+]]}
19-
// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer<float>", i32 10, i1 false, i32 -1, i32 0}
20-
// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer<vector<float, 4> >", i32 10, i1 false, i32 -1, i32 0}
21-
// CHECK-DAG: ![[SingleAllocated]] = !{ptr @"?Buffer2@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer<float>", i32 10, i1 false, i32 3, i32 0}
22-
// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @"?BufferArray2@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer<vector<float, 4> >", i32 10, i1 false, i32 4, i32 0}
23-
// CHECK-DAG: ![[SingleSpace]] = !{ptr @"?Buffer3@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer<float>", i32 10, i1 false, i32 3, i32 1}
24-
// CHECK-DAG: ![[ArraySpace]] = !{ptr @"?BufferArray3@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer<vector<float, 4> >", i32 10, i1 false, i32 4, i32 1}
19+
// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RWBuffer@M@hlsl@@A", i32 10, i32 9, i1 false, i32 -1, i32 0}
20+
// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", i32 10, i32 9, i1 false, i32 -1, i32 0}
21+
// CHECK-DAG: ![[SingleAllocated]] = !{ptr @"?Buffer2@@3V?$RWBuffer@M@hlsl@@A", i32 10, i32 9, i1 false, i32 3, i32 0}
22+
// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @"?BufferArray2@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", i32 10, i32 9, i1 false, i32 4, i32 0}
23+
// CHECK-DAG: ![[SingleSpace]] = !{ptr @"?Buffer3@@3V?$RWBuffer@M@hlsl@@A", i32 10, i32 9, i1 false, i32 3, i32 1}
24+
// CHECK-DAG: ![[ArraySpace]] = !{ptr @"?BufferArray3@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", i32 10, i32 9, i1 false, i32 4, i32 1}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -finclude-default-header -fnative-half-type -emit-llvm -o - %s | FileCheck %s
2+
3+
RWBuffer<int16_t> BufI16;
4+
RWBuffer<uint16_t> BufU16;
5+
RWBuffer<int> BufI32;
6+
RWBuffer<uint> BufU32;
7+
RWBuffer<int64_t> BufI64;
8+
RWBuffer<uint64_t> BufU64;
9+
RWBuffer<half> BufF16;
10+
RWBuffer<float> BufF32;
11+
RWBuffer<double> BufF64;
12+
RWBuffer< vector<int16_t, 4> > BufI16x4;
13+
RWBuffer< vector<uint, 3> > BufU32x3;
14+
RWBuffer<half2> BufF16x2;
15+
RWBuffer<float3> BufF32x3;
16+
// TODO: RWBuffer<snorm half> BufSNormF16; -> 11
17+
// TODO: RWBuffer<unorm half> BufUNormF16; -> 12
18+
// TODO: RWBuffer<snorm float> BufSNormF32; -> 13
19+
// TODO: RWBuffer<unorm float> BufUNormF32; -> 14
20+
// TODO: RWBuffer<snorm double> BufSNormF64; -> 15
21+
// TODO: RWBuffer<unorm double> BufUNormF64; -> 16
22+
23+
[numthreads(1,1,1)]
24+
void main(int GI : SV_GroupIndex) {
25+
BufI16[GI] = 0;
26+
BufU16[GI] = 0;
27+
BufI32[GI] = 0;
28+
BufU32[GI] = 0;
29+
BufI64[GI] = 0;
30+
BufU64[GI] = 0;
31+
BufF16[GI] = 0;
32+
BufF32[GI] = 0;
33+
BufF64[GI] = 0;
34+
BufI16x4[GI] = 0;
35+
BufU32x3[GI] = 0;
36+
BufF16x2[GI] = 0;
37+
BufF32x3[GI] = 0;
38+
}
39+
40+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufI16@@3V?$RWBuffer@F@hlsl@@A", i32 10, i32 2,
41+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufU16@@3V?$RWBuffer@G@hlsl@@A", i32 10, i32 3,
42+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufI32@@3V?$RWBuffer@H@hlsl@@A", i32 10, i32 4,
43+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufU32@@3V?$RWBuffer@I@hlsl@@A", i32 10, i32 5,
44+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufI64@@3V?$RWBuffer@J@hlsl@@A", i32 10, i32 6,
45+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufU64@@3V?$RWBuffer@K@hlsl@@A", i32 10, i32 7,
46+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufF16@@3V?$RWBuffer@$f16@@hlsl@@A", i32 10, i32 8,
47+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufF32@@3V?$RWBuffer@M@hlsl@@A", i32 10, i32 9,
48+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufF64@@3V?$RWBuffer@N@hlsl@@A", i32 10, i32 10,
49+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufI16x4@@3V?$RWBuffer@T?$__vector@F$03@__clang@@@hlsl@@A", i32 10, i32 2,
50+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufU32x3@@3V?$RWBuffer@T?$__vector@I$02@__clang@@@hlsl@@A", i32 10, i32 5,
51+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufF16x2@@3V?$RWBuffer@T?$__vector@$f16@$01@__clang@@@hlsl@@A", i32 10, i32 8,
52+
// CHECK: !{{[0-9]+}} = !{ptr @"?BufF32x3@@3V?$RWBuffer@T?$__vector@M$02@__clang@@@hlsl@@A", i32 10, i32 9,

clang/test/CodeGenHLSL/builtins/RasterizerOrderedBuffer-annotations.hlsl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ RasterizerOrderedBuffer<vector<float, 4> > BufferArray3[4] : register(u4, space1
1212
void main() {}
1313

1414
// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]], ![[SingleAllocated:[0-9]+]], ![[ArrayAllocated:[0-9]+]], ![[SingleSpace:[0-9]+]], ![[ArraySpace:[0-9]+]]}
15-
// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RasterizerOrderedBuffer@M@hlsl@@A", !"RasterizerOrderedBuffer<float>", i32 10, i1 true, i32 -1, i32 0}
16-
// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RasterizerOrderedBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RasterizerOrderedBuffer<vector<float, 4> >", i32 10, i1 true, i32 -1, i32 0}
17-
// CHECK-DAG: ![[SingleAllocated]] = !{ptr @"?Buffer2@@3V?$RasterizerOrderedBuffer@M@hlsl@@A", !"RasterizerOrderedBuffer<float>", i32 10, i1 true, i32 3, i32 0}
18-
// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @"?BufferArray2@@3PAV?$RasterizerOrderedBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RasterizerOrderedBuffer<vector<float, 4> >", i32 10, i1 true, i32 4, i32 0}
19-
// CHECK-DAG: ![[SingleSpace]] = !{ptr @"?Buffer3@@3V?$RasterizerOrderedBuffer@M@hlsl@@A", !"RasterizerOrderedBuffer<float>", i32 10, i1 true, i32 3, i32 1}
20-
// CHECK-DAG: ![[ArraySpace]] = !{ptr @"?BufferArray3@@3PAV?$RasterizerOrderedBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RasterizerOrderedBuffer<vector<float, 4> >", i32 10, i1 true, i32 4, i32 1}
15+
// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RasterizerOrderedBuffer@M@hlsl@@A", i32 10, i32 9, i1 true, i32 -1, i32 0}
16+
// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RasterizerOrderedBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", i32 10, i32 9, i1 true, i32 -1, i32 0}
17+
// CHECK-DAG: ![[SingleAllocated]] = !{ptr @"?Buffer2@@3V?$RasterizerOrderedBuffer@M@hlsl@@A", i32 10, i32 9, i1 true, i32 3, i32 0}
18+
// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @"?BufferArray2@@3PAV?$RasterizerOrderedBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", i32 10, i32 9, i1 true, i32 4, i32 0}
19+
// CHECK-DAG: ![[SingleSpace]] = !{ptr @"?Buffer3@@3V?$RasterizerOrderedBuffer@M@hlsl@@A", i32 10, i32 9, i1 true, i32 3, i32 1}
20+
// CHECK-DAG: ![[ArraySpace]] = !{ptr @"?BufferArray3@@3PAV?$RasterizerOrderedBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", i32 10, i32 9, i1 true, i32 4, i32 1}

clang/test/CodeGenHLSL/cbuf.hlsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ float foo() {
2424

2525
// CHECK: !hlsl.cbufs = !{![[CBMD:[0-9]+]]}
2626
// CHECK: !hlsl.srvs = !{![[TBMD:[0-9]+]]}
27-
// CHECK: ![[CBMD]] = !{ptr @[[CB]], !"A.cb.ty", i32 13, i1 false, i32 0, i32 2}
28-
// CHECK: ![[TBMD]] = !{ptr @[[TB]], !"A.tb.ty", i32 15, i1 false, i32 2, i32 1}
27+
// CHECK: ![[CBMD]] = !{ptr @[[CB]], i32 13, i32 0, i1 false, i32 0, i32 2}
28+
// CHECK: ![[TBMD]] = !{ptr @[[TB]], i32 15, i32 0, i1 false, i32 2, i32 1}

llvm/include/llvm/Frontend/HLSL/HLSLResource.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ enum class ResourceKind : uint32_t {
5454
NumEntries,
5555
};
5656

57+
// The value ordering of this enumeration is part of the DXIL ABI. Elements
58+
// can only be added to the end, and not removed.
59+
enum class ElementType : uint32_t {
60+
Invalid = 0,
61+
I1,
62+
I16,
63+
U16,
64+
I32,
65+
U32,
66+
I64,
67+
U64,
68+
F16,
69+
F32,
70+
F64,
71+
SNormF16,
72+
UNormF16,
73+
SNormF32,
74+
UNormF32,
75+
SNormF64,
76+
UNormF64,
77+
PackedS8x32,
78+
PackedU8x32,
79+
};
80+
5781
class FrontendResource {
5882
MDNode *Entry;
5983

@@ -62,12 +86,13 @@ class FrontendResource {
6286
assert(Entry->getNumOperands() == 6 && "Unexpected metadata shape");
6387
}
6488

65-
FrontendResource(GlobalVariable *GV, StringRef TypeStr, ResourceKind RK,
89+
FrontendResource(GlobalVariable *GV, ResourceKind RK, ElementType ElTy,
6690
bool IsROV, uint32_t ResIndex, uint32_t Space);
6791

6892
GlobalVariable *getGlobalVariable();
6993
StringRef getSourceType();
7094
ResourceKind getResourceKind();
95+
ElementType getElementType();
7196
bool getIsROV();
7297
uint32_t getResourceIndex();
7398
uint32_t getSpace();

llvm/lib/Frontend/HLSL/HLSLResource.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@ GlobalVariable *FrontendResource::getGlobalVariable() {
2323
cast<ConstantAsMetadata>(Entry->getOperand(0))->getValue());
2424
}
2525

26-
StringRef FrontendResource::getSourceType() {
27-
return cast<MDString>(Entry->getOperand(1))->getString();
28-
}
29-
3026
ResourceKind FrontendResource::getResourceKind() {
3127
return static_cast<ResourceKind>(
28+
cast<ConstantInt>(
29+
cast<ConstantAsMetadata>(Entry->getOperand(1))->getValue())
30+
->getLimitedValue());
31+
}
32+
ElementType FrontendResource::getElementType() {
33+
return static_cast<ElementType>(
3234
cast<ConstantInt>(
3335
cast<ConstantAsMetadata>(Entry->getOperand(2))->getValue())
3436
->getLimitedValue());
@@ -49,14 +51,15 @@ uint32_t FrontendResource::getSpace() {
4951
->getLimitedValue();
5052
}
5153

52-
FrontendResource::FrontendResource(GlobalVariable *GV, StringRef TypeStr,
53-
ResourceKind RK, bool IsROV,
54+
FrontendResource::FrontendResource(GlobalVariable *GV, ResourceKind RK,
55+
ElementType ElTy, bool IsROV,
5456
uint32_t ResIndex, uint32_t Space) {
5557
auto &Ctx = GV->getContext();
5658
IRBuilder<> B(Ctx);
5759
Entry = MDNode::get(
58-
Ctx, {ValueAsMetadata::get(GV), MDString::get(Ctx, TypeStr),
60+
Ctx, {ValueAsMetadata::get(GV),
5961
ConstantAsMetadata::get(B.getInt32(static_cast<int>(RK))),
62+
ConstantAsMetadata::get(B.getInt32(static_cast<int>(ElTy))),
6063
ConstantAsMetadata::get(B.getInt1(IsROV)),
6164
ConstantAsMetadata::get(B.getInt32(ResIndex)),
6265
ConstantAsMetadata::get(B.getInt32(Space))});

0 commit comments

Comments
 (0)