SPV_ENV_UNIVERSAL_1_0, // SPIR-V 1.0 latest revision, no other restrictions.
SPV_ENV_VULKAN_1_0, // Vulkan 1.0 latest revision.
SPV_ENV_UNIVERSAL_1_1, // SPIR-V 1.1 latest revision, no other restrictions.
- SPV_ENV_OPENCL_2_1, // OpenCL 2.1 latest revision.
- SPV_ENV_OPENCL_2_2, // OpenCL 2.2 latest revision.
+ SPV_ENV_OPENCL_2_1, // OpenCL Full Profile 2.1 latest revision.
+ SPV_ENV_OPENCL_2_2, // OpenCL Full Profile 2.2 latest revision.
SPV_ENV_OPENGL_4_0, // OpenGL 4.0 plus GL_ARB_gl_spirv, latest revisions.
SPV_ENV_OPENGL_4_1, // OpenGL 4.1 plus GL_ARB_gl_spirv, latest revisions.
SPV_ENV_OPENGL_4_2, // OpenGL 4.2 plus GL_ARB_gl_spirv, latest revisions.
// There is no variant for OpenGL 4.4.
SPV_ENV_OPENGL_4_5, // OpenGL 4.5 plus GL_ARB_gl_spirv, latest revisions.
SPV_ENV_UNIVERSAL_1_2, // SPIR-V 1.2, latest revision, no other restrictions.
+ SPV_ENV_OPENCL_1_2, // OpenCL Full Profile 1.2 plus cl_khr_il_program,
+ // latest revision.
+ SPV_ENV_OPENCL_EMBEDDED_1_2, // OpenCL Embedded Profile 1.2 plus
+ // cl_khr_il_program, latest revision.
+ SPV_ENV_OPENCL_2_0, // OpenCL Full Profile 2.0 plus cl_khr_il_program,
+ // latest revision.
+ SPV_ENV_OPENCL_EMBEDDED_2_0, // OpenCL Embedded Profile 2.0 plus
+ // cl_khr_il_program, latest revision.
+ SPV_ENV_OPENCL_EMBEDDED_2_1, // OpenCL Embedded Profile 2.1 latest revision.
+ SPV_ENV_OPENCL_EMBEDDED_2_2, // OpenCL Embedded Profile 2.2 latest revision.
} spv_target_env;
// SPIR-V Validator can be parameterized with the following Universal Limits.
case SPV_ENV_VULKAN_1_0:
case SPV_ENV_UNIVERSAL_1_1:
case SPV_ENV_UNIVERSAL_1_2:
+ case SPV_ENV_OPENCL_1_2:
+ case SPV_ENV_OPENCL_EMBEDDED_1_2:
+ case SPV_ENV_OPENCL_2_0:
+ case SPV_ENV_OPENCL_EMBEDDED_2_0:
case SPV_ENV_OPENCL_2_1:
+ case SPV_ENV_OPENCL_EMBEDDED_2_1:
case SPV_ENV_OPENCL_2_2:
+ case SPV_ENV_OPENCL_EMBEDDED_2_2:
case SPV_ENV_OPENGL_4_0:
case SPV_ENV_OPENGL_4_1:
case SPV_ENV_OPENGL_4_2:
switch (env) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_OPENCL_1_2:
+ case SPV_ENV_OPENCL_EMBEDDED_1_2:
+ case SPV_ENV_OPENCL_2_0:
+ case SPV_ENV_OPENCL_EMBEDDED_2_0:
case SPV_ENV_OPENCL_2_1:
+ case SPV_ENV_OPENCL_EMBEDDED_2_1:
case SPV_ENV_OPENGL_4_0:
case SPV_ENV_OPENGL_4_1:
case SPV_ENV_OPENGL_4_2:
return SPV_SUCCESS;
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_OPENCL_2_2:
+ case SPV_ENV_OPENCL_EMBEDDED_2_2:
*pInstTable = &kTable_1_2;
return SPV_SUCCESS;
}
switch (env) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_OPENCL_1_2:
+ case SPV_ENV_OPENCL_EMBEDDED_1_2:
+ case SPV_ENV_OPENCL_2_0:
+ case SPV_ENV_OPENCL_EMBEDDED_2_0:
case SPV_ENV_OPENCL_2_1:
+ case SPV_ENV_OPENCL_EMBEDDED_2_1:
case SPV_ENV_OPENGL_4_0:
case SPV_ENV_OPENGL_4_1:
case SPV_ENV_OPENGL_4_2:
return SPV_SUCCESS;
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_OPENCL_2_2:
+ case SPV_ENV_OPENCL_EMBEDDED_2_2:
*pOperandTable = &kTable_1_2;
return SPV_SUCCESS;
}
return "SPIR-V 1.0 (under Vulkan 1.0 semantics)";
case SPV_ENV_UNIVERSAL_1_1:
return "SPIR-V 1.1";
+ case SPV_ENV_OPENCL_1_2:
+ return "SPIR-V 1.0 (under OpenCL 1.2 Full Profile semantics)";
+ case SPV_ENV_OPENCL_EMBEDDED_1_2:
+ return "SPIR-V 1.0 (under OpenCL 1.2 Embedded Profile semantics)";
+ case SPV_ENV_OPENCL_2_0:
+ return "SPIR-V 1.0 (under OpenCL 2.0 Full Profile semantics)";
+ case SPV_ENV_OPENCL_EMBEDDED_2_0:
+ return "SPIR-V 1.0 (under OpenCL 2.0 Embedded Profile semantics)";
case SPV_ENV_OPENCL_2_1:
- return "SPIR-V 1.0 (under OpenCL 2.1 semantics)";
+ return "SPIR-V 1.0 (under OpenCL 2.1 Full Profile semantics)";
+ case SPV_ENV_OPENCL_EMBEDDED_2_1:
+ return "SPIR-V 1.0 (under OpenCL 2.1 Embedded Profile semantics)";
case SPV_ENV_OPENCL_2_2:
- return "SPIR-V 1.1 (under OpenCL 2.2 semantics)";
+ return "SPIR-V 1.1 (under OpenCL 2.2 Full Profile semantics)";
+ case SPV_ENV_OPENCL_EMBEDDED_2_2:
+ return "SPIR-V 1.1 (under OpenCL 2.2 Embedded Profile semantics)";
case SPV_ENV_OPENGL_4_0:
return "SPIR-V 1.0 (under OpenCL 4.0 semantics)";
case SPV_ENV_OPENGL_4_1:
switch (env) {
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_VULKAN_1_0:
+ case SPV_ENV_OPENCL_1_2:
+ case SPV_ENV_OPENCL_EMBEDDED_1_2:
+ case SPV_ENV_OPENCL_2_0:
+ case SPV_ENV_OPENCL_EMBEDDED_2_0:
case SPV_ENV_OPENCL_2_1:
+ case SPV_ENV_OPENCL_EMBEDDED_2_1:
case SPV_ENV_OPENGL_4_0:
case SPV_ENV_OPENGL_4_1:
case SPV_ENV_OPENGL_4_2:
return SPV_SPIRV_VERSION_WORD(1, 1);
case SPV_ENV_UNIVERSAL_1_2:
case SPV_ENV_OPENCL_2_2:
+ case SPV_ENV_OPENCL_EMBEDDED_2_2:
return SPV_SPIRV_VERSION_WORD(1, 2);
}
assert(0 && "Unhandled SPIR-V target environment");
} else if (match("spv1.2")) {
if (env) *env = SPV_ENV_UNIVERSAL_1_2;
return true;
+ } else if (match("opencl1.2embedded")) {
+ if (env) *env = SPV_ENV_OPENCL_EMBEDDED_1_2;
+ return true;
+ } else if (match("opencl1.2")) {
+ if (env) *env = SPV_ENV_OPENCL_1_2;
+ return true;
+ } else if (match("opencl2.0embedded")) {
+ if (env) *env = SPV_ENV_OPENCL_EMBEDDED_2_0;
+ return true;
+ } else if (match("opencl2.0")) {
+ if (env) *env = SPV_ENV_OPENCL_2_0;
+ return true;
+ } else if (match("opencl2.1embedded")) {
+ if (env) *env = SPV_ENV_OPENCL_EMBEDDED_2_1;
+ return true;
} else if (match("opencl2.1")) {
if (env) *env = SPV_ENV_OPENCL_2_1;
return true;
+ } else if (match("opencl2.2embedded")) {
+ if (env) *env = SPV_ENV_OPENCL_EMBEDDED_2_2;
+ return true;
} else if (match("opencl2.2")) {
if (env) *env = SPV_ENV_OPENCL_2_2;
return true;
case SPV_ENV_UNIVERSAL_1_0:
case SPV_ENV_VULKAN_1_0:
case SPV_ENV_UNIVERSAL_1_1:
+ case SPV_ENV_OPENCL_1_2:
+ case SPV_ENV_OPENCL_EMBEDDED_1_2:
+ case SPV_ENV_OPENCL_2_0:
+ case SPV_ENV_OPENCL_EMBEDDED_2_0:
case SPV_ENV_OPENCL_2_1:
+ case SPV_ENV_OPENCL_EMBEDDED_2_1:
case SPV_ENV_OPENCL_2_2:
+ case SPV_ENV_OPENCL_EMBEDDED_2_2:
case SPV_ENV_OPENGL_4_0:
case SPV_ENV_OPENGL_4_1:
case SPV_ENV_OPENGL_4_2:
return false;
}
+bool IsSupportGuaranteedOpenCL_1_2(uint32_t capability, bool embedded_profile) {
+ switch (capability) {
+ case SpvCapabilityAddresses:
+ case SpvCapabilityFloat16Buffer:
+ case SpvCapabilityGroups:
+ case SpvCapabilityInt16:
+ case SpvCapabilityInt8:
+ case SpvCapabilityKernel:
+ case SpvCapabilityLinkage:
+ case SpvCapabilityVector16:
+ return true;
+ case SpvCapabilityInt64:
+ return !embedded_profile;
+ case SpvCapabilityPipes:
+ return embedded_profile;
+ }
+ return false;
+}
+
+bool IsSupportGuaranteedOpenCL_2_0(uint32_t capability, bool embedded_profile) {
+ if (IsSupportGuaranteedOpenCL_1_2(capability, embedded_profile)) return true;
+
+ switch (capability) {
+ case SpvCapabilityDeviceEnqueue:
+ case SpvCapabilityGenericPointer:
+ case SpvCapabilityPipes:
+ return true;
+ }
+ return false;
+}
+
+bool IsSupportGuaranteedOpenCL_2_2(uint32_t capability, bool embedded_profile) {
+ if (IsSupportGuaranteedOpenCL_2_0(capability, embedded_profile)) return true;
+
+ switch (capability) {
+ case SpvCapabilitySubgroupDispatch:
+ case SpvCapabilityPipeStorage:
+ return true;
+ }
+ return false;
+}
+
+bool IsSupportOptionalOpenCL_1_2(uint32_t capability) {
+ switch (capability) {
+ case SpvCapabilityImageBasic:
+ case SpvCapabilityFloat64:
+ return true;
+ }
+ return false;
+}
+
// Checks if |capability| was enabled by extension.
bool IsEnabledByExtension(ValidationState_t& _, uint32_t capability) {
spv_operand_desc operand_desc = nullptr;
return _.HasAnyOfExtensions(operand_exts);
}
+bool IsEnabledByCapabilityOpenCL_1_2(ValidationState_t& _,
+ uint32_t capability) {
+ if (_.HasCapability(SpvCapabilityImageBasic)) {
+ switch (capability) {
+ case SpvCapabilityLiteralSampler:
+ case SpvCapabilitySampled1D:
+ case SpvCapabilityImage1D:
+ case SpvCapabilitySampledBuffer:
+ case SpvCapabilityImageBuffer:
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+
+bool IsEnabledByCapabilityOpenCL_2_0(ValidationState_t& _,
+ uint32_t capability) {
+ if (_.HasCapability(SpvCapabilityImageBasic)) {
+ switch (capability) {
+ case SpvCapabilityImageReadWrite:
+ case SpvCapabilityLiteralSampler:
+ case SpvCapabilitySampled1D:
+ case SpvCapabilityImage1D:
+ case SpvCapabilitySampledBuffer:
+ case SpvCapabilityImageBuffer:
+ return true;
+ }
+ return false;
+ }
+ return false;
+}
+
} // namespace
// Validates that capability declarations use operands allowed in the current
const uint32_t capability = inst->words[operand.offset];
const auto env = _.context()->target_env;
+ const bool opencl_embedded = env == SPV_ENV_OPENCL_EMBEDDED_1_2 ||
+ env == SPV_ENV_OPENCL_EMBEDDED_2_0 ||
+ env == SPV_ENV_OPENCL_EMBEDDED_2_1 ||
+ env == SPV_ENV_OPENCL_EMBEDDED_2_2;
+ const std::string opencl_profile = opencl_embedded ? "Embedded" : "Full";
if (env == SPV_ENV_VULKAN_1_0) {
if (!IsSupportGuaranteedVulkan_1_0(capability) &&
!IsSupportOptionalVulkan_1_0(capability) &&
<< " is not allowed by Vulkan 1.0 specification"
<< " (or requires extension)";
}
+ } else if (env == SPV_ENV_OPENCL_1_2 || env == SPV_ENV_OPENCL_EMBEDDED_1_2) {
+ if (!IsSupportGuaranteedOpenCL_1_2(capability, opencl_embedded) &&
+ !IsSupportOptionalOpenCL_1_2(capability) &&
+ !IsEnabledByExtension(_, capability) &&
+ !IsEnabledByCapabilityOpenCL_1_2(_, capability)) {
+ return _.diag(SPV_ERROR_INVALID_CAPABILITY)
+ << "Capability value " << capability
+ << " is not allowed by OpenCL 1.2 " << opencl_profile
+ << " Profile specification"
+ << " (or requires extension or capability)";
+ }
+ } else if (env == SPV_ENV_OPENCL_2_0 || env == SPV_ENV_OPENCL_EMBEDDED_2_0 ||
+ env == SPV_ENV_OPENCL_2_1 || env == SPV_ENV_OPENCL_EMBEDDED_2_1) {
+ if (!IsSupportGuaranteedOpenCL_2_0(capability, opencl_embedded) &&
+ !IsSupportOptionalOpenCL_1_2(capability) &&
+ !IsEnabledByExtension(_, capability) &&
+ !IsEnabledByCapabilityOpenCL_2_0(_, capability)) {
+ return _.diag(SPV_ERROR_INVALID_CAPABILITY)
+ << "Capability value " << capability
+ << " is not allowed by OpenCL 2.0/2.1 " << opencl_profile
+ << " Profile specification"
+ << " (or requires extension or capability)";
+ }
+ } else if (env == SPV_ENV_OPENCL_2_2 || env == SPV_ENV_OPENCL_EMBEDDED_2_2) {
+ if (!IsSupportGuaranteedOpenCL_2_2(capability, opencl_embedded) &&
+ !IsSupportOptionalOpenCL_1_2(capability) &&
+ !IsEnabledByExtension(_, capability) &&
+ !IsEnabledByCapabilityOpenCL_2_0(_, capability)) {
+ return _.diag(SPV_ERROR_INVALID_CAPABILITY)
+ << "Capability value " << capability
+ << " is not allowed by OpenCL 2.2 " << opencl_profile
+ << " Profile specification"
+ << " (or requires extension or capability)";
+ }
}
return SPV_SUCCESS;
TEST(GetContextTest, InvalidTargetEnvProducesNull) {
// Use a value beyond the last valid enum value.
- spv_context context = spvContextCreate(static_cast<spv_target_env>(15));
+ spv_context context = spvContextCreate(static_cast<spv_target_env>(17));
EXPECT_EQ(context, nullptr);
}
EXPECT_THAT(env, Eq(GetParam().env));
}
-INSTANTIATE_TEST_CASE_P(TargetParsing, TargetParseTest,
- ValuesIn(std::vector<ParseCase>{
- {"spv1.0", true, SPV_ENV_UNIVERSAL_1_0},
- {"spv1.1", true, SPV_ENV_UNIVERSAL_1_1},
- {"spv1.2", true, SPV_ENV_UNIVERSAL_1_2},
- {"vulkan1.0", true, SPV_ENV_VULKAN_1_0},
- {"opencl2.1", true, SPV_ENV_OPENCL_2_1},
- {"opencl2.2", true, SPV_ENV_OPENCL_2_2},
- {"opengl4.0", true, SPV_ENV_OPENGL_4_0},
- {"opengl4.1", true, SPV_ENV_OPENGL_4_1},
- {"opengl4.2", true, SPV_ENV_OPENGL_4_2},
- {"opengl4.3", true, SPV_ENV_OPENGL_4_3},
- {"opengl4.5", true, SPV_ENV_OPENGL_4_5},
- {nullptr, false, SPV_ENV_UNIVERSAL_1_0},
- {"", false, SPV_ENV_UNIVERSAL_1_0},
- {"abc", false, SPV_ENV_UNIVERSAL_1_0},
- }));
+INSTANTIATE_TEST_CASE_P(
+ TargetParsing, TargetParseTest,
+ ValuesIn(std::vector<ParseCase>{
+ {"spv1.0", true, SPV_ENV_UNIVERSAL_1_0},
+ {"spv1.1", true, SPV_ENV_UNIVERSAL_1_1},
+ {"spv1.2", true, SPV_ENV_UNIVERSAL_1_2},
+ {"vulkan1.0", true, SPV_ENV_VULKAN_1_0},
+ {"opencl2.1", true, SPV_ENV_OPENCL_2_1},
+ {"opencl2.2", true, SPV_ENV_OPENCL_2_2},
+ {"opengl4.0", true, SPV_ENV_OPENGL_4_0},
+ {"opengl4.1", true, SPV_ENV_OPENGL_4_1},
+ {"opengl4.2", true, SPV_ENV_OPENGL_4_2},
+ {"opengl4.3", true, SPV_ENV_OPENGL_4_3},
+ {"opengl4.5", true, SPV_ENV_OPENGL_4_5},
+ {"opencl1.2", true, SPV_ENV_OPENCL_1_2},
+ {"opencl1.2embedded", true, SPV_ENV_OPENCL_EMBEDDED_1_2},
+ {"opencl2.0", true, SPV_ENV_OPENCL_2_0},
+ {"opencl2.0embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_0},
+ {"opencl2.1embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_1},
+ {"opencl2.2embedded", true, SPV_ENV_OPENCL_EMBEDDED_2_2},
+ {nullptr, false, SPV_ENV_UNIVERSAL_1_0},
+ {"", false, SPV_ENV_UNIVERSAL_1_0},
+ {"abc", false, SPV_ENV_UNIVERSAL_1_0},
+ }));
} // anonymous namespace
// Returns a vector of all valid target environment enums.
inline std::vector<spv_target_env> AllTargetEnvironments() {
- return {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1, SPV_ENV_OPENCL_2_1,
- SPV_ENV_OPENCL_2_2, SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_0,
- SPV_ENV_OPENGL_4_1, SPV_ENV_OPENGL_4_2, SPV_ENV_OPENGL_4_3,
- SPV_ENV_OPENGL_4_5, SPV_ENV_UNIVERSAL_1_2};
+ return {SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
+ SPV_ENV_OPENCL_1_2, SPV_ENV_OPENCL_EMBEDDED_1_2,
+ SPV_ENV_OPENCL_2_0, SPV_ENV_OPENCL_EMBEDDED_2_0,
+ SPV_ENV_OPENCL_2_1, SPV_ENV_OPENCL_EMBEDDED_2_1,
+ SPV_ENV_OPENCL_2_2, SPV_ENV_OPENCL_EMBEDDED_2_2,
+ SPV_ENV_VULKAN_1_0, SPV_ENV_OPENGL_4_0,
+ SPV_ENV_OPENGL_4_1, SPV_ENV_OPENGL_4_2,
+ SPV_ENV_OPENGL_4_3, SPV_ENV_OPENGL_4_5,
+ SPV_ENV_UNIVERSAL_1_2};
}
// Returns the capabilities in a CapabilitySet as an ordered vector.
HasSubstr("Capability value 4427 is not allowed by Vulkan 1.0"));
}
+TEST_F(ValidateCapability, NonOpenCL12FullCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Pipes
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)";
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_1_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 17 is not allowed by OpenCL 1.2 Full Profile"));
+}
+
+TEST_F(ValidateCapability, OpenCL12FullEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability ImageBasic
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+}
+
+TEST_F(ValidateCapability, OpenCL12FullNotEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_1_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_1_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 43 is not allowed by OpenCL 1.2 Full Profile"));
+}
+
+TEST_F(ValidateCapability, NonOpenCL12EmbeddedCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Int64
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)";
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 11 is not allowed by OpenCL 1.2 Embedded Profile"));
+}
+
+TEST_F(ValidateCapability, OpenCL12EmbeddedEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability ImageBasic
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
+}
+
+TEST_F(ValidateCapability, OpenCL12EmbeddedNotEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_1_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_1_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 43 is not allowed by OpenCL 1.2 Embedded Profile"));
+}
+
+TEST_F(ValidateCapability, OpenCL20FullCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Pipes
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)";
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_0));
+}
+
+TEST_F(ValidateCapability, NonOpenCL20FullCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Matrix
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)";
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_2_0));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 0 is not allowed by OpenCL 2.0/2.1 Full Profile"));
+}
+
+TEST_F(ValidateCapability, OpenCL20FullEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability ImageBasic
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_0));
+}
+
+TEST_F(ValidateCapability, OpenCL20FullNotEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_0);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_2_0));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 43 is not allowed by OpenCL 2.0/2.1 Full Profile"));
+}
+
+TEST_F(ValidateCapability, NonOpenCL20EmbeddedCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Int64
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)";
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Capability value 11 is not allowed by OpenCL 2.0/2.1 "
+ "Embedded Profile"));
+}
+
+TEST_F(ValidateCapability, OpenCL20EmbeddedEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability ImageBasic
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0));
+}
+
+TEST_F(ValidateCapability, OpenCL20EmbeddedNotEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_0);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_0));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Capability value 43 is not allowed by OpenCL 2.0/2.1 "
+ "Embedded Profile"));
+}
+
+TEST_F(ValidateCapability, OpenCL22FullCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability PipeStorage
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)";
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_2));
+}
+
+TEST_F(ValidateCapability, NonOpenCL22FullCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Matrix
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)";
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_2_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 0 is not allowed by OpenCL 2.2 Full Profile"));
+}
+
+TEST_F(ValidateCapability, OpenCL22FullEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability ImageBasic
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_2_2));
+}
+
+TEST_F(ValidateCapability, OpenCL22FullNotEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_2_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_2_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 43 is not allowed by OpenCL 2.2 Full Profile"));
+}
+
+TEST_F(ValidateCapability, NonOpenCL22EmbeddedCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Int64
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)";
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 11 is not allowed by OpenCL 2.2 Embedded Profile"));
+}
+
+TEST_F(ValidateCapability, OpenCL22EmbeddedEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability ImageBasic
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2);
+ EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2));
+}
+
+TEST_F(ValidateCapability, OpenCL22EmbeddedNotEnabledByCapability) {
+ const std::string spirv = R"(
+OpCapability Kernel
+OpCapability Addresses
+OpCapability Linkage
+OpCapability Sampled1D
+OpMemoryModel Physical64 OpenCL
+%u32 = OpTypeInt 32 0
+)" + string(kVoidFVoid);
+
+ CompileSuccessfully(spirv, SPV_ENV_OPENCL_EMBEDDED_2_2);
+ EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
+ ValidateInstructions(SPV_ENV_OPENCL_EMBEDDED_2_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr(
+ "Capability value 43 is not allowed by OpenCL 2.2 Embedded Profile"));
+}
+
} // namespace