@@ -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,136 @@ 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+
935+ void addOpAccessChainReqs (const MachineInstr &Instr,
936+ SPIRV::RequirementHandler &Handler,
937+ const SPIRVSubtarget &Subtarget) {
938+ const MachineRegisterInfo &MRI = Instr.getMF ()->getRegInfo ();
939+ // Get the result type. If it is an image type, then the shader uses
940+ // descriptor indexing. The appropriate capabilities will be added based
941+ // on the specifics of the image.
942+ Register ResTypeReg = Instr.getOperand (1 ).getReg ();
943+ MachineInstr *ResTypeInst = MRI.getUniqueVRegDef (ResTypeReg);
944+
945+ assert (ResTypeInst->getOpcode () == SPIRV::OpTypePointer);
946+ uint32_t StorageClass = ResTypeInst->getOperand (1 ).getImm ();
947+ if (StorageClass != SPIRV::StorageClass::StorageClass::UniformConstant &&
948+ StorageClass != SPIRV::StorageClass::StorageClass::Uniform &&
949+ StorageClass != SPIRV::StorageClass::StorageClass::StorageBuffer) {
950+ return ;
951+ }
952+
953+ Register PointeeTypeReg = ResTypeInst->getOperand (2 ).getReg ();
954+ MachineInstr *PointeeType = MRI.getUniqueVRegDef (PointeeTypeReg);
955+ if (PointeeType->getOpcode () != SPIRV::OpTypeImage &&
956+ PointeeType->getOpcode () != SPIRV::OpTypeSampledImage &&
957+ PointeeType->getOpcode () != SPIRV::OpTypeSampler) {
958+ return ;
959+ }
960+
961+ bool IsNonUniform =
962+ hasNonUniformDecoration (Instr.getOperand (0 ).getReg (), MRI);
963+ if (isUniformTexelBuffer (PointeeType)) {
964+ if (IsNonUniform)
965+ Handler.addRequirements (
966+ SPIRV::Capability::UniformTexelBufferArrayNonUniformIndexingEXT);
967+ else
968+ Handler.addRequirements (
969+ SPIRV::Capability::UniformTexelBufferArrayDynamicIndexingEXT);
970+ } else if (isInputAttachment (PointeeType)) {
971+ if (IsNonUniform)
972+ Handler.addRequirements (
973+ SPIRV::Capability::InputAttachmentArrayNonUniformIndexingEXT);
974+ else
975+ Handler.addRequirements (
976+ SPIRV::Capability::InputAttachmentArrayDynamicIndexingEXT);
977+ } else if (isStorageTexelBuffer (PointeeType)) {
978+ if (IsNonUniform)
979+ Handler.addRequirements (
980+ SPIRV::Capability::StorageTexelBufferArrayNonUniformIndexingEXT);
981+ else
982+ Handler.addRequirements (
983+ SPIRV::Capability::StorageTexelBufferArrayDynamicIndexingEXT);
984+ } else if (isSampledImage (PointeeType) ||
985+ isCombinedImageSampler (PointeeType) ||
986+ PointeeType->getOpcode () == SPIRV::OpTypeSampler) {
987+ if (IsNonUniform)
988+ Handler.addRequirements (
989+ SPIRV::Capability::SampledImageArrayNonUniformIndexingEXT);
990+ else
991+ Handler.addRequirements (
992+ SPIRV::Capability::SampledImageArrayDynamicIndexing);
993+ } else if (isStorageImage (PointeeType)) {
994+ if (IsNonUniform)
995+ Handler.addRequirements (
996+ SPIRV::Capability::StorageImageArrayNonUniformIndexingEXT);
997+ else
998+ Handler.addRequirements (
999+ SPIRV::Capability::StorageImageArrayDynamicIndexing);
1000+ }
1001+ }
1002+
8511003void addInstrRequirements (const MachineInstr &MI,
8521004 SPIRV::RequirementHandler &Reqs,
8531005 const SPIRVSubtarget &ST) {
@@ -967,11 +1119,17 @@ void addInstrRequirements(const MachineInstr &MI,
9671119 case SPIRV::OpConstantSampler:
9681120 Reqs.addCapability (SPIRV::Capability::LiteralSampler);
9691121 break ;
1122+ case SPIRV::OpInBoundsAccessChain:
1123+ case SPIRV::OpAccessChain:
1124+ addOpAccessChainReqs (MI, Reqs, ST);
1125+ break ;
9701126 case SPIRV::OpTypeImage:
9711127 addOpTypeImageReqs (MI, Reqs, ST);
9721128 break ;
9731129 case SPIRV::OpTypeSampler:
974- Reqs.addCapability (SPIRV::Capability::ImageBasic);
1130+ if (!ST.isVulkanEnv ()) {
1131+ Reqs.addCapability (SPIRV::Capability::ImageBasic);
1132+ }
9751133 break ;
9761134 case SPIRV::OpTypeForwardPointer:
9771135 // TODO: check if it's OpenCL's kernel.
0 commit comments