mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-25 17:21:06 +00:00
Check OpSampledImage is only passed into valid instructions (#2467)
Fixes #1528
This commit is contained in:
parent
2d52cbee49
commit
ffbecae56a
@ -748,6 +748,33 @@ spv_result_t ValidateTypeSampledImage(ValidationState_t& _,
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
bool IsAllowedSampledImageOperand(SpvOp opcode) {
|
||||
switch (opcode) {
|
||||
case SpvOpSampledImage:
|
||||
case SpvOpImageSampleImplicitLod:
|
||||
case SpvOpImageSampleExplicitLod:
|
||||
case SpvOpImageSampleDrefImplicitLod:
|
||||
case SpvOpImageSampleDrefExplicitLod:
|
||||
case SpvOpImageSampleProjImplicitLod:
|
||||
case SpvOpImageSampleProjExplicitLod:
|
||||
case SpvOpImageSampleProjDrefImplicitLod:
|
||||
case SpvOpImageSampleProjDrefExplicitLod:
|
||||
case SpvOpImageGather:
|
||||
case SpvOpImageDrefGather:
|
||||
case SpvOpImage:
|
||||
case SpvOpImageQueryLod:
|
||||
case SpvOpImageSparseSampleImplicitLod:
|
||||
case SpvOpImageSparseSampleExplicitLod:
|
||||
case SpvOpImageSparseSampleDrefImplicitLod:
|
||||
case SpvOpImageSparseSampleDrefExplicitLod:
|
||||
case SpvOpImageSparseGather:
|
||||
case SpvOpImageSparseDrefGather:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
spv_result_t ValidateSampledImage(ValidationState_t& _,
|
||||
const Instruction* inst) {
|
||||
if (_.GetIdOpcode(inst->type_id()) != SpvOpTypeSampledImage) {
|
||||
@ -815,11 +842,7 @@ spv_result_t ValidateSampledImage(ValidationState_t& _,
|
||||
"block. The consumer instruction <id> is '"
|
||||
<< _.getIdName(consumer_instr->id()) << "'.";
|
||||
}
|
||||
// TODO: The following check is incomplete. We should also check that the
|
||||
// Sampled Image is not used by instructions that should not take
|
||||
// SampledImage as an argument. We could find the list of valid
|
||||
// instructions by scanning for "Sampled Image" in the operand description
|
||||
// field in the grammar file.
|
||||
|
||||
if (consumer_opcode == SpvOpPhi || consumer_opcode == SpvOpSelect) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "Result <id> from OpSampledImage instruction must not appear "
|
||||
@ -830,6 +853,18 @@ spv_result_t ValidateSampledImage(ValidationState_t& _,
|
||||
<< "' as an operand of <id> '"
|
||||
<< _.getIdName(consumer_instr->id()) << "'.";
|
||||
}
|
||||
|
||||
if (!IsAllowedSampledImageOperand(consumer_opcode)) {
|
||||
return _.diag(SPV_ERROR_INVALID_ID, inst)
|
||||
<< "Result <id> from OpSampledImage instruction must not appear "
|
||||
"as operand for Op"
|
||||
<< spvOpcodeString(static_cast<SpvOp>(consumer_opcode))
|
||||
<< ", since it is not specificed as taking an "
|
||||
<< "OpTypeSampledImage."
|
||||
<< " Found result <id> '" << _.getIdName(inst->id())
|
||||
<< "' as an operand of <id> '"
|
||||
<< _.getIdName(consumer_instr->id()) << "'.";
|
||||
}
|
||||
}
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
|
@ -2283,7 +2283,7 @@ TEST_F(ValidateImage, FetchNotImage) {
|
||||
%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 = OpImageFetch %f32vec4 %simg %u32vec2_01
|
||||
%res1 = OpImageFetch %f32vec4 %sampler %u32vec2_01
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
||||
@ -2292,6 +2292,21 @@ TEST_F(ValidateImage, FetchNotImage) {
|
||||
HasSubstr("Expected Image to be of type OpTypeImage"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, FetchSampledImageDirectly) {
|
||||
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 = OpImageFetch %f32vec4 %simg %u32vec2_01
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("OpSampledImage instruction must not appear as operand "
|
||||
"for OpImageFetch"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, FetchNotSampled) {
|
||||
const std::string body = R"(
|
||||
%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
|
||||
@ -3191,7 +3206,7 @@ TEST_F(ValidateImage, QueryFormatNotImage) {
|
||||
%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 = OpImageQueryFormat %u32 %simg
|
||||
%res1 = OpImageQueryFormat %u32 %sampler
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateKernelCode(body).c_str());
|
||||
@ -3227,7 +3242,7 @@ TEST_F(ValidateImage, QueryOrderNotImage) {
|
||||
%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 = OpImageQueryOrder %u32 %simg
|
||||
%res1 = OpImageQueryOrder %u32 %sampler
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateKernelCode(body).c_str());
|
||||
@ -3276,7 +3291,7 @@ TEST_F(ValidateImage, QuerySizeLodNotImage) {
|
||||
%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 = OpImageQuerySizeLod %u32vec2 %simg %u32_1
|
||||
%res1 = OpImageQuerySizeLod %u32vec2 %sampler %u32_1
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateKernelCode(body).c_str());
|
||||
@ -3285,6 +3300,21 @@ TEST_F(ValidateImage, QuerySizeLodNotImage) {
|
||||
HasSubstr("Expected Image to be of type OpTypeImage"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, QuerySizeLodSampledImageDirectly) {
|
||||
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 = OpImageQuerySizeLod %u32vec2 %simg %u32_1
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("OpSampledImage instruction must not appear as operand "
|
||||
"for OpImageQuerySizeLod"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, QuerySizeLodWrongImageDim) {
|
||||
const std::string body = R"(
|
||||
%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
|
||||
@ -3348,7 +3378,7 @@ TEST_F(ValidateImage, QuerySizeNotImage) {
|
||||
%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
|
||||
%sampler = OpLoad %type_sampler %uniform_sampler
|
||||
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
|
||||
%res1 = OpImageQuerySize %u32vec2 %simg
|
||||
%res1 = OpImageQuerySize %u32vec2 %sampler
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateKernelCode(body).c_str());
|
||||
@ -3357,6 +3387,21 @@ TEST_F(ValidateImage, QuerySizeNotImage) {
|
||||
HasSubstr("Expected Image to be of type OpTypeImage"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, QuerySizeSampledImageDirectly) {
|
||||
const std::string body = R"(
|
||||
%img = OpLoad %type_image_f32_2d_0010 %uniform_image_f32_2d_0010
|
||||
%sampler = OpLoad %type_sampler %uniform_sampler
|
||||
%simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler
|
||||
%res1 = OpImageQuerySize %u32vec2 %simg
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("OpSampledImage instruction must not appear as operand "
|
||||
"for OpImageQuerySize"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, QuerySizeDimSubpassDataBad) {
|
||||
const std::string body = R"(
|
||||
%img = OpLoad %type_image_f32_spd_0002 %uniform_image_f32_spd_0002
|
||||
@ -3531,7 +3576,7 @@ TEST_F(ValidateImage, QueryLevelsNotImage) {
|
||||
%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 = OpImageQueryLevels %u32 %simg
|
||||
%res1 = OpImageQueryLevels %u32 %sampler
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateKernelCode(body).c_str());
|
||||
@ -3540,6 +3585,21 @@ TEST_F(ValidateImage, QueryLevelsNotImage) {
|
||||
HasSubstr("Expected Image to be of type OpTypeImage"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, QueryLevelsSampledImageDirectly) {
|
||||
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 = OpImageQueryLevels %u32 %simg
|
||||
)";
|
||||
|
||||
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("OpSampledImage instruction must not appear as operand "
|
||||
"for OpImageQueryLevels"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateImage, QueryLevelsWrongDim) {
|
||||
const std::string body = R"(
|
||||
%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
|
||||
@ -4481,7 +4541,10 @@ TEST_F(ValidateImage, Issue2463NoSegFault) {
|
||||
)";
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("OpSampledImage instruction must not appear as operand "
|
||||
"for OpReturnValue"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user