Validate OpenCL environment rules for OpTypeImage (#2606)
It is currently not possible to use an Image Format that is
not Unknown without requiring a capability forbidden by the
OpenCL environment. As such the validation of Image Format
currently leans on capability validation entirely.
Fixes #2592.
Signed-off-by: Kevin Petit <kevin.petit@arm.com>
diff --git a/source/val/validate_image.cpp b/source/val/validate_image.cpp
index ebf9ae0..28fd9d1 100644
--- a/source/val/validate_image.cpp
+++ b/source/val/validate_image.cpp
@@ -718,6 +718,11 @@
<< "Expected Sampled Type to be a 32-bit int or float "
"scalar type for Vulkan environment";
}
+ } else if (spvIsOpenCLEnv(_.context()->target_env)) {
+ if (!_.IsVoidType(info.sampled_type)) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << "Sampled Type must be OpTypeVoid in the OpenCL environment.";
+ }
} else {
const SpvOp sampled_type_opcode = _.GetIdOpcode(info.sampled_type);
if (sampled_type_opcode != SpvOpTypeVoid &&
@@ -741,16 +746,39 @@
<< "Invalid Arrayed " << info.arrayed << " (must be 0 or 1)";
}
+ if (spvIsOpenCLEnv(_.context()->target_env)) {
+ if ((info.arrayed == 1) && (info.dim != SpvDim1D) &&
+ (info.dim != SpvDim2D)) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << "In the OpenCL environment, Arrayed may only be set to 1 "
+ << "when Dim is either 1D or 2D.";
+ }
+ }
+
if (info.multisampled > 1) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< "Invalid MS " << info.multisampled << " (must be 0 or 1)";
}
+ if (spvIsOpenCLEnv(_.context()->target_env)) {
+ if (info.multisampled != 0) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << "MS must be 0 in the OpenCL environement.";
+ }
+ }
+
if (info.sampled > 2) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< "Invalid Sampled " << info.sampled << " (must be 0, 1 or 2)";
}
+ if (spvIsOpenCLEnv(_.context()->target_env)) {
+ if (info.sampled != 0) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << "Sampled must be 0 in the OpenCL environment.";
+ }
+ }
+
if (info.dim == SpvDimSubpassData) {
if (info.sampled != 2) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -763,7 +791,15 @@
}
}
- // Format and Access Qualifier are checked elsewhere.
+ // Format and Access Qualifier are also checked elsewhere.
+
+ if (spvIsOpenCLEnv(_.context()->target_env)) {
+ if (info.access_qualifier == SpvAccessQualifierMax) {
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
+ << "In the OpenCL environment, the optional Access Qualifier"
+ << " must be present.";
+ }
+ }
return SPV_SUCCESS;
}
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp
index 745c82b..394f728 100644
--- a/source/val/validation_state.cpp
+++ b/source/val/validation_state.cpp
@@ -691,6 +691,12 @@
return 0;
}
+bool ValidationState_t::IsVoidType(uint32_t id) const {
+ const Instruction* inst = FindDef(id);
+ assert(inst);
+ return inst->opcode() == SpvOpTypeVoid;
+}
+
bool ValidationState_t::IsFloatScalarType(uint32_t id) const {
const Instruction* inst = FindDef(id);
assert(inst);
diff --git a/source/val/validation_state.h b/source/val/validation_state.h
index 9b0a586..c34c1ec 100644
--- a/source/val/validation_state.h
+++ b/source/val/validation_state.h
@@ -548,6 +548,7 @@
// Returns true iff |id| is a type corresponding to the name of the function.
// Only works for types not for objects.
+ bool IsVoidType(uint32_t id) const;
bool IsFloatScalarType(uint32_t id) const;
bool IsFloatVectorType(uint32_t id) const;
bool IsFloatScalarOrVectorType(uint32_t id) const;
diff --git a/test/val/val_opencl_test.cpp b/test/val/val_opencl_test.cpp
index 52e4db6..1a440e8 100644
--- a/test/val/val_opencl_test.cpp
+++ b/test/val/val_opencl_test.cpp
@@ -56,6 +56,97 @@
"\n OpMemoryModel Physical32 GLSL450\n"));
}
+TEST_F(ValidateOpenCL, NonVoidSampledTypeImageBad) {
+ std::string spirv = R"(
+ OpCapability Addresses
+ OpCapability Kernel
+ OpMemoryModel Physical32 OpenCL
+ %1 = OpTypeInt 32 0
+ %2 = OpTypeImage %1 2D 0 0 0 0 Unknown ReadOnly
+)";
+
+ CompileSuccessfully(spirv);
+
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Sampled Type must be OpTypeVoid in the OpenCL environment."
+ "\n %2 = OpTypeImage %uint 2D 0 0 0 0 Unknown ReadOnly\n"));
+}
+
+TEST_F(ValidateOpenCL, NonZeroMSImageBad) {
+ std::string spirv = R"(
+ OpCapability Addresses
+ OpCapability Kernel
+ OpMemoryModel Physical32 OpenCL
+ %1 = OpTypeVoid
+ %2 = OpTypeImage %1 2D 0 0 1 0 Unknown ReadOnly
+)";
+
+ CompileSuccessfully(spirv);
+
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("MS must be 0 in the OpenCL environement."
+ "\n %2 = OpTypeImage %void 2D 0 0 1 0 Unknown ReadOnly\n"));
+}
+
+TEST_F(ValidateOpenCL, Non1D2DArrayedImageBad) {
+ std::string spirv = R"(
+ OpCapability Addresses
+ OpCapability Kernel
+ OpMemoryModel Physical32 OpenCL
+ %1 = OpTypeVoid
+ %2 = OpTypeImage %1 3D 0 1 0 0 Unknown ReadOnly
+)";
+
+ CompileSuccessfully(spirv);
+
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("In the OpenCL environment, Arrayed may only be set to 1 "
+ "when Dim is either 1D or 2D."
+ "\n %2 = OpTypeImage %void 3D 0 1 0 0 Unknown ReadOnly\n"));
+}
+
+TEST_F(ValidateOpenCL, NonZeroSampledImageBad) {
+ std::string spirv = R"(
+ OpCapability Addresses
+ OpCapability Kernel
+ OpMemoryModel Physical32 OpenCL
+ %1 = OpTypeVoid
+ %2 = OpTypeImage %1 3D 0 0 0 1 Unknown ReadOnly
+)";
+
+ CompileSuccessfully(spirv);
+
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Sampled must be 0 in the OpenCL environment."
+ "\n %2 = OpTypeImage %void 3D 0 0 0 1 Unknown ReadOnly\n"));
+}
+
+TEST_F(ValidateOpenCL, NoAccessQualifierImageBad) {
+ std::string spirv = R"(
+ OpCapability Addresses
+ OpCapability Kernel
+ OpMemoryModel Physical32 OpenCL
+ %1 = OpTypeVoid
+ %2 = OpTypeImage %1 3D 0 0 0 0 Unknown
+)";
+
+ CompileSuccessfully(spirv);
+
+ EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_OPENCL_1_2));
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("In the OpenCL environment, the optional "
+ "Access Qualifier must be present."
+ "\n %2 = OpTypeImage %void 3D 0 0 0 0 Unknown\n"));
+}
+
} // namespace
} // namespace val
} // namespace spvtools