Validates that capability declarations use operands allowed in the current context.
| 348 | // Validates that capability declarations use operands allowed in the current |
| 349 | // context. |
| 350 | spv_result_t CapabilityPass(ValidationState_t& _, const Instruction* inst) { |
| 351 | if (inst->opcode() != spv::Op::OpCapability && |
| 352 | inst->opcode() != spv::Op::OpConditionalCapabilityINTEL) |
| 353 | return SPV_SUCCESS; |
| 354 | |
| 355 | assert(!((inst->opcode() == spv::Op::OpCapability) ^ |
| 356 | (inst->operands().size() == 1))); |
| 357 | assert(!((inst->opcode() == spv::Op::OpConditionalCapabilityINTEL) ^ |
| 358 | (inst->operands().size() == 2))); |
| 359 | |
| 360 | const uint32_t i_cap = |
| 361 | inst->opcode() == spv::Op::OpConditionalCapabilityINTEL ? 1 : 0; |
| 362 | const spv_parsed_operand_t& operand = inst->operand(i_cap); |
| 363 | |
| 364 | assert(operand.num_words == 1); |
| 365 | assert(operand.offset < inst->words().size()); |
| 366 | |
| 367 | const uint32_t capability = inst->word(operand.offset); |
| 368 | const auto capability_str = [capability]() { |
| 369 | const spvtools::OperandDesc* desc = nullptr; |
| 370 | if (spvtools::LookupOperand(SPV_OPERAND_TYPE_CAPABILITY, capability, |
| 371 | &desc) != SPV_SUCCESS || |
| 372 | !desc) { |
| 373 | return std::string("Unknown"); |
| 374 | } |
| 375 | return std::string(desc->name().data()); |
| 376 | }; |
| 377 | |
| 378 | const auto env = _.context()->target_env; |
| 379 | const bool opencl_embedded = env == SPV_ENV_OPENCL_EMBEDDED_1_2 || |
| 380 | env == SPV_ENV_OPENCL_EMBEDDED_2_0 || |
| 381 | env == SPV_ENV_OPENCL_EMBEDDED_2_1 || |
| 382 | env == SPV_ENV_OPENCL_EMBEDDED_2_2; |
| 383 | const std::string opencl_profile = opencl_embedded ? "Embedded" : "Full"; |
| 384 | if (env == SPV_ENV_VULKAN_1_0) { |
| 385 | if (!IsSupportGuaranteedVulkan_1_0(capability) && |
| 386 | !IsSupportOptionalVulkan_1_0(capability) && |
| 387 | !IsEnabledByExtension(_, capability)) { |
| 388 | return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst) |
| 389 | << "Capability " << capability_str() |
| 390 | << " is not allowed by Vulkan 1.0 specification" |
| 391 | << " (or requires extension)"; |
| 392 | } |
| 393 | } else if (env == SPV_ENV_VULKAN_1_1) { |
| 394 | if (!IsSupportGuaranteedVulkan_1_1(capability) && |
| 395 | !IsSupportOptionalVulkan_1_1(capability) && |
| 396 | !IsEnabledByExtension(_, capability)) { |
| 397 | return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst) |
| 398 | << "Capability " << capability_str() |
| 399 | << " is not allowed by Vulkan 1.1 specification" |
| 400 | << " (or requires extension)"; |
| 401 | } |
| 402 | } else if (env == SPV_ENV_VULKAN_1_2) { |
| 403 | if (!IsSupportGuaranteedVulkan_1_2(capability) && |
| 404 | !IsSupportOptionalVulkan_1_2(capability) && |
| 405 | !IsEnabledByExtension(_, capability)) { |
| 406 | return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst) |
| 407 | << "Capability " << capability_str() |
no test coverage detected