spirv-val: Combine Image Coordinate checks (#6494)
This originally came out of
https://gitlab.khronos.org/spirv/SPIR-V/-/issues/905 where we found a
driver that crashed passing it 16-bit floats as the coordinate
I tried to combine the logic and went through each type ... I am not
sure why/if there is a difference between Vulkan/OpenCL with respect to
allowing Float vs Int (but found 1 that we have active tests for
https://gitlab.khronos.org/spirv/SPIR-V/-/issues/908) ... the other is
`OpImageRead`/`OpImageWrite`, those were being validated incorrectly
according to the spec
diff --git a/source/opt/convert_to_half_pass.cpp b/source/opt/convert_to_half_pass.cpp
index 77558c7..a3527ff 100644
--- a/source/opt/convert_to_half_pass.cpp
+++ b/source/opt/convert_to_half_pass.cpp
@@ -22,6 +22,7 @@
namespace opt {
namespace {
// Indices of operands in SPIR-V instructions
+constexpr int kImageSampleCoordinateIdInIdx = 1;
constexpr int kImageSampleDrefIdInIdx = 2;
} // namespace
@@ -325,7 +326,7 @@
bool ConvertToHalfPass::ProcessImageRef(Instruction* inst) {
bool modified = false;
- // If image reference, only need to convert dref args back to float32
+ // If image reference, some operands aren't allowed to be non-32 bit floats
if (dref_image_ops_.count(inst->opcode()) != 0) {
uint32_t dref_id = inst->GetSingleWordInOperand(kImageSampleDrefIdInIdx);
if (converted_ids_.count(dref_id) > 0) {
@@ -338,6 +339,19 @@
modified = true;
}
}
+ if (coordinate_image_ops_.count(inst->opcode()) != 0) {
+ uint32_t coordinate_id =
+ inst->GetSingleWordInOperand(kImageSampleCoordinateIdInIdx);
+ if (converted_ids_.count(coordinate_id) > 0) {
+ GenConvert(&coordinate_id, 32, inst);
+ if (status_ == Status::Failure) {
+ return false;
+ }
+ inst->SetInOperand(kImageSampleCoordinateIdInIdx, {coordinate_id});
+ get_def_use_mgr()->AnalyzeInstUse(inst);
+ modified = true;
+ }
+ }
return modified;
}
@@ -591,6 +605,30 @@
spv::Op::OpImageSparseSampleProjDrefExplicitLod,
spv::Op::OpImageSparseDrefGather,
};
+ coordinate_image_ops_ = {
+ spv::Op::OpImageSampleImplicitLod,
+ spv::Op::OpImageSampleExplicitLod,
+ spv::Op::OpImageSampleDrefImplicitLod,
+ spv::Op::OpImageSampleDrefExplicitLod,
+ spv::Op::OpImageSampleProjImplicitLod,
+ spv::Op::OpImageSampleProjExplicitLod,
+ spv::Op::OpImageSampleProjDrefImplicitLod,
+ spv::Op::OpImageSampleProjDrefExplicitLod,
+ spv::Op::OpImageFetch,
+ spv::Op::OpImageGather,
+ spv::Op::OpImageDrefGather,
+ spv::Op::OpImageRead,
+ spv::Op::OpImageWrite,
+ spv::Op::OpImageQueryLod,
+ spv::Op::OpImageSparseSampleImplicitLod,
+ spv::Op::OpImageSparseSampleExplicitLod,
+ spv::Op::OpImageSparseSampleDrefImplicitLod,
+ spv::Op::OpImageSparseSampleDrefExplicitLod,
+ spv::Op::OpImageSparseFetch,
+ spv::Op::OpImageSparseGather,
+ spv::Op::OpImageSparseDrefGather,
+ spv::Op::OpImageSparseRead,
+ };
closure_ops_ = {
spv::Op::OpVectorExtractDynamic,
spv::Op::OpVectorInsertDynamic,
diff --git a/source/opt/convert_to_half_pass.h b/source/opt/convert_to_half_pass.h
index 6e97a2d..c04f27a 100644
--- a/source/opt/convert_to_half_pass.h
+++ b/source/opt/convert_to_half_pass.h
@@ -145,6 +145,9 @@
// Set of only dref sample operations
std::unordered_set<spv::Op, hasher> dref_image_ops_;
+ // Set of only sample operations that have a Coordinate operand
+ std::unordered_set<spv::Op, hasher> coordinate_image_ops_;
+
// Set of operations that can be marked as relaxed
std::unordered_set<spv::Op, hasher> closure_ops_;
diff --git a/source/val/validate_image.cpp b/source/val/validate_image.cpp
index dad6bcc..ea39ea5 100644
--- a/source/val/validate_image.cpp
+++ b/source/val/validate_image.cpp
@@ -237,6 +237,23 @@
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);
}
@@ -1021,6 +1038,84 @@
}
}
+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 &&
+ !_.HasCapability(spv::Capability::Kernel)) ||
+ 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;
+
+ const bool int_or_float = opcode == spv::Op::OpImageSampleExplicitLod ||
+ opcode == spv::Op::OpImageSparseSampleExplicitLod ||
+ opcode == spv::Op::OpImageRead ||
+ opcode == spv::Op::OpImageWrite ||
+ (opcode == spv::Op::OpImageQueryLod &&
+ _.HasCapability(spv::Capability::Kernel)) ||
+ 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());
@@ -1222,38 +1317,9 @@
"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 = */ 3))
+ return result;
const uint32_t sample_type = _.GetOperandTypeId(inst, 4);
if (!sample_type || !_.IsIntScalarType(sample_type)) {
@@ -1344,29 +1410,9 @@
}
}
- 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);
@@ -1453,19 +1499,9 @@
<< 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;
@@ -1527,19 +1563,9 @@
<< "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))
@@ -1607,19 +1633,9 @@
<< "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) {
@@ -1749,19 +1765,9 @@
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 &&
@@ -1806,19 +1812,9 @@
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);
@@ -2109,27 +2105,9 @@
<< "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
diff --git a/test/opt/convert_relaxed_to_half_test.cpp b/test/opt/convert_relaxed_to_half_test.cpp
index c577404..169ab29 100644
--- a/test/opt/convert_relaxed_to_half_test.cpp
+++ b/test/opt/convert_relaxed_to_half_test.cpp
@@ -514,28 +514,30 @@
%14 = OpFAdd %half %55 %56
%16 = OpCompositeConstruct %v2half %13 %14
%58 = OpFConvert %float %14
-%18 = OpImageSampleDrefImplicitLod %float %46 %16 %58
+%59 = OpFConvert %v2float %16
+%18 = OpImageSampleDrefImplicitLod %float %46 %59 %58
%48 = OpLoad %27 %g_tTex1df4
%49 = OpLoad %29 %g_sSamp
%50 = OpSampledImage %31 %48 %49
-%59 = OpFConvert %half %12
-%60 = OpFConvert %half %float_0_200000003
-%15 = OpFMul %half %59 %60
+%60 = OpFConvert %half %12
+%61 = OpFConvert %half %float_0_200000003
+%15 = OpFMul %half %60 %61
%51 = OpAccessChain %_ptr_Uniform_float %_ %int_1
%17 = OpLoad %float %51
-%61 = OpFConvert %half %17
-%62 = OpFConvert %half %float_0_200000003
-%19 = OpFAdd %half %61 %62
+%62 = OpFConvert %half %17
+%63 = OpFConvert %half %float_0_200000003
+%19 = OpFAdd %half %62 %63
%20 = OpCompositeConstruct %v2half %15 %19
-%63 = OpFConvert %float %19
-%21 = OpImageSampleDrefImplicitLod %float %50 %20 %63
-%64 = OpFConvert %half %18
-%65 = OpFConvert %half %21
-%22 = OpFAdd %half %64 %65
-%66 = OpFConvert %half %float_0_5
-%23 = OpFMul %half %22 %66
-%67 = OpFConvert %float %23
-OpStore %_entryPointOutput_Color %67
+%64 = OpFConvert %float %19
+%65 = OpFConvert %v2float %20
+%21 = OpImageSampleDrefImplicitLod %float %50 %65 %64
+%66 = OpFConvert %half %18
+%67 = OpFConvert %half %21
+%22 = OpFAdd %half %66 %67
+%68 = OpFConvert %half %float_0_5
+%23 = OpFMul %half %22 %68
+%69 = OpFConvert %float %23
+OpStore %_entryPointOutput_Color %69
OpReturn
OpFunctionEnd
)";
@@ -1616,6 +1618,7 @@
TEST_F(ConvertToHalfTest, PreserveImageOperandPrecision) {
// Ensure that a non-relaxed texture coordinate does not get relaxed nor
// converted to half precision if the image instruction is marked relaxed.
+ // Update - coordinates are not allowed to be 16-bit regardless
// Also ensure that a relaxed local variable does get converted to half
// precision before being passed to an image opeartor.
@@ -1639,7 +1642,7 @@
OpCapability Float16
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %4 "main" %13 %25
+ OpEntryPoint Fragment %4 "main" %13 %26
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
OpDecorate %9 RelaxedPrecision
@@ -1648,8 +1651,8 @@
OpDecorate %17 DescriptorSet 3
OpDecorate %17 Binding 0
OpDecorate %18 RelaxedPrecision
- OpDecorate %23 RelaxedPrecision
- OpDecorate %25 Location 10
+ OpDecorate %24 RelaxedPrecision
+ OpDecorate %26 Location 10
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeFloat 32
@@ -1669,13 +1672,13 @@
%17 = OpVariable %16 UniformConstant
%19 = OpTypeVector %6 2
;CHECK: [[vec2_t:%\w+]] = OpTypeVector [[float32_t]] 2
- %24 = OpTypePointer Input %7
+ %25 = OpTypePointer Input %7
;CHECK: [[input_ptr_t:%\w+]] = OpTypePointer Input [[vec4_t]]
- %25 = OpVariable %24 Input
- %29 = OpTypeFloat 16
+ %26 = OpVariable %25 Input
+ %30 = OpTypeFloat 16
;CHECK: [[float16_t:%\w+]] = OpTypeFloat 16
- %30 = OpTypeVector %29 4
- %33 = OpTypeVector %29 2
+ %31 = OpTypeVector %30 4
+ %34 = OpTypeVector %30 2
;CHECK: [[vec2_16b_t:%\w+]] = OpTypeVector [[float16_t]] 2
%4 = OpFunction %2 None %3
%5 = OpLabel
@@ -1686,26 +1689,27 @@
OpStore %9 %11
%18 = OpLoad %15 %17
%20 = OpLoad %7 %9
- %31 = OpFConvert %30 %20
- %32 = OpFConvert %30 %20
+ %32 = OpFConvert %31 %20
+ %33 = OpFConvert %31 %20
-; The first sample op should get a 16b coordinate
- %21 = OpVectorShuffle %33 %31 %32 0 1
+; The first sample op should get a 32b coordinate, even if relaxed
+ %21 = OpVectorShuffle %34 %32 %33 0 1
;CHECK: [[uv_16b:%\w+]] = OpVectorShuffle [[vec2_16b_t]]
- %22 = OpImageSampleImplicitLod %7 %18 %21
-;CHECK: OpImageSampleImplicitLod [[vec4_t]] {{%\w+}} [[uv_16b]]
+ %22 = OpFConvert %19 %21
+ %23 = OpImageSampleImplicitLod %7 %18 %22
+;CHECK: OpImageSampleImplicitLod [[vec4_t]] {{%\w+}} {{%\w+}}
- OpStore %13 %22
- %23 = OpLoad %15 %17
- %26 = OpLoad %7 %25
+ OpStore %13 %23
+ %24 = OpLoad %15 %17
+ %27 = OpLoad %7 %26
; The second sample op should get a 32b coordinate
- %27 = OpVectorShuffle %19 %26 %26 0 1
+ %28 = OpVectorShuffle %19 %27 %27 0 1
;CHECK: [[uv_32b:%\w+]] = OpVectorShuffle [[vec2_t]]
- %28 = OpImageSampleImplicitLod %7 %23 %27
+ %29 = OpImageSampleImplicitLod %7 %24 %28
;CHECK: OpImageSampleImplicitLod [[vec4_t]] {{%\w+}} [[uv_32b]]
- OpStore %13 %28
+ OpStore %13 %29
OpReturn
OpFunctionEnd
)";
diff --git a/test/val/val_image_test.cpp b/test/val/val_image_test.cpp
index 106e097..c17b822 100644
--- a/test/val/val_image_test.cpp
+++ b/test/val/val_image_test.cpp
@@ -1493,8 +1493,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be integer scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit integer scalar or vector"));
}
TEST_F(ValidateImage, ImageTexelPointerImageCoordSizeBad) {
@@ -1652,8 +1653,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit float scalar or vector"));
}
TEST_F(ValidateImage, SampleImplicitLodCoordinateSizeTooSmall) {
@@ -1816,7 +1818,22 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ HasSubstr("Expected Coordinate to be a 32-bit integer or float "
+ "scalar or vector"));
+}
+
+TEST_F(ValidateImage, SampleExplicitLodWrongCoordinateType16Bit) {
+ const std::string body = R"(
+%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
+%sampler = OpLoad %type_sampler %uniform_sampler
+%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
+%res1 = OpImageSampleExplicitLod %f32vec4 %simg %f16vec2_00 Lod %f32_1
+)";
+
+ CompileSuccessfully(GenerateShaderCode(body).c_str());
+ ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
+ EXPECT_THAT(getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit scalar or vector"));
}
TEST_F(ValidateImage, SampleExplicitLodCoordinateSizeTooSmall) {
@@ -2515,8 +2532,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit float scalar or vector"));
}
TEST_F(ValidateImage, SampleProjExplicitLodCoordinateSizeTooSmall) {
@@ -2651,8 +2669,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit float scalar or vector"));
}
TEST_F(ValidateImage, SampleProjImplicitLodCoordinateSizeTooSmall) {
@@ -2777,8 +2796,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit float scalar or vector"));
}
TEST_F(ValidateImage, SampleDrefImplicitLodCoordinateSizeTooSmall) {
@@ -2934,8 +2954,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit float scalar or vector"));
}
TEST_F(ValidateImage, SampleDrefExplicitLodCoordinateSizeTooSmall) {
@@ -3074,8 +3095,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit float scalar or vector"));
}
TEST_F(ValidateImage, SampleProjDrefImplicitLodCoordinateSizeTooSmall) {
@@ -3213,8 +3235,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit float scalar or vector"));
}
TEST_F(ValidateImage, SampleProjDrefExplicitLodCoordinateSizeTooSmall) {
@@ -3377,8 +3400,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be int scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit integer scalar or vector"));
}
TEST_F(ValidateImage, FetchCoordinateSizeTooSmall) {
@@ -3552,8 +3576,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit float scalar or vector"));
}
TEST_F(ValidateImage, GatherCoordinateSizeTooSmall) {
@@ -4043,7 +4068,7 @@
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
}
-TEST_F(ValidateImage, ReadWrongCoordinateType) {
+TEST_F(ValidateImage, ReadFloatCoordinateType) {
const std::string body = R"(
%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
%res1 = OpImageRead %u32vec4 %img %f32vec2_00
@@ -4051,9 +4076,20 @@
const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateImage, ReadWrongCoordinateType) {
+ const std::string body = R"(
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
+%res1 = OpImageRead %u32vec4 %img %f16vec2_00
+)";
+
+ const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
+ CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be int scalar or vector"));
+ HasSubstr("Expected Coordinate to be a 32-bit scalar or vector"));
}
TEST_F(ValidateImage, ReadCoordinateSizeTooSmall) {
@@ -4217,7 +4253,7 @@
HasSubstr("Expected Image 'Sampled' parameter to be 0 or 2"));
}
-TEST_F(ValidateImage, WriteWrongCoordinateType) {
+TEST_F(ValidateImage, WriteFloatCoordinateType) {
const std::string body = R"(
%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
OpImageWrite %img %f32vec2_00 %u32vec4_0123
@@ -4225,9 +4261,20 @@
const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
+ ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
+}
+
+TEST_F(ValidateImage, WriteWrongCoordinateType) {
+ const std::string body = R"(
+%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
+OpImageWrite %img %f16vec2_00 %u32vec4_0123
+)";
+
+ const std::string extra = "\nOpCapability StorageImageWriteWithoutFormat\n";
+ CompileSuccessfully(GenerateShaderCode(body, extra).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be int scalar or vector"));
+ HasSubstr("Expected Coordinate to be a 32-bit scalar or vector"));
}
TEST_F(ValidateImage, WriteCoordinateSizeTooSmall) {
@@ -4843,8 +4890,9 @@
CompileSuccessfully(GenerateShaderCode(body).c_str());
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
- EXPECT_THAT(getDiagnosticString(),
- HasSubstr("Expected Coordinate to be float scalar or vector"));
+ EXPECT_THAT(
+ getDiagnosticString(),
+ HasSubstr("Expected Coordinate to be a 32-bit float scalar or vector"));
}
TEST_F(ValidateImage, QueryLodCoordinateSizeTooSmall) {