From 1c128aa9efd991dd67c2bf4daa326c0e80a691d2 Mon Sep 17 00:00:00 2001 From: Alan Baker Date: Wed, 25 Jul 2018 15:30:57 -0400 Subject: [PATCH] Validating for new image operands * Validation checks for new image operands MakeTexelAvailableKHR and MakeTexelVisibleKHR * added tests * Tests that NonPrivateTexelKHR is accepted for all image operands Updating test environments * fixed build errors * changed image types for *FetchSuccess tests to use a type defined in 1.3 shader body --- source/val/validate_image.cpp | 35 ++++ test/val/val_image_test.cpp | 314 ++++++++++++++++++++++++++++++---- 2 files changed, 315 insertions(+), 34 deletions(-) diff --git a/source/val/validate_image.cpp b/source/val/validate_image.cpp index 7d35d5633..67da3f74e 100644 --- a/source/val/validate_image.cpp +++ b/source/val/validate_image.cpp @@ -498,6 +498,41 @@ spv_result_t ValidateImageOperands(ValidationState_t& _, } } + if (mask & SpvImageOperandsMakeTexelAvailableKHRMask) { + // Checked elsewhere: capability and memory model are correct. + if (opcode != SpvOpImageWrite) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Image Operand MakeTexelAvailableKHR can only be used with Op" + << spvOpcodeString(SpvOpImageWrite) << ": Op" + << spvOpcodeString(opcode); + } + + if (!(mask & SpvImageOperandsNonPrivateTexelKHRMask)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Image Operand MakeTexelAvailableKHR requires " + "NonPrivateTexelKHR is also specified: Op" + << spvOpcodeString(opcode); + } + } + + if (mask & SpvImageOperandsMakeTexelVisibleKHRMask) { + // Checked elsewhere: capability and memory model are correct. + if (opcode != SpvOpImageRead && opcode != SpvOpImageSparseRead) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Image Operand MakeTexelVisibleKHR can only be used with Op" + << spvOpcodeString(SpvOpImageRead) << " or Op" + << spvOpcodeString(SpvOpImageSparseRead) << ": Op" + << spvOpcodeString(opcode); + } + + if (!(mask & SpvImageOperandsNonPrivateTexelKHRMask)) { + return _.diag(SPV_ERROR_INVALID_DATA, inst) + << "Image Operand MakeTexelVisibleKHR requires NonPrivateTexelKHR " + "is also specified: Op" + << spvOpcodeString(opcode); + } + } + return SPV_SUCCESS; } diff --git a/test/val/val_image_test.cpp b/test/val/val_image_test.cpp index 5f4783dac..441592473 100644 --- a/test/val/val_image_test.cpp +++ b/test/val/val_image_test.cpp @@ -34,7 +34,8 @@ std::string GenerateShaderCode( const std::string& body, const std::string& capabilities_and_extensions = "", const std::string& execution_model = "Fragment", - const spv_target_env env = SPV_ENV_UNIVERSAL_1_0) { + const spv_target_env env = SPV_ENV_UNIVERSAL_1_0, + const std::string& memory_model = "GLSL450") { std::ostringstream ss; ss << R"( OpCapability Shader @@ -54,7 +55,7 @@ OpCapability ImageBuffer } ss << capabilities_and_extensions; - ss << "OpMemoryModel Logical GLSL450\n"; + ss << "OpMemoryModel Logical " << memory_model << "\n"; ss << "OpEntryPoint " << execution_model << " %main \"main\"\n"; if (execution_model == "Fragment") { ss << "OpExecutionMode %main OriginUpperLeft\n"; @@ -776,10 +777,17 @@ TEST_F(ValidateImage, SampleImplicitLodSuccess) { %res5 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Offset %s32vec2_01 %res6 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MinLod %f32_0_5 %res7 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 +%res8 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SampleImplicitLodWrongResultType) { @@ -889,10 +897,17 @@ TEST_F(ValidateImage, SampleExplicitLodSuccessShader) { %res3 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh ConstOffset %s32vec2_01 %res4 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01 %res5 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec2_hh Grad|Offset|MinLod %f32vec2_10 %f32vec2_01 %s32vec2_01 %f32_0_5 +%res6 = OpImageSampleExplicitLod %f32vec4 %simg %f32vec4_0000 Lod|NonPrivateTexelKHR %f32_1 )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SampleExplicitLodSuccessKernel) { @@ -1467,10 +1482,17 @@ TEST_F(ValidateImage, SampleProjExplicitLodSuccess2D) { %res4 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh ConstOffset %s32vec2_01 %res5 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01 %res7 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Grad|Offset %f32vec2_10 %f32vec2_01 %s32vec2_01 +%res8 = OpImageSampleProjExplicitLod %f32vec4 %simg %f32vec3_hhh Lod|NonPrivateTexelKHR %f32_1 )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SampleProjExplicitLodSuccessRect) { @@ -1594,10 +1616,17 @@ TEST_F(ValidateImage, SampleProjImplicitLodSuccess) { %res5 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Offset %s32vec2_01 %res6 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh MinLod %f32_0_5 %res7 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 +%res8 = OpImageSampleProjImplicitLod %f32vec4 %simg %f32vec3_hhh NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SampleProjImplicitLodWrongResultType) { @@ -1708,10 +1737,17 @@ TEST_F(ValidateImage, SampleDrefImplicitLodSuccess) { %res5 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01 %res6 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5 %res7 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 +%res8 = OpImageSampleDrefImplicitLod %u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SampleDrefImplicitLodWrongResultType) { @@ -1824,10 +1860,17 @@ TEST_F(ValidateImage, SampleDrefExplicitLodSuccess) { %res4 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 ConstOffset %s32vec3_012 %res5 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Offset %s32vec3_012 %res7 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec3_hhh %f32_1 Grad|Offset %f32vec3_hhh %f32vec3_hhh %s32vec3_012 +%res8 = OpImageSampleDrefExplicitLod %s32 %simg %f32vec4_0000 %f32_1 Lod|NonPrivateTexelKHR %f32_1 )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SampleDrefExplicitLodWrongResultType) { @@ -1941,10 +1984,17 @@ TEST_F(ValidateImage, SampleProjDrefImplicitLodSuccess) { %res5 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Offset %s32vec2_01 %res6 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 MinLod %f32_0_5 %res7 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 +%res8 = OpImageSampleProjDrefImplicitLod %f32 %simg %f32vec3_hhh %f32_0_5 NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SampleProjDrefImplicitLodWrongResultType) { @@ -2057,10 +2107,17 @@ TEST_F(ValidateImage, SampleProjDrefExplicitLodSuccess) { %res3 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 ConstOffset %s32_1 %res4 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Offset %s32_1 %res5 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Grad|Offset %f32_0_5 %f32_0_5 %s32_1 +%res6 = OpImageSampleProjDrefExplicitLod %f32 %simg %f32vec2_hh %f32_0_5 Lod|NonPrivateTexelKHR %f32_1 )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SampleProjDrefExplicitLodWrongResultType) { @@ -2151,12 +2208,19 @@ TEST_F(ValidateImage, SampleProjDrefExplicitLodCoordinateSizeTooSmall) { TEST_F(ValidateImage, FetchSuccess) { const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 +%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 %res1 = OpImageFetch %f32vec4 %img %u32vec2_01 +%res2 = OpImageFetch %f32vec4 %img %u32vec2_01 NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, FetchWrongResultType) { @@ -2290,10 +2354,17 @@ TEST_F(ValidateImage, GatherSuccess) { %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler %res1 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 %res2 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 ConstOffsets %const_offsets +%res3 = OpImageGather %f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, GatherWrongResultType) { @@ -2539,10 +2610,17 @@ TEST_F(ValidateImage, DrefGatherSuccess) { %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler %res1 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 %res2 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 ConstOffsets %const_offsets +%res3 = OpImageDrefGather %f32vec4 %simg %f32vec4_0000 %f32_0_5 NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, DrefGatherVoidSampledType) { @@ -3547,10 +3625,17 @@ TEST_F(ValidateImage, SparseSampleImplicitLodSuccess) { %res5 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh Offset %s32vec2_01 %res6 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh MinLod %f32_0_5 %res7 = OpImageSparseSampleImplicitLod %struct_u64_f32vec4 %simg %f32vec2_hh Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 +%res8 = OpImageSparseSampleImplicitLod %struct_u32_f32vec4 %simg %f32vec2_hh NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SparseSampleImplicitLodResultTypeNotStruct) { @@ -3668,10 +3753,17 @@ TEST_F(ValidateImage, SparseSampleDrefImplicitLodSuccess) { %res5 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Offset %s32vec2_01 %res6 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 MinLod %f32_0_5 %res7 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 Bias|Offset|MinLod %f32_0_25 %s32vec2_01 %f32_0_5 +%res8 = OpImageSparseSampleDrefImplicitLod %struct_u32_u32 %simg %f32vec2_hh %f32_1 NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SparseSampleDrefImplicitLodResultTypeNotStruct) { @@ -3753,12 +3845,19 @@ TEST_F(ValidateImage, SparseSampleDrefImplicitLodDifferentSampledType) { TEST_F(ValidateImage, SparseFetchSuccess) { const std::string body = R"( -%img = OpLoad %type_image_f32_rect_0001 %uniform_image_f32_rect_0001 +%img = OpLoad %type_image_f32_1d_0001 %uniform_image_f32_1d_0001 %res1 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01 +%res2 = OpImageSparseFetch %struct_u32_f32vec4 %img %u32vec2_01 NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SparseFetchResultTypeNotStruct) { @@ -3965,10 +4064,17 @@ TEST_F(ValidateImage, SparseGatherSuccess) { %sampler = OpLoad %type_sampler %uniform_sampler %simg = OpSampledImage %type_sampled_image_f32_2d_0001 %img %sampler %res1 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 +%res2 = OpImageSparseGather %struct_u32_f32vec4 %simg %f32vec4_0000 %u32_1 NonPrivateTexelKHR )"; - CompileSuccessfully(GenerateShaderCode(body).c_str()); - ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); + const std::string extra = R"( +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); } TEST_F(ValidateImage, SparseGatherResultTypeNotStruct) { @@ -4095,6 +4201,146 @@ TEST_F(ValidateImage, SparseTexelsResidentResultTypeNotBool) { HasSubstr("Expected Result Type to be bool scalar type")); } +TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageRead) { + const std::string body = R"( +%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 +%res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1 +)"; + + const std::string extra = R"( +OpCapability StorageImageReadWithoutFormat +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); +} + +TEST_F(ValidateImage, MakeTexelVisibleKHRSuccessImageSparseRead) { + 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 MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1 +)"; + + const std::string extra = R"( +OpCapability StorageImageReadWithoutFormat +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); +} + +TEST_F(ValidateImage, MakeTexelVisibleKHRFailureOpcode) { + 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 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelVisibleKHR|NonPrivateTexelKHR %u32_1 +)"; + + const std::string extra = R"( +OpCapability StorageImageReadWithoutFormat +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, + ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); + EXPECT_THAT( + getDiagnosticString(), + HasSubstr("Image Operand MakeTexelVisibleKHR can only be used with " + "OpImageRead or OpImageSparseRead: OpImageSampleImplicitLod")); +} + +TEST_F(ValidateImage, MakeTexelVisibleKHRFailureMissingNonPrivate) { + const std::string body = R"( +%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 +%res1 = OpImageRead %u32vec4 %img %u32vec2_01 MakeTexelVisibleKHR %u32_1 +)"; + + const std::string extra = R"( +OpCapability StorageImageReadWithoutFormat +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, + ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Image Operand MakeTexelVisibleKHR requires " + "NonPrivateTexelKHR is also specified: OpImageRead")); +} + +TEST_F(ValidateImage, MakeTexelAvailableKHRSuccessImageWrite) { + const std::string body = R"( +%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 +%res1 = OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1 +)"; + + const std::string extra = R"( +OpCapability StorageImageWriteWithoutFormat +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); +} + +TEST_F(ValidateImage, MakeTexelAvailableKHRFailureOpcode) { + 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 = OpImageSampleImplicitLod %f32vec4 %simg %f32vec2_hh MakeTexelAvailableKHR|NonPrivateTexelKHR %u32_1 +)"; + + const std::string extra = R"( +OpCapability StorageImageReadWithoutFormat +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, + ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Image Operand MakeTexelAvailableKHR can only be used " + "with OpImageWrite: OpImageSampleImplicitLod")); +} + +TEST_F(ValidateImage, MakeTexelAvailableKHRFailureMissingNonPrivate) { + const std::string body = R"( +%img = OpLoad %type_image_u32_2d_0000 %uniform_image_u32_2d_0000 +%res1 = OpImageWrite %img %u32vec2_01 %u32vec4_0123 MakeTexelAvailableKHR %u32_1 +)"; + + const std::string extra = R"( +OpCapability StorageImageWriteWithoutFormat +OpCapability VulkanMemoryModelKHR +OpExtension "SPV_KHR_vulkan_memory_model" +)"; + CompileSuccessfully(GenerateShaderCode(body, extra, "Fragment", + SPV_ENV_UNIVERSAL_1_3, "VulkanKHR") + .c_str()); + ASSERT_EQ(SPV_ERROR_INVALID_DATA, + ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); + EXPECT_THAT(getDiagnosticString(), + HasSubstr("Image Operand MakeTexelAvailableKHR requires " + "NonPrivateTexelKHR is also specified: OpImageWrite")); +} + } // namespace } // namespace val } // namespace spvtools