@@ -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+
8511001void 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.
0 commit comments