Vulkan specific validation rules for OpTypeRuntimeArray
| 791 | |
| 792 | // Vulkan specific validation rules for OpTypeRuntimeArray |
| 793 | spv_result_t ValidateVariableVulkanArray(ValidationState_t& _, |
| 794 | const Instruction* inst, |
| 795 | spv::StorageClass storage_class, |
| 796 | const Instruction& value_type, |
| 797 | uint32_t value_id) { |
| 798 | // OpTypeRuntimeArray should only ever be in a container like OpTypeStruct, |
| 799 | // so should never appear as a bare variable. |
| 800 | // Unless the module has the RuntimeDescriptorArray capability. |
| 801 | if (value_type.opcode() == spv::Op::OpTypeRuntimeArray) { |
| 802 | if (!_.HasCapability(spv::Capability::RuntimeDescriptorArray)) { |
| 803 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 804 | << _.VkErrorID(4680) << "OpVariable, <id> " |
| 805 | << _.getIdName(inst->id()) |
| 806 | << ", is attempting to create memory for an illegal type, " |
| 807 | << "OpTypeRuntimeArray.\nFor Vulkan OpTypeRuntimeArray can only " |
| 808 | << "appear as the final member of an OpTypeStruct, thus cannot " |
| 809 | << "be instantiated via OpVariable, unless the " |
| 810 | "RuntimeDescriptorArray Capability is declared"; |
| 811 | } else { |
| 812 | // A bare variable OpTypeRuntimeArray is allowed in this context, but |
| 813 | // still need to check the storage class. |
| 814 | if (storage_class != spv::StorageClass::StorageBuffer && |
| 815 | storage_class != spv::StorageClass::Uniform && |
| 816 | storage_class != spv::StorageClass::UniformConstant) { |
| 817 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 818 | << _.VkErrorID(4680) |
| 819 | << "For Vulkan with RuntimeDescriptorArray, a variable " |
| 820 | << "containing OpTypeRuntimeArray must have storage class of " |
| 821 | << "StorageBuffer, Uniform, or UniformConstant."; |
| 822 | } |
| 823 | } |
| 824 | } |
| 825 | |
| 826 | // If an OpStruct has an OpTypeRuntimeArray somewhere within it, then it |
| 827 | // must either have the storage class StorageBuffer and be decorated |
| 828 | // with Block, or it must be in the Uniform storage class |
| 829 | if (value_type.opcode() == spv::Op::OpTypeStruct) { |
| 830 | if (DoesStructContainRTA(_, &value_type)) { |
| 831 | if (storage_class == spv::StorageClass::StorageBuffer || |
| 832 | storage_class == spv::StorageClass::PhysicalStorageBuffer) { |
| 833 | if (!_.HasDecoration(value_id, spv::Decoration::Block)) { |
| 834 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 835 | << _.VkErrorID(4680) |
| 836 | << "For Vulkan, an OpTypeStruct variable containing an " |
| 837 | << "OpTypeRuntimeArray must be decorated with Block if it " |
| 838 | << "has storage class StorageBuffer or " |
| 839 | "PhysicalStorageBuffer."; |
| 840 | } |
| 841 | } else if (storage_class == spv::StorageClass::Uniform) { |
| 842 | // BufferBlock Uniform were always allowed. |
| 843 | // |
| 844 | // Block Uniform use to be invalid, but Vulkan added |
| 845 | // VK_EXT_shader_uniform_buffer_unsized_array and now this is |
| 846 | // validated at runtime |
| 847 | // |
| 848 | // The uniform must have either the Block or BufferBlock decoration |
| 849 | // (see VUID-StandaloneSpirv-Uniform-06676) |
| 850 | } else { |
no test coverage detected