|
|
@@ -640,65 +640,64 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
return SPV_SUCCESS;
|
|
|
}
|
|
|
|
|
|
-// Checks some of the validation rules which are common to multiple opcodes.
|
|
|
-spv_result_t ValidateImageCommon(ValidationState_t& _, const Instruction* inst,
|
|
|
- const ImageTypeInfo& info) {
|
|
|
- const SpvOp opcode = inst->opcode();
|
|
|
- if (IsProj(opcode)) {
|
|
|
- if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
|
|
|
- info.dim != SpvDimRect) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image 'Dim' parameter to be 1D, 2D, 3D or Rect";
|
|
|
- }
|
|
|
+// Validate OpImage*Proj* instructions
|
|
|
+spv_result_t ValidateImageProj(ValidationState_t& _, const Instruction* inst,
|
|
|
+ const ImageTypeInfo& info) {
|
|
|
+ if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
|
|
|
+ info.dim != SpvDimRect) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Image 'Dim' parameter to be 1D, 2D, 3D or Rect";
|
|
|
+ }
|
|
|
|
|
|
- if (info.multisampled != 0) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image 'MS' parameter to be 0";
|
|
|
- }
|
|
|
+ if (info.multisampled != 0) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Image 'MS' parameter to be 0";
|
|
|
+ }
|
|
|
|
|
|
- if (info.arrayed != 0) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image 'arrayed' parameter to be 0";
|
|
|
- }
|
|
|
+ if (info.arrayed != 0) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Image 'arrayed' parameter to be 0";
|
|
|
}
|
|
|
|
|
|
- if (opcode == SpvOpImageRead || opcode == SpvOpImageSparseRead ||
|
|
|
- opcode == SpvOpImageWrite) {
|
|
|
- if (info.sampled == 0) {
|
|
|
- } else if (info.sampled == 2) {
|
|
|
- if (info.dim == SpvDim1D && !_.HasCapability(SpvCapabilityImage1D)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Capability Image1D is required to access storage image";
|
|
|
- } else if (info.dim == SpvDimRect &&
|
|
|
- !_.HasCapability(SpvCapabilityImageRect)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Capability ImageRect is required to access storage image";
|
|
|
- } else if (info.dim == SpvDimBuffer &&
|
|
|
- !_.HasCapability(SpvCapabilityImageBuffer)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Capability ImageBuffer is required to access storage image";
|
|
|
- } else if (info.dim == SpvDimCube && info.arrayed == 1 &&
|
|
|
- !_.HasCapability(SpvCapabilityImageCubeArray)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Capability ImageCubeArray is required to access "
|
|
|
- << "storage image";
|
|
|
- }
|
|
|
+ return SPV_SUCCESS;
|
|
|
+}
|
|
|
|
|
|
- if (info.multisampled == 1 &&
|
|
|
- !_.HasCapability(SpvCapabilityImageMSArray)) {
|
|
|
+// Validate OpImage*Read and OpImage*Write instructions
|
|
|
+spv_result_t ValidateImageReadWrite(ValidationState_t& _,
|
|
|
+ const Instruction* inst,
|
|
|
+ const ImageTypeInfo& info) {
|
|
|
+ if (info.sampled == 2) {
|
|
|
+ if (info.dim == SpvDim1D && !_.HasCapability(SpvCapabilityImage1D)) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Capability Image1D is required to access storage image";
|
|
|
+ } else if (info.dim == SpvDimRect &&
|
|
|
+ !_.HasCapability(SpvCapabilityImageRect)) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Capability ImageRect is required to access storage image";
|
|
|
+ } else if (info.dim == SpvDimBuffer &&
|
|
|
+ !_.HasCapability(SpvCapabilityImageBuffer)) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Capability ImageBuffer is required to access storage image";
|
|
|
+ } else if (info.dim == SpvDimCube && info.arrayed == 1 &&
|
|
|
+ !_.HasCapability(SpvCapabilityImageCubeArray)) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Capability ImageCubeArray is required to access "
|
|
|
+ << "storage image";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (info.multisampled == 1 && !_.HasCapability(SpvCapabilityImageMSArray)) {
|
|
|
#if 0
|
|
|
- // TODO([email protected]) The description of this rule in the spec
|
|
|
- // is unclear and Glslang doesn't declare ImageMSArray. Need to clarify
|
|
|
- // and reenable.
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Capability ImageMSArray is required to access storage "
|
|
|
- << "image";
|
|
|
-#endif
|
|
|
- }
|
|
|
- } else {
|
|
|
+ // TODO([email protected]) The description of this rule in the spec
|
|
|
+ // is unclear and Glslang doesn't declare ImageMSArray. Need to clarify
|
|
|
+ // and reenable.
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image 'Sampled' parameter to be 0 or 2";
|
|
|
+ << "Capability ImageMSArray is required to access storage "
|
|
|
+ << "image";
|
|
|
+#endif
|
|
|
}
|
|
|
+ } else if (info.sampled != 0) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Image 'Sampled' parameter to be 0 or 2";
|
|
|
}
|
|
|
|
|
|
return SPV_SUCCESS;
|
|
|
@@ -813,7 +812,8 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Dim is checked elsewhere.
|
|
|
+ // Universal checks on image type operands
|
|
|
+ // Dim and Format and Access Qualifier are checked elsewhere.
|
|
|
|
|
|
if (info.depth > 2) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
@@ -825,70 +825,53 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
|
|
|
<< "Invalid Arrayed " << info.arrayed << " (must be 0 or 1)";
|
|
|
}
|
|
|
|
|
|
- if (spvIsOpenCLEnv(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(target_env)) {
|
|
|
- if (info.multisampled != 0) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "MS must be 0 in the OpenCL environment.";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
if (info.sampled > 2) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Invalid Sampled " << info.sampled << " (must be 0, 1 or 2)";
|
|
|
}
|
|
|
|
|
|
- if (spvIsVulkanEnv(target_env)) {
|
|
|
- if (info.sampled == 0) {
|
|
|
+ if (info.dim == SpvDimSubpassData) {
|
|
|
+ if (info.sampled != 2) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << _.VkErrorID(4657)
|
|
|
- << "Sampled must be 1 or 2 in the Vulkan environment.";
|
|
|
+ << _.VkErrorID(6214) << "Dim SubpassData requires Sampled to be 2";
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- if (spvIsOpenCLEnv(_.context()->target_env)) {
|
|
|
- if (info.sampled != 0) {
|
|
|
+ if (info.format != SpvImageFormatUnknown) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Sampled must be 0 in the OpenCL environment.";
|
|
|
+ << "Dim SubpassData requires format Unknown";
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (info.multisampled && (info.sampled == 2) &&
|
|
|
+ !_.HasCapability(SpvCapabilityStorageImageMultisample)) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Capability StorageImageMultisample is required when using "
|
|
|
+ "multisampled storage image";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (info.dim == SpvDimSubpassData) {
|
|
|
- if (info.sampled != 2) {
|
|
|
+ if (spvIsOpenCLEnv(target_env)) {
|
|
|
+ if ((info.arrayed == 1) && (info.dim != SpvDim1D) &&
|
|
|
+ (info.dim != SpvDim2D)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << _.VkErrorID(6214) << "Dim SubpassData requires Sampled to be 2";
|
|
|
+ << "In the OpenCL environment, Arrayed may only be set to 1 "
|
|
|
+ << "when Dim is either 1D or 2D.";
|
|
|
}
|
|
|
|
|
|
- if (info.format != SpvImageFormatUnknown) {
|
|
|
+ if (info.multisampled != 0) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Dim SubpassData requires format Unknown";
|
|
|
+ << "MS must be 0 in the OpenCL environment.";
|
|
|
}
|
|
|
|
|
|
- if (spvIsVulkanEnv(target_env)) {
|
|
|
- if (info.arrayed != 0) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << _.VkErrorID(6214)
|
|
|
- << "Dim SubpassData requires Arrayed to be 0";
|
|
|
- }
|
|
|
+ if (info.sampled != 0) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Sampled must be 0 in the OpenCL environment.";
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
- // 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"
|
|
|
@@ -896,12 +879,16 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (info.multisampled && (info.sampled == 2) &&
|
|
|
- (info.dim != SpvDimSubpassData)) {
|
|
|
- if (!_.HasCapability(SpvCapabilityStorageImageMultisample)) {
|
|
|
+ if (spvIsVulkanEnv(target_env)) {
|
|
|
+ if (info.sampled == 0) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Capability StorageImageMultisample is required when using "
|
|
|
- "multisampled storage image";
|
|
|
+ << _.VkErrorID(4657)
|
|
|
+ << "Sampled must be 1 or 2 in the Vulkan environment.";
|
|
|
+ }
|
|
|
+
|
|
|
+ if (info.dim == SpvDimSubpassData && info.arrayed != 0) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << _.VkErrorID(6214) << "Dim SubpassData requires Arrayed to be 0";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1213,7 +1200,9 @@ spv_result_t ValidateImageLod(ValidationState_t& _, const Instruction* inst) {
|
|
|
<< "Corrupt image type definition";
|
|
|
}
|
|
|
|
|
|
- if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
|
|
|
+ if (IsProj(opcode)) {
|
|
|
+ if (spv_result_t result = ValidateImageProj(_, inst, info)) return result;
|
|
|
+ }
|
|
|
|
|
|
if (info.multisampled) {
|
|
|
// When using image operands, the Sample image operand is required if and
|
|
|
@@ -1324,7 +1313,9 @@ spv_result_t ValidateImageDrefLod(ValidationState_t& _,
|
|
|
<< "Corrupt image type definition";
|
|
|
}
|
|
|
|
|
|
- if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
|
|
|
+ if (IsProj(opcode)) {
|
|
|
+ if (spv_result_t result = ValidateImageProj(_, inst, info)) return result;
|
|
|
+ }
|
|
|
|
|
|
if (info.multisampled) {
|
|
|
// When using image operands, the Sample image operand is required if and
|
|
|
@@ -1594,6 +1585,13 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
|
|
|
<< " to have 4 components";
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
|
|
|
+ if (mask & SpvImageOperandsConstOffsetMask) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "ConstOffset image operand not allowed "
|
|
|
+ << "in the OpenCL environment.";
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (info.dim == SpvDimSubpassData) {
|
|
|
@@ -1619,7 +1617,8 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
|
|
|
+ if (spv_result_t result = ValidateImageReadWrite(_, inst, info))
|
|
|
+ return result;
|
|
|
|
|
|
const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
|
|
|
if (!_.IsIntScalarOrVectorType(coord_type)) {
|
|
|
@@ -1644,16 +1643,6 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
|
|
|
-
|
|
|
- if (mask & SpvImageOperandsConstOffsetMask) {
|
|
|
- if (spvIsOpenCLEnv(_.context()->target_env)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "ConstOffset image operand not allowed "
|
|
|
- << "in the OpenCL environment.";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
if (spv_result_t result =
|
|
|
ValidateImageOperands(_, inst, info, /* word_index = */ 6))
|
|
|
return result;
|
|
|
@@ -1679,7 +1668,8 @@ spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) {
|
|
|
<< "Image 'Dim' cannot be SubpassData";
|
|
|
}
|
|
|
|
|
|
- if (spv_result_t result = ValidateImageCommon(_, inst, info)) return result;
|
|
|
+ if (spv_result_t result = ValidateImageReadWrite(_, inst, info))
|
|
|
+ return result;
|
|
|
|
|
|
const uint32_t coord_type = _.GetOperandTypeId(inst, 1);
|
|
|
if (!_.IsIntScalarOrVectorType(coord_type)) {
|