| 1125 | } |
| 1126 | |
| 1127 | spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) { |
| 1128 | const bool untyped_pointer = inst->opcode() == spv::Op::OpUntypedVariableKHR; |
| 1129 | |
| 1130 | auto result_type = _.FindDef(inst->type_id()); |
| 1131 | if (untyped_pointer) { |
| 1132 | if (!result_type || |
| 1133 | result_type->opcode() != spv::Op::OpTypeUntypedPointerKHR) |
| 1134 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1135 | << "Result type must be an untyped pointer"; |
| 1136 | } else { |
| 1137 | if (!result_type || result_type->opcode() != spv::Op::OpTypePointer) { |
| 1138 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1139 | << "OpVariable Result Type <id> " << _.getIdName(inst->type_id()) |
| 1140 | << " is not a pointer type."; |
| 1141 | } |
| 1142 | } |
| 1143 | |
| 1144 | const auto storage_class_index = 2u; |
| 1145 | auto storage_class = |
| 1146 | inst->GetOperandAs<spv::StorageClass>(storage_class_index); |
| 1147 | uint32_t value_id = 0; |
| 1148 | if (untyped_pointer) { |
| 1149 | const bool has_data_type = 3u < inst->operands().size(); |
| 1150 | if (has_data_type) { |
| 1151 | value_id = inst->GetOperandAs<uint32_t>(3u); |
| 1152 | auto data_type = _.FindDef(value_id); |
| 1153 | if (!data_type || !spvOpcodeGeneratesType(data_type->opcode())) { |
| 1154 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1155 | << "Data type must be a type instruction"; |
| 1156 | } |
| 1157 | } else { |
| 1158 | if (storage_class == spv::StorageClass::Function || |
| 1159 | storage_class == spv::StorageClass::Private || |
| 1160 | storage_class == spv::StorageClass::Workgroup) { |
| 1161 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1162 | << "Data type must be specified for Function, Private, and " |
| 1163 | "Workgroup storage classes"; |
| 1164 | } |
| 1165 | // Added from SPV_EXT_descriptor_heap |
| 1166 | // Vulkan allows untyped pointer without |Data Type| but only for heap |
| 1167 | // decorated variable that are in UniformConstant |
| 1168 | if (spvIsVulkanEnv(_.context()->target_env)) { |
| 1169 | if (storage_class != spv::StorageClass::UniformConstant) { |
| 1170 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1171 | << _.VkErrorID(11167) << "Storage class is " |
| 1172 | << StorageClassToString(storage_class) |
| 1173 | << ", but Vulkan requires that Data Type be specified when " |
| 1174 | "not using UniformConstant storage class"; |
| 1175 | } else if (!(_.IsDescriptorHeapBaseVariable(inst))) { |
| 1176 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1177 | << _.VkErrorID(11347) |
| 1178 | << "Storage class is UniformConstant, but Vulkan requires " |
| 1179 | "that Data Type be specified if the variable is not " |
| 1180 | "decorated with SamplerHeapEXT or ResourceHeapEXT"; |
| 1181 | } |
| 1182 | } |
| 1183 | } |
| 1184 | } |
no test coverage detected