| 1386 | } |
| 1387 | |
| 1388 | spv_result_t ValidateStore(ValidationState_t& _, const Instruction* inst) { |
| 1389 | const auto pointer_index = 0; |
| 1390 | const auto pointer_id = inst->GetOperandAs<uint32_t>(pointer_index); |
| 1391 | const auto pointer = _.FindDef(pointer_id); |
| 1392 | if (!pointer || |
| 1393 | (_.addressing_model() == spv::AddressingModel::Logical && |
| 1394 | ((!_.features().variable_pointers && |
| 1395 | !spvOpcodeReturnsLogicalPointer(pointer->opcode())) || |
| 1396 | (_.features().variable_pointers && |
| 1397 | !spvOpcodeReturnsLogicalVariablePointer(pointer->opcode()))))) { |
| 1398 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1399 | << "OpStore Pointer <id> " << _.getIdName(pointer_id) |
| 1400 | << " is not a logical pointer."; |
| 1401 | } |
| 1402 | const auto pointer_type = _.FindDef(pointer->type_id()); |
| 1403 | if (!pointer_type || |
| 1404 | (pointer_type->opcode() != spv::Op::OpTypePointer && |
| 1405 | pointer_type->opcode() != spv::Op::OpTypeUntypedPointerKHR)) { |
| 1406 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1407 | << "OpStore type for pointer <id> " << _.getIdName(pointer_id) |
| 1408 | << " is not a pointer type."; |
| 1409 | } |
| 1410 | |
| 1411 | Instruction* type = nullptr; |
| 1412 | if (pointer_type->opcode() == spv::Op::OpTypePointer) { |
| 1413 | const auto type_id = pointer_type->GetOperandAs<uint32_t>(2); |
| 1414 | type = _.FindDef(type_id); |
| 1415 | if (!type || spv::Op::OpTypeVoid == type->opcode()) { |
| 1416 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1417 | << "OpStore Pointer <id> " << _.getIdName(pointer_id) |
| 1418 | << "s type is void."; |
| 1419 | } |
| 1420 | } |
| 1421 | |
| 1422 | // validate storage class |
| 1423 | { |
| 1424 | uint32_t data_type; |
| 1425 | spv::StorageClass storage_class; |
| 1426 | if (!_.GetPointerTypeInfo(pointer_type->id(), &data_type, &storage_class)) { |
| 1427 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1428 | << "OpStore Pointer <id> " << _.getIdName(pointer_id) |
| 1429 | << " is not pointer type"; |
| 1430 | } |
| 1431 | |
| 1432 | if (storage_class == spv::StorageClass::UniformConstant || |
| 1433 | storage_class == spv::StorageClass::Input || |
| 1434 | storage_class == spv::StorageClass::PushConstant) { |
| 1435 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1436 | << "OpStore Pointer <id> " << _.getIdName(pointer_id) |
| 1437 | << " storage class is read-only"; |
| 1438 | } else if (storage_class == spv::StorageClass::ShaderRecordBufferKHR) { |
| 1439 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 1440 | << "ShaderRecordBufferKHR Storage Class variables are read only"; |
| 1441 | } else if (storage_class == spv::StorageClass::HitAttributeKHR) { |
| 1442 | std::string errorVUID = _.VkErrorID(4703); |
| 1443 | _.function(inst->function()->id()) |
| 1444 | ->RegisterExecutionModelLimitation( |
| 1445 | [errorVUID](spv::ExecutionModel model, std::string* message) { |
no test coverage detected