Skip to content

Commit 7c9e0d5

Browse files
s-perronKeenuts
andauthored
[SPIRV] Lower spirv.Layout type (#140059)
Add this type in accordance with the [design doc](llvm/wg-hlsl#171). Fixes #138276 --------- Co-authored-by: Nathan Gauër <github@keenuts.net>
1 parent a9b64bb commit 7c9e0d5

File tree

8 files changed

+121
-21
lines changed

8 files changed

+121
-21
lines changed

llvm/lib/Target/SPIRV/SPIRVBuiltins.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3194,6 +3194,12 @@ static SPIRVType *getVulkanBufferType(const TargetExtType *ExtensionType,
31943194
return GR->getOrCreateVulkanBufferType(MIRBuilder, T, SC, IsWritable);
31953195
}
31963196

3197+
static SPIRVType *getLayoutType(const TargetExtType *ExtensionType,
3198+
MachineIRBuilder &MIRBuilder,
3199+
SPIRVGlobalRegistry *GR) {
3200+
return GR->getOrCreateLayoutType(MIRBuilder, ExtensionType);
3201+
}
3202+
31973203
namespace SPIRV {
31983204
TargetExtType *parseBuiltinTypeNameToTargetExtType(std::string TypeName,
31993205
LLVMContext &Context) {
@@ -3271,6 +3277,8 @@ SPIRVType *lowerBuiltinType(const Type *OpaqueType,
32713277
TargetType = getInlineSpirvType(BuiltinType, MIRBuilder, GR);
32723278
} else if (Name == "spirv.VulkanBuffer") {
32733279
TargetType = getVulkanBufferType(BuiltinType, MIRBuilder, GR);
3280+
} else if (Name == "spirv.Layout") {
3281+
TargetType = getLayoutType(BuiltinType, MIRBuilder, GR);
32743282
} else {
32753283
// Lookup the demangled builtin type in the TableGen records.
32763284
const SPIRV::BuiltinType *TypeRecord = SPIRV::lookupBuiltinType(Name);

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -672,10 +672,16 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
672672
} else if (HandleType->getTargetExtName() == "spirv.VulkanBuffer") {
673673
// This call is supposed to index into an array
674674
Ty = HandleType->getTypeParameter(0);
675-
assert(Ty->isArrayTy() &&
676-
"spv_resource_getpointer indexes into an array, so the type of "
677-
"the buffer should be an array.");
678-
Ty = Ty->getArrayElementType();
675+
if (Ty->isArrayTy())
676+
Ty = Ty->getArrayElementType();
677+
else {
678+
TargetExtType *BufferTy = cast<TargetExtType>(Ty);
679+
assert(BufferTy->getTargetExtName() == "spirv.Layout");
680+
Ty = BufferTy->getTypeParameter(0);
681+
assert(Ty && Ty->isStructTy());
682+
uint32_t Index = cast<ConstantInt>(II->getOperand(1))->getZExtValue();
683+
Ty = cast<StructType>(Ty)->getElementType(Index);
684+
}
679685
} else {
680686
llvm_unreachable("Unknown handle type for spv_resource_getpointer.");
681687
}

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -962,7 +962,7 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeOpaque(const StructType *Ty,
962962
SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(
963963
const StructType *Ty, MachineIRBuilder &MIRBuilder,
964964
SPIRV::AccessQualifier::AccessQualifier AccQual,
965-
bool ExplicitLayoutRequired, bool EmitIR) {
965+
StructOffsetDecorator Decorator, bool EmitIR) {
966966
const SPIRVSubtarget &ST =
967967
cast<SPIRVSubtarget>(MIRBuilder.getMF().getSubtarget());
968968
SmallVector<Register, 4> FieldTypes;
@@ -978,8 +978,9 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(
978978
}
979979

980980
for (const auto &Elem : Ty->elements()) {
981-
SPIRVType *ElemTy = findSPIRVType(toTypedPointer(Elem), MIRBuilder, AccQual,
982-
ExplicitLayoutRequired, EmitIR);
981+
SPIRVType *ElemTy = findSPIRVType(
982+
toTypedPointer(Elem), MIRBuilder, AccQual,
983+
/* ExplicitLayoutRequired= */ Decorator != nullptr, EmitIR);
983984
assert(ElemTy && ElemTy->getOpcode() != SPIRV::OpTypeVoid &&
984985
"Invalid struct element type");
985986
FieldTypes.push_back(getSPIRVTypeID(ElemTy));
@@ -1006,9 +1007,8 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeStruct(
10061007
return MIBStruct;
10071008
});
10081009

1009-
if (ExplicitLayoutRequired)
1010-
addStructOffsetDecorations(SPVType->defs().begin()->getReg(),
1011-
const_cast<StructType *>(Ty), MIRBuilder);
1010+
if (Decorator)
1011+
Decorator(SPVType->defs().begin()->getReg());
10121012

10131013
return SPVType;
10141014
}
@@ -1147,8 +1147,15 @@ SPIRVType *SPIRVGlobalRegistry::createSPIRVType(
11471147
if (auto SType = dyn_cast<StructType>(Ty)) {
11481148
if (SType->isOpaque())
11491149
return getOpTypeOpaque(SType, MIRBuilder);
1150-
return getOpTypeStruct(SType, MIRBuilder, AccQual, ExplicitLayoutRequired,
1151-
EmitIR);
1150+
1151+
StructOffsetDecorator Decorator = nullptr;
1152+
if (ExplicitLayoutRequired) {
1153+
Decorator = [&MIRBuilder, SType, this](Register Reg) {
1154+
addStructOffsetDecorations(Reg, const_cast<StructType *>(SType),
1155+
MIRBuilder);
1156+
};
1157+
}
1158+
return getOpTypeStruct(SType, MIRBuilder, AccQual, Decorator, EmitIR);
11521159
}
11531160
if (auto FType = dyn_cast<FunctionType>(Ty)) {
11541161
SPIRVType *RetTy = findSPIRVType(FType->getReturnType(), MIRBuilder,
@@ -1465,6 +1472,32 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateVulkanBufferType(
14651472
return R;
14661473
}
14671474

1475+
SPIRVType *SPIRVGlobalRegistry::getOrCreateLayoutType(
1476+
MachineIRBuilder &MIRBuilder, const TargetExtType *T, bool EmitIr) {
1477+
auto Key = SPIRV::handle(T);
1478+
if (const MachineInstr *MI = findMI(Key, &MIRBuilder.getMF()))
1479+
return MI;
1480+
1481+
StructType *ST = cast<StructType>(T->getTypeParameter(0));
1482+
ArrayRef<uint32_t> Offsets = T->int_params().slice(1);
1483+
assert(ST->getNumElements() == Offsets.size());
1484+
1485+
StructOffsetDecorator Decorator = [&MIRBuilder, &Offsets](Register Reg) {
1486+
for (uint32_t I = 0; I < Offsets.size(); ++I) {
1487+
buildOpMemberDecorate(Reg, MIRBuilder, SPIRV::Decoration::Offset, I,
1488+
{Offsets[I]});
1489+
}
1490+
};
1491+
1492+
// We need a new OpTypeStruct instruction because decorations will be
1493+
// different from a struct with an explicit layout created from a different
1494+
// entry point.
1495+
SPIRVType *SPIRVStructType = getOpTypeStruct(
1496+
ST, MIRBuilder, SPIRV::AccessQualifier::None, Decorator, EmitIr);
1497+
add(Key, SPIRVStructType);
1498+
return SPIRVStructType;
1499+
}
1500+
14681501
SPIRVType *SPIRVGlobalRegistry::getOrCreateOpTypeImage(
14691502
MachineIRBuilder &MIRBuilder, SPIRVType *SampledType, SPIRV::Dim::Dim Dim,
14701503
uint32_t Depth, uint32_t Arrayed, uint32_t Multisampled, uint32_t Sampled,

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
namespace llvm {
2727
class SPIRVSubtarget;
2828
using SPIRVType = const MachineInstr;
29+
using StructOffsetDecorator = std::function<void(Register)>;
2930

3031
class SPIRVGlobalRegistry : public SPIRVIRMapping {
3132
// Registers holding values which have types associated with them.
@@ -451,7 +452,7 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
451452

452453
SPIRVType *getOpTypeStruct(const StructType *Ty, MachineIRBuilder &MIRBuilder,
453454
SPIRV::AccessQualifier::AccessQualifier AccQual,
454-
bool ExplicitLayoutRequired, bool EmitIR);
455+
StructOffsetDecorator Decorator, bool EmitIR);
455456

456457
SPIRVType *getOpTypePointer(SPIRV::StorageClass::StorageClass SC,
457458
SPIRVType *ElemType, MachineIRBuilder &MIRBuilder,
@@ -601,6 +602,9 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
601602
SPIRV::StorageClass::StorageClass SC,
602603
bool IsWritable, bool EmitIr = false);
603604

605+
SPIRVType *getOrCreateLayoutType(MachineIRBuilder &MIRBuilder,
606+
const TargetExtType *T, bool EmitIr = false);
607+
604608
SPIRVType *
605609
getOrCreateOpTypeImage(MachineIRBuilder &MIRBuilder, SPIRVType *SampledType,
606610
SPIRV::Dim::Dim Dim, uint32_t Depth, uint32_t Arrayed,

llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,15 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
8686
const LLT p8 = LLT::pointer(8, PSize); // Output
8787
const LLT p10 = LLT::pointer(10, PSize); // Private
8888
const LLT p11 = LLT::pointer(11, PSize); // StorageBuffer
89+
const LLT p12 = LLT::pointer(12, PSize); // Uniform
8990

9091
// TODO: remove copy-pasting here by using concatenation in some way.
9192
auto allPtrsScalarsAndVectors = {
92-
p0, p1, p2, p3, p4, p5, p6, p7, p8,
93-
p10, p11, s1, s8, s16, s32, s64, v2s1, v2s8,
94-
v2s16, v2s32, v2s64, v3s1, v3s8, v3s16, v3s32, v3s64, v4s1,
95-
v4s8, v4s16, v4s32, v4s64, v8s1, v8s8, v8s16, v8s32, v8s64,
96-
v16s1, v16s8, v16s16, v16s32, v16s64};
93+
p0, p1, p2, p3, p4, p5, p6, p7, p8,
94+
p10, p11, p12, s1, s8, s16, s32, s64, v2s1,
95+
v2s8, v2s16, v2s32, v2s64, v3s1, v3s8, v3s16, v3s32, v3s64,
96+
v4s1, v4s8, v4s16, v4s32, v4s64, v8s1, v8s8, v8s16, v8s32,
97+
v8s64, v16s1, v16s8, v16s16, v16s32, v16s64};
9798

9899
auto allVectors = {v2s1, v2s8, v2s16, v2s32, v2s64, v3s1, v3s8,
99100
v3s16, v3s32, v3s64, v4s1, v4s8, v4s16, v4s32,
@@ -120,10 +121,10 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
120121
s16, s32, s64, v2s16, v2s32, v2s64, v3s16, v3s32, v3s64,
121122
v4s16, v4s32, v4s64, v8s16, v8s32, v8s64, v16s16, v16s32, v16s64};
122123

123-
auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1, p2, p3,
124-
p4, p5, p6, p7, p8, p10, p11};
124+
auto allFloatAndIntScalarsAndPtrs = {s8, s16, s32, s64, p0, p1, p2, p3,
125+
p4, p5, p6, p7, p8, p10, p11, p12};
125126

126-
auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p10, p11};
127+
auto allPtrs = {p0, p1, p2, p3, p4, p5, p6, p7, p8, p10, p11, p12};
127128

128129
bool IsExtendedInts =
129130
ST.canUseExtension(

llvm/lib/Target/SPIRV/SPIRVUtils.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,8 @@ addressSpaceToStorageClass(unsigned AddrSpace, const SPIRVSubtarget &STI) {
262262
return SPIRV::StorageClass::Private;
263263
case 11:
264264
return SPIRV::StorageClass::StorageBuffer;
265+
case 12:
266+
return SPIRV::StorageClass::Uniform;
265267
default:
266268
report_fatal_error("Unknown address space");
267269
}

llvm/lib/Target/SPIRV/SPIRVUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ storageClassToAddressSpace(SPIRV::StorageClass::StorageClass SC) {
210210
return 10;
211211
case SPIRV::StorageClass::StorageBuffer:
212212
return 11;
213+
case SPIRV::StorageClass::Uniform:
214+
return 12;
213215
default:
214216
report_fatal_error("Unable to get address space id");
215217
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.6-unknown-vulkan1.3-library %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-unknown-vulkan1.3-library %s -o - -filetype=obj | spirv-val %}
3+
4+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G10"
5+
6+
; CHECK-DAG: OpName [[standard_layout:%[0-9]+]] "standard_layout"
7+
; CHECK-DAG: OpMemberDecorate [[standard_layout]] 0 Offset 0
8+
; CHECK-DAG: OpMemberDecorate [[standard_layout]] 1 Offset 4
9+
10+
; CHECK-DAG: OpName [[standard_layout_with_different_offset:%[0-9]+]] "standard_layout"
11+
; CHECK-DAG: OpMemberDecorate [[standard_layout_with_different_offset]] 0 Offset 0
12+
; CHECK-DAG: OpMemberDecorate [[standard_layout_with_different_offset]] 1 Offset 8
13+
%standard_layout = type { i32, i32 }
14+
15+
; CHECK-DAG: OpName [[backwards_layout:%[0-9]+]] "backwards_layout"
16+
; CHECK-DAG: OpMemberDecorate [[backwards_layout]] 0 Offset 4
17+
; CHECK-DAG: OpMemberDecorate [[backwards_layout]] 1 Offset 0
18+
%backwards_layout = type { i32, i32 }
19+
20+
; CHECK-DAG: OpName [[large_gap:%[0-9]+]] "large_gap"
21+
; CHECK-DAG: OpMemberDecorate [[large_gap]] 0 Offset 0
22+
; CHECK-DAG: OpMemberDecorate [[large_gap]] 1 Offset 64
23+
; CHECK-DAG: OpMemberDecorate [[large_gap]] 2 Offset 1020
24+
; CHECK-DAG: OpMemberDecorate [[large_gap]] 3 Offset 4
25+
%large_gap = type { i32, i32, i32, i32 }
26+
27+
; CHECK-DAG: OpName [[mixed_layout:%[0-9]+]] "mixed_layout"
28+
; CHECK-DAG: OpMemberDecorate [[mixed_layout]] 0 Offset 0
29+
; CHECK-DAG: OpMemberDecorate [[mixed_layout]] 1 Offset 8
30+
; CHECK-DAG: OpMemberDecorate [[mixed_layout]] 2 Offset 4
31+
; CHECK-DAG: OpMemberDecorate [[mixed_layout]] 3 Offset 12
32+
%mixed_layout = type { i32, i32, i32, i32 }
33+
34+
define void @main() local_unnamed_addr #1 {
35+
entry:
36+
%standard_handle = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %standard_layout, 8, 0, 4), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
37+
%standard_handle_with_different_offset = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %standard_layout, 12, 0, 8), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
38+
%backwards_handle = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %backwards_layout, 8, 4, 0), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
39+
%large_gap_handle = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %large_gap, 1024, 0, 64, 1020, 4), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
40+
%mixed_handle = tail call target("spirv.VulkanBuffer", target("spirv.Layout", %mixed_layout, 16, 0, 8, 4, 12), 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.VulkanBuffer_tspirv.Layout_s___cblayout_Bs_8_0_4t_2_0t(i32 0, i32 1, i32 1, i32 0, i1 false)
41+
ret void
42+
}
43+
44+
attributes #1 = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(readwrite, argmem: write, inaccessiblemem: none) "approx-func-fp-math"="false" "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }

0 commit comments

Comments
 (0)