|
|
@@ -237,6 +237,23 @@ uint32_t GetMinCoordSize(spv::Op opcode, const ImageTypeInfo& info) {
|
|
|
return 3;
|
|
|
}
|
|
|
|
|
|
+ if (opcode == spv::Op::OpImageQueryLod) {
|
|
|
+ return GetPlaneCoordSize(info);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (opcode == spv::Op::OpImageTexelPointer) {
|
|
|
+ if (info.arrayed == 0) {
|
|
|
+ return GetPlaneCoordSize(info);
|
|
|
+ } else if (info.dim == spv::Dim::Dim1D) {
|
|
|
+ return 2;
|
|
|
+ } else if (info.dim == spv::Dim::Cube || info.dim == spv::Dim::Dim2D) {
|
|
|
+ return 3;
|
|
|
+ } else {
|
|
|
+ assert(false);
|
|
|
+ return 0; // caught elsewhere
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return GetPlaneCoordSize(info) + info.arrayed + (IsProj(opcode) ? 1 : 0);
|
|
|
}
|
|
|
|
|
|
@@ -314,10 +331,10 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
<< "Image Operand Bias can only be used with ImplicitLod opcodes";
|
|
|
}
|
|
|
|
|
|
- const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
- if (!_.IsFloatScalarType(type_id)) {
|
|
|
+ const uint32_t bias_type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
+ if (!_.IsFloatScalarType(bias_type_id, 32)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image Operand Bias to be float scalar";
|
|
|
+ << "Expected Image Operand Bias to be a 32-bit float scalar";
|
|
|
}
|
|
|
|
|
|
if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
|
|
|
@@ -327,7 +344,10 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
"or Cube";
|
|
|
}
|
|
|
|
|
|
- // Multisampled is already checked.
|
|
|
+ // - |Sample| operand is required to have MS != 0
|
|
|
+ // - |Sample| is only allowed with [Fetch, Write, or Read]
|
|
|
+ // - |Bias| can only be used with |ImplicitLod| opcodes
|
|
|
+ // Multisampled is already checked in all cases
|
|
|
}
|
|
|
|
|
|
if (mask & uint32_t(spv::ImageOperandsMask::Lod)) {
|
|
|
@@ -345,17 +365,19 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
"time";
|
|
|
}
|
|
|
|
|
|
- const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
+ const uint32_t lod_type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
if (is_explicit_lod || is_valid_gather_lod_bias_amd) {
|
|
|
- if (!_.IsFloatScalarType(type_id)) {
|
|
|
+ if (!_.IsFloatScalarType(lod_type_id, 32)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image Operand Lod to be float scalar when used "
|
|
|
+ << "Expected Image Operand Lod to be a 32-bit float scalar when "
|
|
|
+ "used "
|
|
|
<< "with ExplicitLod";
|
|
|
}
|
|
|
} else {
|
|
|
- if (!_.IsIntScalarType(type_id)) {
|
|
|
+ if (!_.IsIntScalarType(lod_type_id, 32)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image Operand Lod to be int scalar when used with "
|
|
|
+ << "Expected Image Operand Lod to be a 32-bit int scalar when "
|
|
|
+ "used with "
|
|
|
<< "OpImageFetch";
|
|
|
}
|
|
|
}
|
|
|
@@ -367,7 +389,10 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
"or Cube";
|
|
|
}
|
|
|
|
|
|
- // Multisampled is already checked.
|
|
|
+ if (info.multisampled != 0) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Image Operand Lod requires 'MS' parameter to be 0";
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (mask & uint32_t(spv::ImageOperandsMask::Grad)) {
|
|
|
@@ -379,9 +404,12 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
const uint32_t dx_type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
const uint32_t dy_type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
if (!_.IsFloatScalarOrVectorType(dx_type_id) ||
|
|
|
- !_.IsFloatScalarOrVectorType(dy_type_id)) {
|
|
|
+ _.GetBitWidth(dx_type_id) != 32 ||
|
|
|
+ !_.IsFloatScalarOrVectorType(dy_type_id) ||
|
|
|
+ _.GetBitWidth(dy_type_id) != 32) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected both Image Operand Grad ids to be float scalars or "
|
|
|
+ << "Expected both Image Operand Grad ids to be 32-bit float "
|
|
|
+ "scalars or "
|
|
|
<< "vectors";
|
|
|
}
|
|
|
|
|
|
@@ -400,7 +428,10 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
<< " components, but given " << dy_size;
|
|
|
}
|
|
|
|
|
|
- // Multisampled is already checked.
|
|
|
+ // - |Sample| operand is required to have MS != 0
|
|
|
+ // - |Sample| is only allowed with [Fetch, Write, or Read]
|
|
|
+ // - |Grad| can only be used with |ExplicitLod| opcodes
|
|
|
+ // Multisampled is already checked in all cases
|
|
|
}
|
|
|
|
|
|
if (mask & uint32_t(spv::ImageOperandsMask::ConstOffset)) {
|
|
|
@@ -410,21 +441,23 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
"'Dim'";
|
|
|
}
|
|
|
|
|
|
- const uint32_t id = inst->word(word_index++);
|
|
|
- const uint32_t type_id = _.GetTypeId(id);
|
|
|
- if (!_.IsIntScalarOrVectorType(type_id)) {
|
|
|
+ const uint32_t offset_id = inst->word(word_index++);
|
|
|
+ const uint32_t offset_type_id = _.GetTypeId(offset_id);
|
|
|
+ if (!_.IsIntScalarOrVectorType(offset_type_id) ||
|
|
|
+ _.GetBitWidth(offset_type_id) != 32) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image Operand ConstOffset to be int scalar or "
|
|
|
+ << "Expected Image Operand ConstOffset to be a 32-bit int scalar "
|
|
|
+ "or "
|
|
|
<< "vector";
|
|
|
}
|
|
|
|
|
|
- if (!spvOpcodeIsConstant(_.GetIdOpcode(id))) {
|
|
|
+ if (!spvOpcodeIsConstant(_.GetIdOpcode(offset_id))) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Expected Image Operand ConstOffset to be a const object";
|
|
|
}
|
|
|
|
|
|
const uint32_t plane_size = GetPlaneCoordSize(info);
|
|
|
- const uint32_t offset_size = _.GetDimension(type_id);
|
|
|
+ const uint32_t offset_size = _.GetDimension(offset_type_id);
|
|
|
if (plane_size != offset_size) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Expected Image Operand ConstOffset to have " << plane_size
|
|
|
@@ -438,16 +471,17 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
<< "Image Operand Offset cannot be used with Cube Image 'Dim'";
|
|
|
}
|
|
|
|
|
|
- const uint32_t id = inst->word(word_index++);
|
|
|
- const uint32_t type_id = _.GetTypeId(id);
|
|
|
- if (!_.IsIntScalarOrVectorType(type_id)) {
|
|
|
+ const uint32_t offset_id = inst->word(word_index++);
|
|
|
+ const uint32_t offset_type_id = _.GetTypeId(offset_id);
|
|
|
+ if (!_.IsIntScalarOrVectorType(offset_type_id) ||
|
|
|
+ _.GetBitWidth(offset_type_id) != 32) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image Operand Offset to be int scalar or "
|
|
|
+ << "Expected Image Operand Offset to be a 32-bit int scalar or "
|
|
|
<< "vector";
|
|
|
}
|
|
|
|
|
|
const uint32_t plane_size = GetPlaneCoordSize(info);
|
|
|
- const uint32_t offset_size = _.GetDimension(type_id);
|
|
|
+ const uint32_t offset_size = _.GetDimension(offset_type_id);
|
|
|
if (plane_size != offset_size) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Expected Image Operand Offset to have " << plane_size
|
|
|
@@ -487,9 +521,9 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
"'Dim'";
|
|
|
}
|
|
|
|
|
|
- const uint32_t id = inst->word(word_index++);
|
|
|
- const uint32_t type_id = _.GetTypeId(id);
|
|
|
- const Instruction* type_inst = _.FindDef(type_id);
|
|
|
+ const uint32_t offset_id = inst->word(word_index++);
|
|
|
+ const uint32_t offset_type_id = _.GetTypeId(offset_id);
|
|
|
+ const Instruction* type_inst = _.FindDef(offset_type_id);
|
|
|
assert(type_inst);
|
|
|
|
|
|
if (type_inst->opcode() != spv::Op::OpTypeArray) {
|
|
|
@@ -509,13 +543,14 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
|
|
|
const uint32_t component_type = type_inst->word(2);
|
|
|
if (!_.IsIntVectorType(component_type) ||
|
|
|
- _.GetDimension(component_type) != 2) {
|
|
|
+ _.GetDimension(component_type) != 2 ||
|
|
|
+ _.GetBitWidth(component_type) != 32) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image Operand ConstOffsets array components to be "
|
|
|
- "int vectors of size 2";
|
|
|
+ << "Expected Image Operand ConstOffsets array components to be a "
|
|
|
+ "32-bit int vectors of size 2";
|
|
|
}
|
|
|
|
|
|
- if (!spvOpcodeIsConstant(_.GetIdOpcode(id))) {
|
|
|
+ if (!spvOpcodeIsConstant(_.GetIdOpcode(offset_id))) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Expected Image Operand ConstOffsets to be a const object";
|
|
|
}
|
|
|
@@ -537,10 +572,10 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
<< "Image Operand Sample requires non-zero 'MS' parameter";
|
|
|
}
|
|
|
|
|
|
- const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
- if (!_.IsIntScalarType(type_id)) {
|
|
|
+ const uint32_t sample_type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
+ if (!_.IsIntScalarType(sample_type_id, 32)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image Operand Sample to be int scalar";
|
|
|
+ << "Expected Image Operand Sample to be a 32-bit int scalar";
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -551,10 +586,10 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
|
|
|
<< "opcodes or together with Image Operand Grad";
|
|
|
}
|
|
|
|
|
|
- const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
- if (!_.IsFloatScalarType(type_id)) {
|
|
|
+ const uint32_t minlod_type_id = _.GetTypeId(inst->word(word_index++));
|
|
|
+ if (!_.IsFloatScalarType(minlod_type_id, 32)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image Operand MinLod to be float scalar";
|
|
|
+ << "Expected Image Operand MinLod to be a 32-bit float scalar";
|
|
|
}
|
|
|
|
|
|
if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
|
|
|
@@ -782,8 +817,7 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
|
|
|
<< "Corrupt image type definition";
|
|
|
}
|
|
|
|
|
|
- if (_.IsIntScalarType(info.sampled_type) &&
|
|
|
- (64 == _.GetBitWidth(info.sampled_type)) &&
|
|
|
+ if (_.IsIntScalarType(info.sampled_type, 64) &&
|
|
|
!_.HasCapability(spv::Capability::Int64ImageEXT)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Capability Int64ImageEXT is required when using Sampled Type of "
|
|
|
@@ -792,12 +826,9 @@ spv_result_t ValidateTypeImage(ValidationState_t& _, const Instruction* inst) {
|
|
|
|
|
|
const auto target_env = _.context()->target_env;
|
|
|
if (spvIsVulkanEnv(target_env)) {
|
|
|
- if ((!_.IsFloatScalarType(info.sampled_type) &&
|
|
|
- !_.IsIntScalarType(info.sampled_type)) ||
|
|
|
- ((32 != _.GetBitWidth(info.sampled_type)) &&
|
|
|
- (64 != _.GetBitWidth(info.sampled_type))) ||
|
|
|
- ((64 == _.GetBitWidth(info.sampled_type)) &&
|
|
|
- _.IsFloatScalarType(info.sampled_type))) {
|
|
|
+ if (!_.IsFloatScalarType(info.sampled_type, 32) &&
|
|
|
+ !_.IsIntScalarType(info.sampled_type, 32) &&
|
|
|
+ !_.IsIntScalarType(info.sampled_type, 64)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< _.VkErrorID(4656)
|
|
|
<< "Expected Sampled Type to be a 32-bit int, 64-bit int or "
|
|
|
@@ -1007,6 +1038,82 @@ bool IsAllowedSampledImageOperand(spv::Op opcode, ValidationState_t& _) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+spv_result_t ValidateImageCoordinate(ValidationState_t& _,
|
|
|
+ const Instruction* inst,
|
|
|
+ const ImageTypeInfo& info,
|
|
|
+ uint32_t word_index) {
|
|
|
+ const spv::Op opcode = inst->opcode();
|
|
|
+ const uint32_t coord_type = _.GetOperandTypeId(inst, word_index);
|
|
|
+
|
|
|
+ const bool float_only =
|
|
|
+ opcode == spv::Op::OpImageSampleImplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSampleDrefImplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSampleDrefExplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSampleProjImplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSampleProjExplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSampleProjDrefImplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSampleProjDrefExplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageGather ||
|
|
|
+ opcode == spv::Op::OpImageDrefGather ||
|
|
|
+ opcode == spv::Op::OpImageQueryLod ||
|
|
|
+ opcode == spv::Op::OpImageSparseSampleImplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSparseSampleDrefImplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSparseSampleDrefExplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSparseGather ||
|
|
|
+ opcode == spv::Op::OpImageSparseDrefGather;
|
|
|
+
|
|
|
+ const bool int_only = opcode == spv::Op::OpImageFetch ||
|
|
|
+ opcode == spv::Op::OpImageSparseFetch ||
|
|
|
+ opcode == spv::Op::OpImageTexelPointer ||
|
|
|
+ opcode == spv::Op::OpUntypedImageTexelPointerEXT;
|
|
|
+
|
|
|
+ const bool int_or_float = opcode == spv::Op::OpImageSampleExplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageSparseSampleExplicitLod ||
|
|
|
+ opcode == spv::Op::OpImageRead ||
|
|
|
+ opcode == spv::Op::OpImageWrite ||
|
|
|
+ opcode == spv::Op::OpImageSparseRead;
|
|
|
+
|
|
|
+ assert(float_only || int_only || int_or_float);
|
|
|
+
|
|
|
+ if (float_only && !_.IsFloatScalarOrVectorType(coord_type)) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Coordinate to be a 32-bit float scalar or vector";
|
|
|
+ } else if (int_only && !_.IsIntScalarOrVectorType(coord_type)) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Coordinate to be a 32-bit integer scalar or vector";
|
|
|
+ } else if (int_or_float) {
|
|
|
+ if (!_.IsFloatScalarOrVectorType(coord_type) &&
|
|
|
+ !_.IsIntScalarOrVectorType(coord_type)) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Coordinate to be a 32-bit integer or float scalar or "
|
|
|
+ "vector";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Needs to be after we validate the scalar/vector
|
|
|
+ if (_.GetBitWidth(coord_type) != 32) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Coordinate to be a 32-bit scalar or vector";
|
|
|
+ }
|
|
|
+
|
|
|
+ const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
|
|
|
+ const uint32_t actual_coord_size = _.GetDimension(coord_type);
|
|
|
+
|
|
|
+ if (opcode == spv::Op::OpImageTexelPointer) {
|
|
|
+ if (min_coord_size != actual_coord_size) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Coordinate to have " << min_coord_size
|
|
|
+ << " components, but given " << actual_coord_size;
|
|
|
+ }
|
|
|
+ } else if (min_coord_size > actual_coord_size) {
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << "Expected Coordinate to have at least " << min_coord_size
|
|
|
+ << " components, but given only " << actual_coord_size;
|
|
|
+ }
|
|
|
+
|
|
|
+ return SPV_SUCCESS;
|
|
|
+}
|
|
|
+
|
|
|
spv_result_t ValidateSampledImage(ValidationState_t& _,
|
|
|
const Instruction* inst) {
|
|
|
auto type_inst = _.FindDef(inst->type_id());
|
|
|
@@ -1135,6 +1242,8 @@ spv_result_t ValidateSampledImage(ValidationState_t& _,
|
|
|
|
|
|
spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
|
|
|
const Instruction* inst) {
|
|
|
+ bool isUntyped = (inst->opcode() == spv::Op::OpUntypedImageTexelPointerEXT);
|
|
|
+
|
|
|
const auto result_type = _.FindDef(inst->type_id());
|
|
|
if (result_type->opcode() != spv::Op::OpTypePointer &&
|
|
|
result_type->opcode() != spv::Op::OpTypeUntypedPointerKHR) {
|
|
|
@@ -1165,16 +1274,23 @@ spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const auto image_ptr = _.FindDef(_.GetOperandTypeId(inst, 2));
|
|
|
- if (!image_ptr || image_ptr->opcode() != spv::Op::OpTypePointer) {
|
|
|
+ const auto image_ptr =
|
|
|
+ _.FindDef(_.GetOperandTypeId(inst, (isUntyped ? 3 : 2)));
|
|
|
+ if (!image_ptr ||
|
|
|
+ (isUntyped && image_ptr->opcode() != spv::Op::OpTypeUntypedPointerKHR) ||
|
|
|
+ (!isUntyped && image_ptr->opcode() != spv::Op::OpTypePointer)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image to be OpTypePointer";
|
|
|
+ << "Expected Image to be "
|
|
|
+ << (isUntyped ? "OpTypeUntypedPointerKHR" : "OpTypePointer");
|
|
|
}
|
|
|
|
|
|
- const auto image_type = image_ptr->GetOperandAs<uint32_t>(2);
|
|
|
+ const auto image_type = isUntyped ? inst->GetOperandAs<uint32_t>(2)
|
|
|
+ : image_ptr->GetOperandAs<uint32_t>(2);
|
|
|
if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image to be OpTypePointer with Type OpTypeImage";
|
|
|
+ << "Expected Image to be "
|
|
|
+ << (isUntyped ? "OpTypeUntypedPointerKHR" : "OpTypePointer ")
|
|
|
+ << "with Type OpTypeImage";
|
|
|
}
|
|
|
|
|
|
ImageTypeInfo info;
|
|
|
@@ -1199,49 +1315,23 @@ spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
|
|
|
|
|
|
if (info.dim == spv::Dim::SubpassData) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Image Dim SubpassData cannot be used with OpImageTexelPointer";
|
|
|
+ << "Image Dim SubpassData cannot be used with "
|
|
|
+ << (isUntyped ? "OpUntypedImageTexelPointerEXT"
|
|
|
+ : "OpImageTexelPointer");
|
|
|
}
|
|
|
|
|
|
if (info.dim == spv::Dim::TileImageDataEXT) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Image Dim TileImageDataEXT cannot be used with "
|
|
|
- "OpImageTexelPointer";
|
|
|
+ << (isUntyped ? "OpUntypedImageTexelPointerEXT"
|
|
|
+ : "OpImageTexelPointer");
|
|
|
}
|
|
|
|
|
|
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
|
|
|
- if (!coord_type || !_.IsIntScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be integer scalar or vector";
|
|
|
- }
|
|
|
-
|
|
|
- uint32_t expected_coord_size = 0;
|
|
|
- if (info.arrayed == 0) {
|
|
|
- expected_coord_size = GetPlaneCoordSize(info);
|
|
|
- } else if (info.arrayed == 1) {
|
|
|
- switch (info.dim) {
|
|
|
- case spv::Dim::Dim1D:
|
|
|
- expected_coord_size = 2;
|
|
|
- break;
|
|
|
- case spv::Dim::Cube:
|
|
|
- case spv::Dim::Dim2D:
|
|
|
- expected_coord_size = 3;
|
|
|
- break;
|
|
|
- default:
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Image 'Dim' must be one of 1D, 2D, or Cube when "
|
|
|
- "Arrayed is 1";
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
|
|
|
- if (expected_coord_size != actual_coord_size) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to have " << expected_coord_size
|
|
|
- << " components, but given " << actual_coord_size;
|
|
|
- }
|
|
|
+ if (spv_result_t result = ValidateImageCoordinate(
|
|
|
+ _, inst, info, /* word_index = */ (isUntyped ? 4 : 3)))
|
|
|
+ return result;
|
|
|
|
|
|
- const uint32_t sample_type = _.GetOperandTypeId(inst, 4);
|
|
|
+ const uint32_t sample_type = _.GetOperandTypeId(inst, (isUntyped ? 5 : 4));
|
|
|
if (!sample_type || !_.IsIntScalarType(sample_type)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Expected Sample to be integer scalar";
|
|
|
@@ -1249,7 +1339,8 @@ spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
|
|
|
|
|
|
if (info.multisampled == 0) {
|
|
|
uint64_t ms = 0;
|
|
|
- if (!_.EvalConstantValUint64(inst->GetOperandAs<uint32_t>(4), &ms) ||
|
|
|
+ if (!_.EvalConstantValUint64(
|
|
|
+ inst->GetOperandAs<uint32_t>(isUntyped ? 5 : 4), &ms) ||
|
|
|
ms != 0) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Expected Sample for Image with MS 0 to be a valid <id> for "
|
|
|
@@ -1258,18 +1349,24 @@ spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
|
|
|
}
|
|
|
|
|
|
if (spvIsVulkanEnv(_.context()->target_env)) {
|
|
|
- if ((info.format != spv::ImageFormat::R64i) &&
|
|
|
- (info.format != spv::ImageFormat::R64ui) &&
|
|
|
- (info.format != spv::ImageFormat::R32f) &&
|
|
|
- (info.format != spv::ImageFormat::R32i) &&
|
|
|
- (info.format != spv::ImageFormat::R32ui) &&
|
|
|
- !((info.format == spv::ImageFormat::Rg16f ||
|
|
|
- info.format == spv::ImageFormat::Rgba16f) &&
|
|
|
- _.HasCapability(spv::Capability::AtomicFloat16VectorNV))) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << _.VkErrorID(4658)
|
|
|
+ bool valid_format = info.format == spv::ImageFormat::R64i ||
|
|
|
+ info.format == spv::ImageFormat::R64ui ||
|
|
|
+ info.format == spv::ImageFormat::R32f ||
|
|
|
+ info.format == spv::ImageFormat::R32i ||
|
|
|
+ info.format == spv::ImageFormat::R32ui;
|
|
|
+ if (!valid_format &&
|
|
|
+ _.HasCapability(spv::Capability::AtomicFloat16VectorNV)) {
|
|
|
+ valid_format = info.format == spv::ImageFormat::Rg16f ||
|
|
|
+ info.format == spv::ImageFormat::Rgba16f;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!valid_format) {
|
|
|
+ const uint32_t vuid = isUntyped ? 11416 : 4658;
|
|
|
+ return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
+ << _.VkErrorID(vuid)
|
|
|
<< "Expected the Image Format in Image to be R64i, R64ui, R32f, "
|
|
|
- "R32i, or R32ui for Vulkan environment";
|
|
|
+ "R32i, or R32ui for Vulkan environment using Op"
|
|
|
+ << spvOpcodeString(inst->opcode());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1330,29 +1427,9 @@ spv_result_t ValidateImageLod(ValidationState_t& _, const Instruction* inst) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
|
|
|
- if ((opcode == spv::Op::OpImageSampleExplicitLod ||
|
|
|
- opcode == spv::Op::OpImageSparseSampleExplicitLod) &&
|
|
|
- _.HasCapability(spv::Capability::Kernel)) {
|
|
|
- if (!_.IsFloatScalarOrVectorType(coord_type) &&
|
|
|
- !_.IsIntScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be int or float scalar or vector";
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (!_.IsFloatScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be float scalar or vector";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
|
|
|
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
|
|
|
- if (min_coord_size > actual_coord_size) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to have at least " << min_coord_size
|
|
|
- << " components, but given only " << actual_coord_size;
|
|
|
- }
|
|
|
+ if (spv_result_t result =
|
|
|
+ ValidateImageCoordinate(_, inst, info, /* word_index = */ 3))
|
|
|
+ return result;
|
|
|
|
|
|
const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
|
|
|
|
|
|
@@ -1377,7 +1454,7 @@ spv_result_t ValidateImageLod(ValidationState_t& _, const Instruction* inst) {
|
|
|
spv_result_t ValidateImageDref(ValidationState_t& _, const Instruction* inst,
|
|
|
const ImageTypeInfo& info) {
|
|
|
const uint32_t dref_type = _.GetOperandTypeId(inst, 4);
|
|
|
- if (!_.IsFloatScalarType(dref_type) || _.GetBitWidth(dref_type) != 32) {
|
|
|
+ if (!_.IsFloatScalarType(dref_type, 32)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Expected Dref to be of 32-bit float type";
|
|
|
}
|
|
|
@@ -1439,19 +1516,9 @@ spv_result_t ValidateImageDrefLod(ValidationState_t& _,
|
|
|
<< GetActualResultTypeStr(opcode);
|
|
|
}
|
|
|
|
|
|
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
|
|
|
- if (!_.IsFloatScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be float scalar or vector";
|
|
|
- }
|
|
|
-
|
|
|
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
|
|
|
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
|
|
|
- if (min_coord_size > actual_coord_size) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to have at least " << min_coord_size
|
|
|
- << " components, but given only " << actual_coord_size;
|
|
|
- }
|
|
|
+ if (spv_result_t result =
|
|
|
+ ValidateImageCoordinate(_, inst, info, /* word_index = */ 3))
|
|
|
+ return result;
|
|
|
|
|
|
if (spv_result_t result = ValidateImageDref(_, inst, info)) return result;
|
|
|
|
|
|
@@ -1513,19 +1580,9 @@ spv_result_t ValidateImageFetch(ValidationState_t& _, const Instruction* inst) {
|
|
|
<< "Expected Image 'Sampled' parameter to be 1";
|
|
|
}
|
|
|
|
|
|
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
|
|
|
- if (!_.IsIntScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be int scalar or vector";
|
|
|
- }
|
|
|
-
|
|
|
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
|
|
|
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
|
|
|
- if (min_coord_size > actual_coord_size) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to have at least " << min_coord_size
|
|
|
- << " components, but given only " << actual_coord_size;
|
|
|
- }
|
|
|
+ if (spv_result_t result =
|
|
|
+ ValidateImageCoordinate(_, inst, info, /* word_index = */ 3))
|
|
|
+ return result;
|
|
|
|
|
|
if (spv_result_t result =
|
|
|
ValidateImageOperands(_, inst, info, /* word_index = */ 6))
|
|
|
@@ -1593,26 +1650,15 @@ spv_result_t ValidateImageGather(ValidationState_t& _,
|
|
|
<< "Expected Image 'Dim' to be 2D, Cube, or Rect";
|
|
|
}
|
|
|
|
|
|
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
|
|
|
- if (!_.IsFloatScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be float scalar or vector";
|
|
|
- }
|
|
|
-
|
|
|
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
|
|
|
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
|
|
|
- if (min_coord_size > actual_coord_size) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to have at least " << min_coord_size
|
|
|
- << " components, but given only " << actual_coord_size;
|
|
|
- }
|
|
|
+ if (spv_result_t result =
|
|
|
+ ValidateImageCoordinate(_, inst, info, /* word_index = */ 3))
|
|
|
+ return result;
|
|
|
|
|
|
if (opcode == spv::Op::OpImageGather ||
|
|
|
opcode == spv::Op::OpImageSparseGather) {
|
|
|
const uint32_t component = inst->GetOperandAs<uint32_t>(4);
|
|
|
const uint32_t component_index_type = _.GetTypeId(component);
|
|
|
- if (!_.IsIntScalarType(component_index_type) ||
|
|
|
- _.GetBitWidth(component_index_type) != 32) {
|
|
|
+ if (!_.IsIntScalarType(component_index_type, 32)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
<< "Expected Component to be 32-bit int scalar";
|
|
|
}
|
|
|
@@ -1736,19 +1782,9 @@ spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
|
|
|
if (spv_result_t result = ValidateImageReadWrite(_, inst, info))
|
|
|
return result;
|
|
|
|
|
|
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
|
|
|
- if (!_.IsIntScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be int scalar or vector";
|
|
|
- }
|
|
|
-
|
|
|
- const uint32_t min_coord_size = GetMinCoordSize(opcode, info);
|
|
|
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
|
|
|
- if (min_coord_size > actual_coord_size) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to have at least " << min_coord_size
|
|
|
- << " components, but given only " << actual_coord_size;
|
|
|
- }
|
|
|
+ if (spv_result_t result =
|
|
|
+ ValidateImageCoordinate(_, inst, info, /* word_index = */ 3))
|
|
|
+ return result;
|
|
|
|
|
|
if (spvIsVulkanEnv(_.context()->target_env)) {
|
|
|
if (info.format == spv::ImageFormat::Unknown &&
|
|
|
@@ -1793,19 +1829,9 @@ spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) {
|
|
|
if (spv_result_t result = ValidateImageReadWrite(_, inst, info))
|
|
|
return result;
|
|
|
|
|
|
- const uint32_t coord_type = _.GetOperandTypeId(inst, 1);
|
|
|
- if (!_.IsIntScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be int scalar or vector";
|
|
|
- }
|
|
|
-
|
|
|
- const uint32_t min_coord_size = GetMinCoordSize(inst->opcode(), info);
|
|
|
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
|
|
|
- if (min_coord_size > actual_coord_size) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to have at least " << min_coord_size
|
|
|
- << " components, but given only " << actual_coord_size;
|
|
|
- }
|
|
|
+ if (spv_result_t result =
|
|
|
+ ValidateImageCoordinate(_, inst, info, /* word_index = */ 1))
|
|
|
+ return result;
|
|
|
|
|
|
// because it needs to match with 'Sampled Type' the Texel can't be a boolean
|
|
|
const uint32_t texel_type = _.GetOperandTypeId(inst, 2);
|
|
|
@@ -1933,9 +1959,9 @@ spv_result_t ValidateImageQuerySizeLod(ValidationState_t& _,
|
|
|
}
|
|
|
|
|
|
const uint32_t lod_type = _.GetOperandTypeId(inst, 3);
|
|
|
- if (!_.IsIntScalarType(lod_type)) {
|
|
|
+ if (!_.IsIntScalarType(lod_type, 32)) {
|
|
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Level of Detail to be int scalar";
|
|
|
+ << "Expected Level of Detail to be a 32-bit int scalar";
|
|
|
}
|
|
|
return SPV_SUCCESS;
|
|
|
}
|
|
|
@@ -2096,27 +2122,9 @@ spv_result_t ValidateImageQueryLod(ValidationState_t& _,
|
|
|
<< "Image 'Dim' must be 1D, 2D, 3D or Cube";
|
|
|
}
|
|
|
|
|
|
- const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
|
|
|
- if (_.HasCapability(spv::Capability::Kernel)) {
|
|
|
- if (!_.IsFloatScalarOrVectorType(coord_type) &&
|
|
|
- !_.IsIntScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be int or float scalar or vector";
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (!_.IsFloatScalarOrVectorType(coord_type)) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to be float scalar or vector";
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const uint32_t min_coord_size = GetPlaneCoordSize(info);
|
|
|
- const uint32_t actual_coord_size = _.GetDimension(coord_type);
|
|
|
- if (min_coord_size > actual_coord_size) {
|
|
|
- return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
|
|
- << "Expected Coordinate to have at least " << min_coord_size
|
|
|
- << " components, but given only " << actual_coord_size;
|
|
|
- }
|
|
|
+ if (spv_result_t result =
|
|
|
+ ValidateImageCoordinate(_, inst, info, /* word_index = */ 3))
|
|
|
+ return result;
|
|
|
|
|
|
// The operand is a sampled image.
|
|
|
// The sampled image type is already checked to be parameterized by an image
|
|
|
@@ -2381,6 +2389,7 @@ spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst) {
|
|
|
case spv::Op::OpSampledImage:
|
|
|
return ValidateSampledImage(_, inst);
|
|
|
case spv::Op::OpImageTexelPointer:
|
|
|
+ case spv::Op::OpUntypedImageTexelPointerEXT:
|
|
|
return ValidateImageTexelPointer(_, inst);
|
|
|
|
|
|
case spv::Op::OpImageSampleImplicitLod:
|