Skip to content

Commit 9d80a7f

Browse files
committed
[SPIRV][HLSL] Handle arrays of resources
This commit adds the ability to get a particular resource from an array of resources using the handle_fromBinding intrinsic. The main changes are: 1. Create an array when generating the type. 2. Add capabilities from [SPV_EXT_descriptor_indexing](https://htmlpreview.github.io/?https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extensions/EXT/SPV_EXT_descriptor_indexing.html). We are still missing the ability to declare a runtime array. That will be done in a follow up PR.
1 parent 5af7ae5 commit 9d80a7f

18 files changed

+813
-10
lines changed

llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,16 @@ Register SPIRVGlobalRegistry::buildGlobalVariable(
716716
static std::string buildSpirvTypeName(const SPIRVType *Type,
717717
MachineIRBuilder &MIRBuilder) {
718718
switch (Type->getOpcode()) {
719+
case SPIRV::OpTypeSampledImage: {
720+
Register SampledTypeReg = Type->getOperand(1).getReg();
721+
auto *SampledType = MIRBuilder.getMRI()->getUniqueVRegDef(SampledTypeReg);
722+
std::string TypeName =
723+
"sampled_image_" + buildSpirvTypeName(SampledType, MIRBuilder);
724+
for (uint32_t I = 2; I < Type->getNumOperands(); ++I) {
725+
TypeName = (TypeName + '_' + Twine(Type->getOperand(I).getImm())).str();
726+
}
727+
return TypeName;
728+
}
719729
case SPIRV::OpTypeImage: {
720730
Register SampledTypeReg = Type->getOperand(1).getReg();
721731
auto *SampledType = MIRBuilder.getMRI()->getUniqueVRegDef(SampledTypeReg);
@@ -726,8 +736,18 @@ static std::string buildSpirvTypeName(const SPIRVType *Type,
726736
}
727737
return TypeName;
728738
}
739+
case SPIRV::OpTypeArray: {
740+
Register ElementTypeReg = Type->getOperand(1).getReg();
741+
auto *ElementType = MIRBuilder.getMRI()->getUniqueVRegDef(ElementTypeReg);
742+
uint32_t ArraySize = 32; // Type->getOperand(2).getCImm()->getZExtValue();
743+
return (buildSpirvTypeName(ElementType, MIRBuilder) + Twine("[") +
744+
Twine(ArraySize) + Twine("]"))
745+
.str();
746+
}
729747
case SPIRV::OpTypeFloat:
730748
return ("f" + Twine(Type->getOperand(1).getImm())).str();
749+
case SPIRV::OpTypeSampler:
750+
return ("sampler");
731751
case SPIRV::OpTypeInt:
732752
if (Type->getOperand(2).getImm())
733753
return ("i" + Twine(Type->getOperand(1).getImm())).str();

llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ class SPIRVInstructionSelector : public InstructionSelector {
257257
SPIRVType *SrcPtrTy) const;
258258
Register buildPointerToResource(const SPIRVType *ResType, uint32_t Set,
259259
uint32_t Binding, uint32_t ArraySize,
260+
Register IndexReg, bool IsNonUniform,
260261
MachineIRBuilder MIRBuilder) const;
261262
};
262263

@@ -2577,10 +2578,15 @@ void SPIRVInstructionSelector::selectHandleFromBinding(Register &ResVReg,
25772578
uint32_t Set = foldImm(I.getOperand(2), MRI);
25782579
uint32_t Binding = foldImm(I.getOperand(3), MRI);
25792580
uint32_t ArraySize = foldImm(I.getOperand(4), MRI);
2581+
Register IndexReg = I.getOperand(5).getReg();
2582+
bool IsNonUniform = ArraySize > 1 && foldImm(I.getOperand(6), MRI);
25802583

25812584
MachineIRBuilder MIRBuilder(I);
2582-
Register VarReg =
2583-
buildPointerToResource(ResType, Set, Binding, ArraySize, MIRBuilder);
2585+
Register VarReg = buildPointerToResource(ResType, Set, Binding, ArraySize,
2586+
IndexReg, IsNonUniform, MIRBuilder);
2587+
2588+
if (IsNonUniform)
2589+
buildOpDecorate(ResVReg, I, TII, SPIRV::Decoration::NonUniformEXT, {});
25842590

25852591
// TODO: For now we assume the resource is an image, which needs to be
25862592
// loaded to get the handle. That will not be true for storage buffers.
@@ -2592,10 +2598,35 @@ void SPIRVInstructionSelector::selectHandleFromBinding(Register &ResVReg,
25922598

25932599
Register SPIRVInstructionSelector::buildPointerToResource(
25942600
const SPIRVType *ResType, uint32_t Set, uint32_t Binding,
2595-
uint32_t ArraySize, MachineIRBuilder MIRBuilder) const {
2596-
assert(ArraySize == 1 && "Resource arrays are not implemented yet.");
2597-
return GR.getOrCreateGlobalVariableWithBinding(ResType, Set, Binding,
2598-
MIRBuilder);
2601+
uint32_t ArraySize, Register IndexReg, bool IsNonUniform,
2602+
MachineIRBuilder MIRBuilder) const {
2603+
if (ArraySize == 1)
2604+
return GR.getOrCreateGlobalVariableWithBinding(ResType, Set, Binding,
2605+
MIRBuilder);
2606+
2607+
const SPIRVType *VarType = GR.getOrCreateSPIRVArrayType(
2608+
ResType, ArraySize, *MIRBuilder.getInsertPt(), TII);
2609+
Register VarReg = GR.getOrCreateGlobalVariableWithBinding(
2610+
VarType, Set, Binding, MIRBuilder);
2611+
2612+
SPIRVType *ResPointerType = GR.getOrCreateSPIRVPointerType(
2613+
ResType, MIRBuilder, SPIRV::StorageClass::UniformConstant);
2614+
2615+
Register AcReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
2616+
if (IsNonUniform) {
2617+
// It is unclear which value needs to be marked an non-uniform, so both
2618+
// the index and the access changed are decorated as non-uniform.
2619+
buildOpDecorate(IndexReg, MIRBuilder, SPIRV::Decoration::NonUniformEXT, {});
2620+
buildOpDecorate(AcReg, MIRBuilder, SPIRV::Decoration::NonUniformEXT, {});
2621+
}
2622+
2623+
MIRBuilder.buildInstr(SPIRV::OpAccessChain)
2624+
.addDef(AcReg)
2625+
.addUse(GR.getSPIRVTypeID(ResPointerType))
2626+
.addUse(VarReg)
2627+
.addUse(IndexReg);
2628+
2629+
return AcReg;
25992630
}
26002631

26012632
bool SPIRVInstructionSelector::selectAllocaArray(Register ResVReg,

llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp

Lines changed: 158 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -689,11 +689,31 @@ void RequirementHandler::initAvailableCapabilitiesForVulkan(
689689
const SPIRVSubtarget &ST) {
690690
addAvailableCaps({Capability::Shader, Capability::Linkage});
691691

692-
// Provided by all supported Vulkan versions.
692+
// Core in Vulkan 1.1 and earlier.
693693
addAvailableCaps({Capability::Int16, Capability::Int64, Capability::Float16,
694694
Capability::Float64, Capability::GroupNonUniform,
695695
Capability::Image1D, Capability::SampledBuffer,
696-
Capability::ImageBuffer});
696+
Capability::ImageBuffer,
697+
Capability::UniformBufferArrayDynamicIndexing,
698+
Capability::SampledImageArrayDynamicIndexing,
699+
Capability::StorageBufferArrayDynamicIndexing,
700+
Capability::StorageImageArrayDynamicIndexing});
701+
702+
// Became core in Vulkan 1.2
703+
if (ST.isAtLeastSPIRVVer(VersionTuple(1, 5))) {
704+
addAvailableCaps(
705+
{Capability::ShaderNonUniformEXT, Capability::RuntimeDescriptorArrayEXT,
706+
Capability::InputAttachmentArrayDynamicIndexingEXT,
707+
Capability::UniformTexelBufferArrayDynamicIndexingEXT,
708+
Capability::StorageTexelBufferArrayDynamicIndexingEXT,
709+
Capability::UniformBufferArrayNonUniformIndexingEXT,
710+
Capability::SampledImageArrayNonUniformIndexingEXT,
711+
Capability::StorageBufferArrayNonUniformIndexingEXT,
712+
Capability::StorageImageArrayNonUniformIndexingEXT,
713+
Capability::InputAttachmentArrayNonUniformIndexingEXT,
714+
Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
715+
Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
716+
}
697717
}
698718

699719
} // namespace SPIRV
@@ -729,6 +749,8 @@ static void addOpDecorateReqs(const MachineInstr &MI, unsigned DecIndex,
729749
Dec == SPIRV::Decoration::ImplementInRegisterMapINTEL) {
730750
Reqs.addExtension(
731751
SPIRV::Extension::SPV_INTEL_global_variable_fpga_decorations);
752+
} else if (Dec == SPIRV::Decoration::NonUniformEXT) {
753+
Reqs.addRequirements(SPIRV::Capability::ShaderNonUniformEXT);
732754
}
733755
}
734756

@@ -848,6 +870,134 @@ static void AddAtomicFloatRequirements(const MachineInstr &MI,
848870
}
849871
}
850872

873+
bool isUniformTexelBuffer(MachineInstr *ImageInst) {
874+
if (ImageInst->getOpcode() != SPIRV::OpTypeImage)
875+
return false;
876+
uint32_t Dim = ImageInst->getOperand(2).getImm();
877+
uint32_t Sampled = ImageInst->getOperand(6).getImm();
878+
return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 1;
879+
}
880+
881+
bool isStorageTexelBuffer(MachineInstr *ImageInst) {
882+
if (ImageInst->getOpcode() != SPIRV::OpTypeImage)
883+
return false;
884+
uint32_t Dim = ImageInst->getOperand(2).getImm();
885+
uint32_t Sampled = ImageInst->getOperand(6).getImm();
886+
return Dim == SPIRV::Dim::DIM_Buffer && Sampled == 2;
887+
}
888+
889+
bool isSampledImage(MachineInstr *ImageInst) {
890+
if (ImageInst->getOpcode() != SPIRV::OpTypeImage)
891+
return false;
892+
uint32_t Dim = ImageInst->getOperand(2).getImm();
893+
uint32_t Sampled = ImageInst->getOperand(6).getImm();
894+
return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 1;
895+
}
896+
897+
bool isInputAttachment(MachineInstr *ImageInst) {
898+
if (ImageInst->getOpcode() != SPIRV::OpTypeImage)
899+
return false;
900+
uint32_t Dim = ImageInst->getOperand(2).getImm();
901+
uint32_t Sampled = ImageInst->getOperand(6).getImm();
902+
return Dim == SPIRV::Dim::DIM_SubpassData && Sampled == 2;
903+
}
904+
905+
bool isStorageImage(MachineInstr *ImageInst) {
906+
if (ImageInst->getOpcode() != SPIRV::OpTypeImage)
907+
return false;
908+
uint32_t Dim = ImageInst->getOperand(2).getImm();
909+
uint32_t Sampled = ImageInst->getOperand(6).getImm();
910+
return Dim != SPIRV::Dim::DIM_Buffer && Sampled == 2;
911+
}
912+
913+
bool isCombinedImageSampler(MachineInstr *SampledImageInst) {
914+
if (SampledImageInst->getOpcode() != SPIRV::OpTypeSampledImage)
915+
return false;
916+
917+
const MachineRegisterInfo &MRI = SampledImageInst->getMF()->getRegInfo();
918+
Register ImageReg = SampledImageInst->getOperand(1).getReg();
919+
auto *ImageInst = MRI.getUniqueVRegDef(ImageReg);
920+
return isSampledImage(ImageInst);
921+
}
922+
923+
bool hasNonUniformDecoration(Register Reg, const MachineRegisterInfo &MRI) {
924+
for (const auto &MI : MRI.reg_instructions(Reg)) {
925+
if (MI.getOpcode() != SPIRV::OpDecorate)
926+
continue;
927+
928+
uint32_t Dec = MI.getOperand(1).getImm();
929+
if (Dec == SPIRV::Decoration::NonUniformEXT)
930+
return true;
931+
}
932+
return false;
933+
}
934+
void addOpAccessChainReqs(const MachineInstr &instr,
935+
SPIRV::RequirementHandler &handler,
936+
const SPIRVSubtarget &subtarget) {
937+
const MachineRegisterInfo &MRI = instr.getMF()->getRegInfo();
938+
// Get the result type. If it is an image type, then the shader uses
939+
// descriptor indexing. The appropriate capabilities will be added based
940+
// on the specifics of the image.
941+
Register ResTypeReg = instr.getOperand(1).getReg();
942+
MachineInstr *ResTypeInst = MRI.getUniqueVRegDef(ResTypeReg);
943+
944+
assert(ResTypeInst->getOpcode() == SPIRV::OpTypePointer);
945+
uint32_t StorageClass = ResTypeInst->getOperand(1).getImm();
946+
if (StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
947+
StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
948+
StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
949+
return;
950+
}
951+
952+
Register PointeeTypeReg = ResTypeInst->getOperand(2).getReg();
953+
MachineInstr *PointeeType = MRI.getUniqueVRegDef(PointeeTypeReg);
954+
if (PointeeType->getOpcode() != SPIRV::OpTypeImage &&
955+
PointeeType->getOpcode() != SPIRV::OpTypeSampledImage &&
956+
PointeeType->getOpcode() != SPIRV::OpTypeSampler)
957+
return;
958+
959+
bool IsNonUniform =
960+
hasNonUniformDecoration(instr.getOperand(0).getReg(), MRI);
961+
if (isUniformTexelBuffer(PointeeType)) {
962+
if (IsNonUniform)
963+
handler.addRequirements(
964+
SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
965+
else
966+
handler.addRequirements(
967+
SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
968+
} else if (isInputAttachment(PointeeType)) {
969+
if (IsNonUniform)
970+
handler.addRequirements(
971+
SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
972+
else
973+
handler.addRequirements(
974+
SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
975+
} else if (isStorageTexelBuffer(PointeeType)) {
976+
if (IsNonUniform)
977+
handler.addRequirements(
978+
SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
979+
else
980+
handler.addRequirements(
981+
SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
982+
} else if (isSampledImage(PointeeType) ||
983+
isCombinedImageSampler(PointeeType) ||
984+
PointeeType->getOpcode() == SPIRV::OpTypeSampler) {
985+
if (IsNonUniform)
986+
handler.addRequirements(
987+
SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
988+
else
989+
handler.addRequirements(
990+
SPIRV::Capability::SampledImageArrayDynamicIndexing);
991+
} else if (isStorageImage(PointeeType)) {
992+
if (IsNonUniform)
993+
handler.addRequirements(
994+
SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
995+
else
996+
handler.addRequirements(
997+
SPIRV::Capability::StorageImageArrayDynamicIndexing);
998+
}
999+
}
1000+
8511001
void addInstrRequirements(const MachineInstr &MI,
8521002
SPIRV::RequirementHandler &Reqs,
8531003
const SPIRVSubtarget &ST) {
@@ -967,11 +1117,16 @@ void addInstrRequirements(const MachineInstr &MI,
9671117
case SPIRV::OpConstantSampler:
9681118
Reqs.addCapability(SPIRV::Capability::LiteralSampler);
9691119
break;
1120+
case SPIRV::OpAccessChain:
1121+
addOpAccessChainReqs(MI, Reqs, ST);
1122+
break;
9701123
case SPIRV::OpTypeImage:
9711124
addOpTypeImageReqs(MI, Reqs, ST);
9721125
break;
9731126
case SPIRV::OpTypeSampler:
974-
Reqs.addCapability(SPIRV::Capability::ImageBasic);
1127+
if (ST.isOpenCLEnv()) {
1128+
Reqs.addCapability(SPIRV::Capability::ImageBasic);
1129+
}
9751130
break;
9761131
case SPIRV::OpTypeForwardPointer:
9771132
// TODO: check if it's OpenCL's kernel.

llvm/lib/Target/SPIRV/SPIRVSymbolicOperands.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,9 @@ defm GeometryPointSize : CapabilityOperand<24, 0, 0, [], [Geometry]>;
355355
defm ImageGatherExtended : CapabilityOperand<25, 0, 0, [], [Shader]>;
356356
defm StorageImageMultisample : CapabilityOperand<27, 0, 0, [], [Shader]>;
357357
defm UniformBufferArrayDynamicIndexing : CapabilityOperand<28, 0, 0, [], [Shader]>;
358-
defm SampledImageArrayDymnamicIndexing : CapabilityOperand<29, 0, 0, [], [Shader]>;
358+
defm SampledImageArrayDynamicIndexing : CapabilityOperand<29, 0, 0, [], [Shader]>;
359+
defm StorageBufferArrayDynamicIndexing : CapabilityOperand<30, 0, 0, [], [Shader]>;
360+
defm StorageImageArrayDynamicIndexing : CapabilityOperand<31, 0, 0, [], [Shader]>;
359361
defm ClipDistance : CapabilityOperand<32, 0, 0, [], [Shader]>;
360362
defm CullDistance : CapabilityOperand<33, 0, 0, [], [Shader]>;
361363
defm SampleRateShading : CapabilityOperand<35, 0, 0, [], [Shader]>;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv1.5-vulkan-library %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.5-vulkan-library %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK: OpCapability Shader
5+
; CHECK-NEXT: OpCapability SampledImageArrayDynamicIndexing
6+
; CHECK-NEXT: OpCapability Sampled1D
7+
; CHECK-NOT: OpCapability
8+
9+
; CHECK-DAG: OpDecorate [[Var:%[0-9]+]] DescriptorSet 3
10+
; CHECK-DAG: OpDecorate [[Var]] Binding 4
11+
12+
; CHECK-DAG: [[int:%[0-9]+]] = OpTypeInt 32 0
13+
; CHECK-DAG: [[BufferType:%[0-9]+]] = OpTypeImage [[int]] 1D 2 0 0 1 R32i {{$}}
14+
; CHECK-DAG: [[CombindedType:%[0-9]+]] = OpTypeSampledImage [[BufferType]]
15+
; CHECK-DAG: [[BufferPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[CombindedType]]
16+
; CHECK-DAG: [[ArraySize:%[0-9]+]] = OpConstant [[int]] 3
17+
; CHECK-DAG: [[One:%[0-9]+]] = OpConstant [[int]] 1
18+
; CHECK-DAG: [[Zero:%[0-9]+]] = OpConstant [[int]] 0
19+
; CHECK-DAG: [[BufferArrayType:%[0-9]+]] = OpTypeArray [[CombindedType]] [[ArraySize]]
20+
; CHECK-DAG: [[ArrayPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[BufferArrayType]]
21+
; CHECK-DAG: [[Var]] = OpVariable [[ArrayPtrType]] UniformConstant
22+
23+
; CHECK: {{%[0-9]+}} = OpFunction {{%[0-9]+}} DontInline {{%[0-9]+}}
24+
; CHECK-NEXT: OpLabel
25+
define void @main() #0 {
26+
; CHECK: [[ac:%[0-9]+]] = OpAccessChain [[BufferPtrType]] [[Var]] [[Zero]]
27+
; CHECK: [[buffer:%[0-9]+]] = OpLoad [[CombindedType]] [[ac]]
28+
%buffer0 = call target("spirv.SampledImage", i32, 0, 2, 0, 0, 1, 24)
29+
@llvm.spv.handle.fromBinding.tspirv.Image_f32_0_2_0_0_1_24(
30+
i32 3, i32 4, i32 3, i32 0, i1 false)
31+
32+
; CHECK: [[ac:%[0-9]+]] = OpAccessChain [[BufferPtrType]] [[Var]] [[One]]
33+
; CHECK: [[buffer:%[0-9]+]] = OpLoad [[CombindedType]] [[ac]]
34+
%buffer1 = call target("spirv.SampledImage", i32, 0, 2, 0, 0, 1, 24)
35+
@llvm.spv.handle.fromBinding.tspirv.Image_f32_0_2_0_0_1_24(
36+
i32 3, i32 4, i32 3, i32 1, i1 false)
37+
ret void
38+
}
39+
40+
attributes #0 = { convergent noinline norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv1.5-vulkan-library %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.5-vulkan-library %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK: OpCapability Shader
5+
; CHECK: OpCapability ShaderNonUniform
6+
; CHECK-NEXT: OpCapability SampledImageArrayNonUniformIndexing
7+
; CHECK-NEXT: OpCapability Sampled1D
8+
; CHECK-NOT: OpCapability
9+
10+
; CHECK-DAG: OpDecorate [[Var:%[0-9]+]] DescriptorSet 3
11+
; CHECK-DAG: OpDecorate [[Var]] Binding 4
12+
; CHECK: OpDecorate [[Zero:%[0-9]+]] NonUniform
13+
; CHECK: OpDecorate [[ac0:%[0-9]+]] NonUniform
14+
; CHECK: OpDecorate [[ld0:%[0-9]+]] NonUniform
15+
; CHECK: OpDecorate [[One:%[0-9]+]] NonUniform
16+
; CHECK: OpDecorate [[ac1:%[0-9]+]] NonUniform
17+
; CHECK: OpDecorate [[ld1:%[0-9]+]] NonUniform
18+
19+
; CHECK-DAG: [[int:%[0-9]+]] = OpTypeInt 32 0
20+
; CHECK-DAG: [[BufferType:%[0-9]+]] = OpTypeImage [[int]] 1D 2 0 0 1 R32i {{$}}
21+
; CHECK-DAG: [[CombindedType:%[0-9]+]] = OpTypeSampledImage [[BufferType]]
22+
; CHECK-DAG: [[BufferPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[CombindedType]]
23+
; CHECK-DAG: [[ArraySize:%[0-9]+]] = OpConstant [[int]] 3
24+
; CHECK-DAG: [[One]] = OpConstant [[int]] 1
25+
; CHECK-DAG: [[Zero]] = OpConstant [[int]] 0
26+
; CHECK-DAG: [[BufferArrayType:%[0-9]+]] = OpTypeArray [[CombindedType]] [[ArraySize]]
27+
; CHECK-DAG: [[ArrayPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[BufferArrayType]]
28+
; CHECK-DAG: [[Var]] = OpVariable [[ArrayPtrType]] UniformConstant
29+
30+
; CHECK: {{%[0-9]+}} = OpFunction {{%[0-9]+}} DontInline {{%[0-9]+}}
31+
; CHECK-NEXT: OpLabel
32+
define void @main() #0 {
33+
; CHECK: [[ac0]] = OpAccessChain [[BufferPtrType]] [[Var]] [[Zero]]
34+
; CHECK: [[ld0:%[0-9]+]] = OpLoad [[CombindedType]] [[ac0]]
35+
%buffer0 = call target("spirv.SampledImage", i32, 0, 2, 0, 0, 1, 24)
36+
@llvm.spv.handle.fromBinding.tspirv.Image_f32_0_2_0_0_1_24(
37+
i32 3, i32 4, i32 3, i32 0, i1 true)
38+
39+
; CHECK: [[ac1]] = OpAccessChain [[BufferPtrType]] [[Var]] [[One]]
40+
; CHECK: [[ld1]] = OpLoad [[CombindedType]] [[ac1]]
41+
%buffer1 = call target("spirv.SampledImage", i32, 0, 2, 0, 0, 1, 24)
42+
@llvm.spv.handle.fromBinding.tspirv.Image_f32_0_2_0_0_1_24(
43+
i32 3, i32 4, i32 3, i32 1, i1 true)
44+
ret void
45+
}
46+
47+
attributes #0 = { convergent noinline norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }

0 commit comments

Comments
 (0)