mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-23 12:10:06 +00:00
Validate Sampled=1 for Vulkan ImageQuerySizeLod, ImageQueryLevels, ImageQueryLod (#4103)
Also require image type parameter to OpTypeSampledImage to have Sampled=0 or Sampled=1 Fixes #4102
This commit is contained in:
parent
e25db023c4
commit
56f8ed48ef
@ -877,6 +877,20 @@ spv_result_t ValidateTypeSampledImage(ValidationState_t& _,
|
|||||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||||
<< "Expected Image to be of type OpTypeImage";
|
<< "Expected Image to be of type OpTypeImage";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageTypeInfo info;
|
||||||
|
if (!GetImageTypeInfo(_, image_type, &info)) {
|
||||||
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||||
|
<< "Corrupt image type definition";
|
||||||
|
}
|
||||||
|
// OpenCL requires Sampled=0, checked elsewhere.
|
||||||
|
// Vulkan uses the Sampled=1 case.
|
||||||
|
if ((info.sampled != 0) && (info.sampled != 1)) {
|
||||||
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||||
|
<< "Sampled image type requires an image type with \"Sampled\" "
|
||||||
|
"operand set to 0 or 1";
|
||||||
|
}
|
||||||
|
|
||||||
return SPV_SUCCESS;
|
return SPV_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1728,6 +1742,16 @@ spv_result_t ValidateImageQuerySizeLod(ValidationState_t& _,
|
|||||||
return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'MS' must be 0";
|
return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'MS' must be 0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto target_env = _.context()->target_env;
|
||||||
|
if (spvIsVulkanEnv(target_env)) {
|
||||||
|
if (info.sampled != 1) {
|
||||||
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||||
|
<< _.VkErrorID(4659)
|
||||||
|
<< "OpImageQuerySizeLod must only consume an \"Image\" operand "
|
||||||
|
"whose type has its \"Sampled\" operand set to 1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t result_num_components = _.GetDimension(result_type);
|
uint32_t result_num_components = _.GetDimension(result_type);
|
||||||
if (result_num_components != expected_num_components) {
|
if (result_num_components != expected_num_components) {
|
||||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||||
@ -1902,6 +1926,13 @@ spv_result_t ValidateImageQueryLod(ValidationState_t& _,
|
|||||||
<< "Expected Coordinate to have at least " << min_coord_size
|
<< "Expected Coordinate to have at least " << min_coord_size
|
||||||
<< " components, but given only " << actual_coord_size;
|
<< " components, but given only " << actual_coord_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The operad is a sampled image.
|
||||||
|
// The sampled image type is already checked to be parameterized by an image
|
||||||
|
// type with Sampled=0 or Sampled=1. Vulkan bans Sampled=0, and so we have
|
||||||
|
// Sampled=1. So the validator already enforces Vulkan VUID 4659:
|
||||||
|
// OpImageQuerySizeLod must only consume an “Image” operand whose type has
|
||||||
|
// its "Sampled" operand set to 1
|
||||||
return SPV_SUCCESS;
|
return SPV_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1938,6 +1969,15 @@ spv_result_t ValidateImageQueryLevelsOrSamples(ValidationState_t& _,
|
|||||||
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||||
<< "Image 'Dim' must be 1D, 2D, 3D or Cube";
|
<< "Image 'Dim' must be 1D, 2D, 3D or Cube";
|
||||||
}
|
}
|
||||||
|
const auto target_env = _.context()->target_env;
|
||||||
|
if (spvIsVulkanEnv(target_env)) {
|
||||||
|
if (info.sampled != 1) {
|
||||||
|
return _.diag(SPV_ERROR_INVALID_DATA, inst)
|
||||||
|
<< _.VkErrorID(4659)
|
||||||
|
<< "OpImageQueryLevels must only consume an \"Image\" operand "
|
||||||
|
"whose type has its \"Sampled\" operand set to 1";
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(opcode == SpvOpImageQuerySamples);
|
assert(opcode == SpvOpImageQuerySamples);
|
||||||
if (info.dim != SpvDim2D) {
|
if (info.dim != SpvDim2D) {
|
||||||
|
@ -224,7 +224,6 @@ OpDecorate %uniform_sampler Binding 0
|
|||||||
%type_image_f32_1d_0002_rgba32f = OpTypeImage %f32 1D 0 0 0 2 Rgba32f
|
%type_image_f32_1d_0002_rgba32f = OpTypeImage %f32 1D 0 0 0 2 Rgba32f
|
||||||
%ptr_image_f32_1d_0002_rgba32f = OpTypePointer UniformConstant %type_image_f32_1d_0002_rgba32f
|
%ptr_image_f32_1d_0002_rgba32f = OpTypePointer UniformConstant %type_image_f32_1d_0002_rgba32f
|
||||||
%uniform_image_f32_1d_0002_rgba32f = OpVariable %ptr_image_f32_1d_0002_rgba32f UniformConstant
|
%uniform_image_f32_1d_0002_rgba32f = OpVariable %ptr_image_f32_1d_0002_rgba32f UniformConstant
|
||||||
%type_sampled_image_f32_1d_0002_rgba32f = OpTypeSampledImage %type_image_f32_1d_0002_rgba32f
|
|
||||||
|
|
||||||
%type_image_f32_2d_0001 = OpTypeImage %f32 2D 0 0 0 1 Unknown
|
%type_image_f32_2d_0001 = OpTypeImage %f32 2D 0 0 0 1 Unknown
|
||||||
%ptr_image_f32_2d_0001 = OpTypePointer UniformConstant %type_image_f32_2d_0001
|
%ptr_image_f32_2d_0001 = OpTypePointer UniformConstant %type_image_f32_2d_0001
|
||||||
@ -244,7 +243,6 @@ OpDecorate %uniform_sampler Binding 0
|
|||||||
%type_image_u32_2d_0002 = OpTypeImage %u32 2D 0 0 0 2 Unknown
|
%type_image_u32_2d_0002 = OpTypeImage %u32 2D 0 0 0 2 Unknown
|
||||||
%ptr_image_u32_2d_0002 = OpTypePointer UniformConstant %type_image_u32_2d_0002
|
%ptr_image_u32_2d_0002 = OpTypePointer UniformConstant %type_image_u32_2d_0002
|
||||||
%uniform_image_u32_2d_0002 = OpVariable %ptr_image_u32_2d_0002 UniformConstant
|
%uniform_image_u32_2d_0002 = OpVariable %ptr_image_u32_2d_0002 UniformConstant
|
||||||
%type_sampled_image_u32_2d_0002 = OpTypeSampledImage %type_image_u32_2d_0002
|
|
||||||
|
|
||||||
%type_image_s32_3d_0001 = OpTypeImage %s32 3D 0 0 0 1 Unknown
|
%type_image_s32_3d_0001 = OpTypeImage %s32 3D 0 0 0 1 Unknown
|
||||||
%ptr_image_s32_3d_0001 = OpTypePointer UniformConstant %type_image_s32_3d_0001
|
%ptr_image_s32_3d_0001 = OpTypePointer UniformConstant %type_image_s32_3d_0001
|
||||||
@ -254,17 +252,14 @@ OpDecorate %uniform_sampler Binding 0
|
|||||||
%type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Unknown
|
%type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Unknown
|
||||||
%ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
|
%ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
|
||||||
%uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
|
%uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
|
||||||
%type_sampled_image_f32_2d_0002 = OpTypeSampledImage %type_image_f32_2d_0002
|
|
||||||
|
|
||||||
%type_image_s32_2d_0002 = OpTypeImage %s32 2D 0 0 0 2 Unknown
|
%type_image_s32_2d_0002 = OpTypeImage %s32 2D 0 0 0 2 Unknown
|
||||||
%ptr_image_s32_2d_0002 = OpTypePointer UniformConstant %type_image_s32_2d_0002
|
%ptr_image_s32_2d_0002 = OpTypePointer UniformConstant %type_image_s32_2d_0002
|
||||||
%uniform_image_s32_2d_0002 = OpVariable %ptr_image_s32_2d_0002 UniformConstant
|
%uniform_image_s32_2d_0002 = OpVariable %ptr_image_s32_2d_0002 UniformConstant
|
||||||
%type_sampled_image_s32_2d_0002 = OpTypeSampledImage %type_image_s32_2d_0002
|
|
||||||
|
|
||||||
%type_image_f32_spd_0002 = OpTypeImage %f32 SubpassData 0 0 0 2 Unknown
|
%type_image_f32_spd_0002 = OpTypeImage %f32 SubpassData 0 0 0 2 Unknown
|
||||||
%ptr_image_f32_spd_0002 = OpTypePointer UniformConstant %type_image_f32_spd_0002
|
%ptr_image_f32_spd_0002 = OpTypePointer UniformConstant %type_image_f32_spd_0002
|
||||||
%uniform_image_f32_spd_0002 = OpVariable %ptr_image_f32_spd_0002 UniformConstant
|
%uniform_image_f32_spd_0002 = OpVariable %ptr_image_f32_spd_0002 UniformConstant
|
||||||
%type_sampled_image_f32_spd_0002 = OpTypeSampledImage %type_image_f32_spd_0002
|
|
||||||
|
|
||||||
%type_image_f32_3d_0111 = OpTypeImage %f32 3D 0 1 1 1 Unknown
|
%type_image_f32_3d_0111 = OpTypeImage %f32 3D 0 1 1 1 Unknown
|
||||||
%ptr_image_f32_3d_0111 = OpTypePointer UniformConstant %type_image_f32_3d_0111
|
%ptr_image_f32_3d_0111 = OpTypePointer UniformConstant %type_image_f32_3d_0111
|
||||||
@ -279,7 +274,6 @@ OpDecorate %uniform_sampler Binding 0
|
|||||||
%type_image_f32_cube_0102_rgba32f = OpTypeImage %f32 Cube 0 1 0 2 Rgba32f
|
%type_image_f32_cube_0102_rgba32f = OpTypeImage %f32 Cube 0 1 0 2 Rgba32f
|
||||||
%ptr_image_f32_cube_0102_rgba32f = OpTypePointer UniformConstant %type_image_f32_cube_0102_rgba32f
|
%ptr_image_f32_cube_0102_rgba32f = OpTypePointer UniformConstant %type_image_f32_cube_0102_rgba32f
|
||||||
%uniform_image_f32_cube_0102_rgba32f = OpVariable %ptr_image_f32_cube_0102_rgba32f UniformConstant
|
%uniform_image_f32_cube_0102_rgba32f = OpVariable %ptr_image_f32_cube_0102_rgba32f UniformConstant
|
||||||
%type_sampled_image_f32_cube_0102_rgba32f = OpTypeSampledImage %type_image_f32_cube_0102_rgba32f
|
|
||||||
|
|
||||||
%type_sampler = OpTypeSampler
|
%type_sampler = OpTypeSampler
|
||||||
%ptr_sampler = OpTypePointer UniformConstant %type_sampler
|
%ptr_sampler = OpTypePointer UniformConstant %type_sampler
|
||||||
@ -312,7 +306,6 @@ OpDecorate %uniform_sampler Binding 0
|
|||||||
%type_image_void_2d_0002 = OpTypeImage %void 2D 0 0 0 2 Unknown
|
%type_image_void_2d_0002 = OpTypeImage %void 2D 0 0 0 2 Unknown
|
||||||
%ptr_image_void_2d_0002 = OpTypePointer UniformConstant %type_image_void_2d_0002
|
%ptr_image_void_2d_0002 = OpTypePointer UniformConstant %type_image_void_2d_0002
|
||||||
%uniform_image_void_2d_0002 = OpVariable %ptr_image_void_2d_0002 UniformConstant
|
%uniform_image_void_2d_0002 = OpVariable %ptr_image_void_2d_0002 UniformConstant
|
||||||
%type_sampled_image_void_2d_0002 = OpTypeSampledImage %type_image_void_2d_0002
|
|
||||||
|
|
||||||
%type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown
|
%type_image_f32_rect_0001 = OpTypeImage %f32 Rect 0 0 0 1 Unknown
|
||||||
%ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001
|
%ptr_image_f32_rect_0001 = OpTypePointer UniformConstant %type_image_f32_rect_0001
|
||||||
@ -863,7 +856,7 @@ TEST_F(ValidateImage, TypeImageMultisampleSubpassData_OK) {
|
|||||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ValidateImage, TypeSampledImageNotImage) {
|
TEST_F(ValidateImage, TypeSampledImage_NotImage_Error) {
|
||||||
const std::string code = GetShaderHeader("", false) + R"(
|
const std::string code = GetShaderHeader("", false) + R"(
|
||||||
%simg_type = OpTypeSampledImage %f32
|
%simg_type = OpTypeSampledImage %f32
|
||||||
)";
|
)";
|
||||||
@ -874,6 +867,43 @@ TEST_F(ValidateImage, TypeSampledImageNotImage) {
|
|||||||
HasSubstr("Expected Image to be of type OpTypeImage"));
|
HasSubstr("Expected Image to be of type OpTypeImage"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, TypeSampledImage_Sampled0_Success) {
|
||||||
|
// This is ok in the OpenCL and universal environments.
|
||||||
|
// Vulkan will reject an OpTypeImage with Sampled=0, checked elsewhere.
|
||||||
|
const std::string code = GetShaderHeader() + R"(
|
||||||
|
%imty = OpTypeImage %f32 2D 0 0 0 0 Unknown
|
||||||
|
%simg_type = OpTypeSampledImage %imty
|
||||||
|
)" + TrivialMain();
|
||||||
|
|
||||||
|
CompileSuccessfully(code.c_str());
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||||
|
EXPECT_EQ(getDiagnosticString(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, TypeSampledImage_Sampled2_Error) {
|
||||||
|
const std::string code = GetShaderHeader() + R"(
|
||||||
|
%storage_image = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
|
||||||
|
%simg_type = OpTypeSampledImage %storage_image
|
||||||
|
)" + TrivialMain();
|
||||||
|
|
||||||
|
CompileSuccessfully(code.c_str());
|
||||||
|
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||||
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
|
HasSubstr("Sampled image type requires an image type with "
|
||||||
|
"\"Sampled\" operand set to 0 or 1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, TypeSampledImage_Sampled1_Success) {
|
||||||
|
const std::string code = GetShaderHeader() + R"(
|
||||||
|
%im = OpTypeImage %f32 2D 0 0 0 1 Unknown
|
||||||
|
%simg_type = OpTypeSampledImage %im
|
||||||
|
)" + TrivialMain();
|
||||||
|
|
||||||
|
CompileSuccessfully(code.c_str());
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||||
|
EXPECT_EQ(getDiagnosticString(), "");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ValidateImage, SampledImageSuccess) {
|
TEST_F(ValidateImage, SampledImageSuccess) {
|
||||||
const std::string body = R"(
|
const std::string body = R"(
|
||||||
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
|
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
|
||||||
@ -925,31 +955,32 @@ TEST_F(ValidateImage, SampledImageNotImage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ValidateImage, SampledImageImageNotForSampling) {
|
TEST_F(ValidateImage, SampledImageImageNotForSampling) {
|
||||||
const std::string body = R"(
|
const std::string code = GetShaderHeader() + R"(
|
||||||
%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
|
%im_ty = OpTypeImage %f32 2D 0 0 0 2 Unknown
|
||||||
%sampler = OpLoad %type_sampler %uniform_sampler
|
%sampler_ty = OpTypeSampler
|
||||||
%simg = OpSampledImage %type_sampled_image_f32_2d_0002 %img %sampler
|
%sampled_image_ty = OpTypeSampledImage %im_ty ; will fail here first!
|
||||||
|
|
||||||
|
%ptr_im_ty = OpTypePointer UniformConstant %im_ty
|
||||||
|
%var_im = OpVariable %ptr_im_ty UniformConstant
|
||||||
|
|
||||||
|
%ptr_sampler_ty = OpTypePointer UniformConstant %sampler_ty
|
||||||
|
%var_sampler = OpVariable %ptr_sampler_ty UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %func
|
||||||
|
%entry = OpLabel
|
||||||
|
%im = OpLoad %im_ty %var_im
|
||||||
|
%sampler = OpLoad %sampler_ty %var_sampler
|
||||||
|
%sampled_image = OpSampledImage %sampled_image_ty %im %sampler
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
)";
|
)";
|
||||||
|
|
||||||
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
CompileSuccessfully(code.c_str());
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||||
EXPECT_THAT(getDiagnosticString(),
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
HasSubstr("Expected Image 'Sampled' parameter to be 0 or 1"));
|
HasSubstr("Sampled image type requires an image type with "
|
||||||
}
|
"\"Sampled\" operand set to 0 or 1"))
|
||||||
|
<< code;
|
||||||
TEST_F(ValidateImage, SampledImageVulkanUnknownSampled) {
|
|
||||||
const std::string body = R"(
|
|
||||||
%img = OpLoad %type_image_u32_2d_0002 %uniform_image_u32_2d_0002
|
|
||||||
%sampler = OpLoad %type_sampler %uniform_sampler
|
|
||||||
%simg = OpSampledImage %type_sampled_image_u32_2d_0002 %img %sampler
|
|
||||||
)";
|
|
||||||
|
|
||||||
const spv_target_env env = SPV_ENV_VULKAN_1_0;
|
|
||||||
CompileSuccessfully(GenerateShaderCode(body, "", "Fragment", "", env), env);
|
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(env));
|
|
||||||
EXPECT_THAT(getDiagnosticString(),
|
|
||||||
HasSubstr("Expected Image 'Sampled' parameter to "
|
|
||||||
"be 1 for Vulkan environment."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ValidateImage, SampledImageNotSampler) {
|
TEST_F(ValidateImage, SampledImageNotSampler) {
|
||||||
@ -1022,7 +1053,7 @@ TEST_F(ValidateImage, ImageTexelPointerImageNotResultTypePointer) {
|
|||||||
|
|
||||||
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
||||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||||
EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 142[%142] cannot be a "
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 136[%136] cannot be a "
|
||||||
"type"));
|
"type"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3399,7 +3430,6 @@ OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %u32_1
|
|||||||
%type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
|
%type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
|
||||||
%ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
|
%ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
|
||||||
%uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
|
%uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
|
||||||
%type_sampled_image_f32_2d_0012 = OpTypeSampledImage %type_image_f32_2d_0012
|
|
||||||
)";
|
)";
|
||||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||||
SPV_ENV_UNIVERSAL_1_0, "GLSL450",
|
SPV_ENV_UNIVERSAL_1_0, "GLSL450",
|
||||||
@ -3581,7 +3611,6 @@ OpImageWrite %img %u32vec2_01 %f32vec4_0000 Sample %f32_1
|
|||||||
%type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
|
%type_image_f32_2d_0012 = OpTypeImage %f32 2D 0 0 1 2 Unknown
|
||||||
%ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
|
%ptr_image_f32_2d_0012 = OpTypePointer UniformConstant %type_image_f32_2d_0012
|
||||||
%uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
|
%uniform_image_f32_2d_0012 = OpVariable %ptr_image_f32_2d_0012 UniformConstant
|
||||||
%type_sampled_image_f32_2d_0012 = OpTypeSampledImage %type_image_f32_2d_0012
|
|
||||||
)";
|
)";
|
||||||
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", "",
|
||||||
SPV_ENV_UNIVERSAL_1_0, "GLSL450",
|
SPV_ENV_UNIVERSAL_1_0, "GLSL450",
|
||||||
@ -3810,6 +3839,67 @@ TEST_F(ValidateImage, QuerySizeLodSampledImageDirectly) {
|
|||||||
"for OpImageQuerySizeLod"));
|
"for OpImageQuerySizeLod"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, QuerySizeLodMultisampledError) {
|
||||||
|
const std::string body = R"(
|
||||||
|
%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
|
||||||
|
%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
|
||||||
|
)";
|
||||||
|
|
||||||
|
CompileSuccessfully(GenerateKernelCode(body).c_str());
|
||||||
|
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
|
||||||
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("Image 'MS' must be 0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, QuerySizeLodNonSampledUniversalSuccess) {
|
||||||
|
const std::string body = R"(
|
||||||
|
%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
|
||||||
|
%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_1
|
||||||
|
)";
|
||||||
|
|
||||||
|
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||||
|
EXPECT_EQ(getDiagnosticString(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, QuerySizeLodVulkanNonSampledError) {
|
||||||
|
// Create a whole shader module. Avoid Vulkan incompatibility with
|
||||||
|
// SampledRrect images inserted by helper function GenerateShaderCode.
|
||||||
|
const std::string body = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
OpCapability ImageQuery
|
||||||
|
OpMemoryModel Logical Simple
|
||||||
|
OpEntryPoint Fragment %main "main"
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
|
||||||
|
%f32 = OpTypeFloat 32
|
||||||
|
%u32 = OpTypeInt 32 0
|
||||||
|
%u32_0 = OpConstant %u32 0
|
||||||
|
%u32vec2 = OpTypeVector %u32 2
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%voidfn = OpTypeFunction %void
|
||||||
|
|
||||||
|
; Test with a storage image.
|
||||||
|
%type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
|
||||||
|
%ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
|
||||||
|
%uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
|
||||||
|
%res1 = OpImageQuerySizeLod %u32vec2 %img %u32_0
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
|
CompileSuccessfully(body.c_str());
|
||||||
|
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||||
|
EXPECT_THAT(
|
||||||
|
getDiagnosticString(),
|
||||||
|
HasSubstr(
|
||||||
|
"OpImageQuerySizeLod must only consume an \"Image\" operand whose "
|
||||||
|
"type has its \"Sampled\" operand set to 1"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ValidateImage, QuerySizeLodWrongImageDim) {
|
TEST_F(ValidateImage, QuerySizeLodWrongImageDim) {
|
||||||
const std::string body = R"(
|
const std::string body = R"(
|
||||||
%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
|
%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001
|
||||||
@ -4096,6 +4186,53 @@ TEST_F(ValidateImage, QueryLevelsWrongDim) {
|
|||||||
HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
|
HasSubstr("Image 'Dim' must be 1D, 2D, 3D or Cube"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, QuerySizeLevelsNonSampledUniversalSuccess) {
|
||||||
|
const std::string body = R"(
|
||||||
|
%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
|
||||||
|
%res1 = OpImageQueryLevels %u32 %img
|
||||||
|
)";
|
||||||
|
|
||||||
|
CompileSuccessfully(GenerateShaderCode(body).c_str());
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||||
|
EXPECT_EQ(getDiagnosticString(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, QuerySizeLevelsVulkanNonSampledError) {
|
||||||
|
// Create a whole shader module. Avoid Vulkan incompatibility with
|
||||||
|
// SampledRrect images inserted by helper function GenerateShaderCode.
|
||||||
|
const std::string body = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
OpCapability ImageQuery
|
||||||
|
OpMemoryModel Logical Simple
|
||||||
|
OpEntryPoint Fragment %main "main"
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
|
||||||
|
%f32 = OpTypeFloat 32
|
||||||
|
%u32 = OpTypeInt 32 0
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%voidfn = OpTypeFunction %void
|
||||||
|
|
||||||
|
; Test with a storage image.
|
||||||
|
%type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
|
||||||
|
%ptr_image_f32_2d_0002 = OpTypePointer UniformConstant %type_image_f32_2d_0002
|
||||||
|
%uniform_image_f32_2d_0002 = OpVariable %ptr_image_f32_2d_0002 UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
%img = OpLoad %type_image_f32_2d_0002 %uniform_image_f32_2d_0002
|
||||||
|
%res1 = OpImageQueryLevels %u32 %img
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
|
CompileSuccessfully(body.c_str());
|
||||||
|
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||||
|
EXPECT_THAT(
|
||||||
|
getDiagnosticString(),
|
||||||
|
HasSubstr("OpImageQueryLevels must only consume an \"Image\" operand "
|
||||||
|
"whose type has its \"Sampled\" operand set to 1"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ValidateImage, QuerySamplesSuccess) {
|
TEST_F(ValidateImage, QuerySamplesSuccess) {
|
||||||
const std::string body = R"(
|
const std::string body = R"(
|
||||||
%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
|
%img = OpLoad %type_image_f32_2d_0011 %uniform_image_f32_2d_0011
|
||||||
@ -4186,6 +4323,100 @@ OpExecutionMode %main DerivativeGroupLinearNV
|
|||||||
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, QueryLodUniversalSuccess) {
|
||||||
|
// Create a whole shader module. Avoid Vulkan incompatibility with
|
||||||
|
// SampledRrect images inserted by helper function GenerateShaderCode.
|
||||||
|
const std::string body = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
OpCapability ImageQuery
|
||||||
|
OpMemoryModel Logical Simple
|
||||||
|
OpEntryPoint Fragment %main "main"
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
|
||||||
|
OpDecorate %uniform_image_f32_2d_0000 DescriptorSet 0
|
||||||
|
OpDecorate %uniform_image_f32_2d_0000 Binding 0
|
||||||
|
OpDecorate %sampler DescriptorSet 0
|
||||||
|
OpDecorate %sampler Binding 1
|
||||||
|
|
||||||
|
%f32 = OpTypeFloat 32
|
||||||
|
%f32vec2 = OpTypeVector %f32 2
|
||||||
|
%f32vec2_null = OpConstantNull %f32vec2
|
||||||
|
%u32 = OpTypeInt 32 0
|
||||||
|
%u32vec2 = OpTypeVector %u32 2
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%voidfn = OpTypeFunction %void
|
||||||
|
|
||||||
|
; Test with an image with sampled = 0
|
||||||
|
%type_image_f32_2d_0000 = OpTypeImage %f32 2D 0 0 0 0 Rgba32f
|
||||||
|
%ptr_image_f32_2d_0000 = OpTypePointer UniformConstant %type_image_f32_2d_0000
|
||||||
|
%uniform_image_f32_2d_0000 = OpVariable %ptr_image_f32_2d_0000 UniformConstant
|
||||||
|
%sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0000
|
||||||
|
|
||||||
|
%sampler_ty = OpTypeSampler
|
||||||
|
%ptr_sampler_ty = OpTypePointer UniformConstant %sampler_ty
|
||||||
|
%sampler = OpVariable %ptr_sampler_ty UniformConstant
|
||||||
|
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
%img = OpLoad %type_image_f32_2d_0000 %uniform_image_f32_2d_0000
|
||||||
|
%s = OpLoad %sampler_ty %sampler
|
||||||
|
%simg = OpSampledImage %sampled_image_ty %img %s
|
||||||
|
%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
|
CompileSuccessfully(body.c_str());
|
||||||
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(ValidateImage, QueryLodVulkanNonSampledError) {
|
||||||
|
// Create a whole shader module. Avoid Vulkan incompatibility with
|
||||||
|
// SampledRrect images inserted by helper function GenerateShaderCode.
|
||||||
|
const std::string body = R"(
|
||||||
|
OpCapability Shader
|
||||||
|
OpCapability ImageQuery
|
||||||
|
OpMemoryModel Logical Simple
|
||||||
|
OpEntryPoint Fragment %main "main"
|
||||||
|
OpExecutionMode %main OriginUpperLeft
|
||||||
|
|
||||||
|
OpDecorate %sampled_image DescriptorSet 0
|
||||||
|
OpDecorate %sampled_image Binding 0
|
||||||
|
|
||||||
|
%f32 = OpTypeFloat 32
|
||||||
|
%f32vec2 = OpTypeVector %f32 2
|
||||||
|
%f32vec2_null = OpConstantNull %f32vec2
|
||||||
|
%u32 = OpTypeInt 32 0
|
||||||
|
%u32vec2 = OpTypeVector %u32 2
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%voidfn = OpTypeFunction %void
|
||||||
|
|
||||||
|
; Test with an image with Sampled = 2
|
||||||
|
; In Vulkan it Sampled must be 1 or 2, checked in another part of the
|
||||||
|
; validation flow.
|
||||||
|
%type_image_f32_2d_0002 = OpTypeImage %f32 2D 0 0 0 2 Rgba32f
|
||||||
|
|
||||||
|
; Expect to fail here.
|
||||||
|
%sampled_image_ty = OpTypeSampledImage %type_image_f32_2d_0002
|
||||||
|
%ptr_sampled_image_ty = OpTypePointer UniformConstant %sampled_image_ty
|
||||||
|
%sampled_image = OpVariable %ptr_sampled_image_ty UniformConstant
|
||||||
|
|
||||||
|
%main = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
%simg = OpLoad %sampled_image_ty %sampled_image
|
||||||
|
%res1 = OpImageQueryLod %f32vec2 %simg %f32vec2_null
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
|
CompileSuccessfully(body.c_str());
|
||||||
|
ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
|
||||||
|
EXPECT_THAT(getDiagnosticString(),
|
||||||
|
HasSubstr("Sampled image type requires an image type with "
|
||||||
|
"\"Sampled\" operand set to 0 or 1"));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) {
|
TEST_F(ValidateImage, QueryLodComputeShaderDerivativesMissingMode) {
|
||||||
const std::string body = R"(
|
const std::string body = R"(
|
||||||
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
|
%img = OpLoad %type_image_f32_2d_0001 %uniform_image_f32_2d_0001
|
||||||
|
Loading…
Reference in New Issue
Block a user