Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spirv-val: Add support for SPV_AMD_shader_image_load_store_lod #3186

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion source/val/validate_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,17 @@ bool IsExplicitLod(SpvOp opcode) {
return false;
}

bool IsValidLodOperand(const ValidationState_t& _, SpvOp opcode) {
switch (opcode) {
case SpvOpImageRead:
case SpvOpImageWrite:
case SpvOpImageSparseRead:
return _.HasCapability(SpvCapabilityImageReadWriteLodAMD);
default:
return IsExplicitLod(opcode);
}
}

// Returns true if the opcode is a Image instruction which applies
// homogenous projection to the coordinates.
bool IsProj(SpvOp opcode) {
Expand Down Expand Up @@ -248,6 +259,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,

const bool is_implicit_lod = IsImplicitLod(opcode);
const bool is_explicit_lod = IsExplicitLod(opcode);
const bool is_valid_lod_operand = IsValidLodOperand(_, opcode);

// The checks should be done in the order of definition of OperandImage.

Expand Down Expand Up @@ -277,7 +289,7 @@ spv_result_t ValidateImageOperands(ValidationState_t& _,
}

if (mask & SpvImageOperandsLodMask) {
if (!is_explicit_lod && opcode != SpvOpImageFetch &&
if (!is_valid_lod_operand && opcode != SpvOpImageFetch &&
opcode != SpvOpImageSparseFetch) {
return _.diag(SPV_ERROR_INVALID_DATA, inst)
<< "Image Operand Lod can only be used with ExplicitLod opcodes "
Expand Down
163 changes: 163 additions & 0 deletions test/val/val_image_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4841,6 +4841,169 @@ TEST_F(ValidateImage, ZeroExtendVectorSIntTexelV14Good) {
EXPECT_THAT(getDiagnosticString(), Eq(""));
}

TEST_F(ValidateImage, ReadLodAMDSuccess1) {
const std::string body = R"(
%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
%res1 = OpImageRead %u32vec4 %img %u32vec2_01 Lod %u32_0
)";

const std::string extra =
"\nOpCapability StorageImageReadWithoutFormat\n"
"OpCapability ImageReadWriteLodAMD\n"
"OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
}

TEST_F(ValidateImage, ReadLodAMDSuccess2) {
const std::string body = R"(
%img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
%res1 = OpImageRead %f32vec4 %img %u32vec2_01 Lod %u32_0
)";

const std::string extra =
"\nOpCapability Image1D\n"
"OpCapability ImageReadWriteLodAMD\n"
"OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
}

TEST_F(ValidateImage, ReadLodAMDSuccess3) {
const std::string body = R"(
%img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
%res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
)";

const std::string extra =
"\nOpCapability ImageCubeArray\n"
"OpCapability ImageReadWriteLodAMD\n"
"OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
}

TEST_F(ValidateImage, ReadLodAMDNeedCapability) {
const std::string body = R"(
%img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
%res1 = OpImageRead %f32vec4 %img %u32vec3_012 Lod %u32_0
)";

const std::string extra = "\nOpCapability ImageCubeArray\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Image Operand Lod can only be used with ExplicitLod "
"opcodes and OpImageFetch"));
}

TEST_F(ValidateImage, WriteLodAMDSuccess1) {
const std::string body = R"(
%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000
OpImageWrite %img %u32vec2_01 %u32vec4_0123 Lod %u32_0
)";

const std::string extra =
"\nOpCapability StorageImageWriteWithoutFormat\n"
"OpCapability ImageReadWriteLodAMD\n"
"OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
}

TEST_F(ValidateImage, WriteLodAMDSuccess2) {
const std::string body = R"(
%img = OpLoad %type_image_f32_1d_0002_rgba32f %uniform_image_f32_1d_0002_rgba32f
OpImageWrite %img %u32_1 %f32vec4_0000 Lod %u32_0
)";

const std::string extra =
"\nOpCapability Image1D\n"
"OpCapability ImageReadWriteLodAMD\n"
"OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
}

TEST_F(ValidateImage, WriteLodAMDSuccess3) {
const std::string body = R"(
%img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
)";

const std::string extra =
"\nOpCapability ImageCubeArray\n"
"OpCapability ImageReadWriteLodAMD\n"
"OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
}

TEST_F(ValidateImage, WriteLodAMDNeedCapability) {
const std::string body = R"(
%img = OpLoad %type_image_f32_cube_0102_rgba32f %uniform_image_f32_cube_0102_rgba32f
OpImageWrite %img %u32vec3_012 %f32vec4_0000 Lod %u32_0
)";

const std::string extra = "\nOpCapability ImageCubeArray\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Image Operand Lod can only be used with ExplicitLod "
"opcodes and OpImageFetch"));
}

TEST_F(ValidateImage, SparseReadLodAMDSuccess) {
const std::string body = R"(
%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
%res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
)";

const std::string extra =
"\nOpCapability StorageImageReadWithoutFormat\n"
"OpCapability ImageReadWriteLodAMD\n"
"OpExtension \"SPV_AMD_shader_image_load_store_lod\"\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
}

TEST_F(ValidateImage, SparseReadLodAMDNeedCapability) {
const std::string body = R"(
%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
%res1 = OpImageSparseRead %struct_u32_f32vec4 %img %u32vec2_01 Lod %u32_0
)";

const std::string extra = "\nOpCapability StorageImageReadWithoutFormat\n";
CompileSuccessfully(
GenerateShaderCode(body, extra, "Fragment", "", SPV_ENV_UNIVERSAL_1_1),
SPV_ENV_UNIVERSAL_1_1);
ASSERT_EQ(SPV_ERROR_INVALID_DATA,
ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Image Operand Lod can only be used with ExplicitLod "
"opcodes and OpImageFetch"));
}

// No negative tests for ZeroExtend since we don't truly know the
// texel format.

Expand Down