| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- // Copyright (c) 2021 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include <vector>
- #include "gmock/gmock.h"
- #include "source/opt/convert_to_sampled_image_pass.h"
- #include "test/opt/pass_fixture.h"
- #include "test/opt/pass_utils.h"
- namespace spvtools {
- namespace opt {
- namespace {
- using testing::Eq;
- using VectorOfDescriptorSetAndBindingPairs =
- std::vector<DescriptorSetAndBinding>;
- struct DescriptorSetAndBindingStringParsingTestCase {
- const char* descriptor_set_binding_str;
- bool expect_success;
- VectorOfDescriptorSetAndBindingPairs expected_descriptor_set_binding_pairs;
- };
- using DescriptorSetAndBindingStringParsingTest =
- ::testing::TestWithParam<DescriptorSetAndBindingStringParsingTestCase>;
- TEST_P(DescriptorSetAndBindingStringParsingTest, TestCase) {
- const auto& tc = GetParam();
- auto actual_descriptor_set_binding_pairs =
- ConvertToSampledImagePass::ParseDescriptorSetBindingPairsString(
- tc.descriptor_set_binding_str);
- if (tc.expect_success) {
- EXPECT_NE(nullptr, actual_descriptor_set_binding_pairs);
- if (actual_descriptor_set_binding_pairs) {
- EXPECT_THAT(*actual_descriptor_set_binding_pairs,
- Eq(tc.expected_descriptor_set_binding_pairs));
- }
- } else {
- EXPECT_EQ(nullptr, actual_descriptor_set_binding_pairs);
- }
- }
- INSTANTIATE_TEST_SUITE_P(
- ValidString, DescriptorSetAndBindingStringParsingTest,
- ::testing::ValuesIn(std::vector<
- DescriptorSetAndBindingStringParsingTestCase>{
- // 0. empty vector
- {"", true, VectorOfDescriptorSetAndBindingPairs({})},
- // 1. one pair
- {"100:1024", true,
- VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{100,
- 1024}})},
- // 2. two pairs
- {"100:1024 200:2048", true,
- VectorOfDescriptorSetAndBindingPairs(
- {DescriptorSetAndBinding{100, 1024},
- DescriptorSetAndBinding{200, 2048}})},
- // 3. spaces between entries
- {"100:1024 \n \r \t \v \f 200:2048", true,
- VectorOfDescriptorSetAndBindingPairs(
- {DescriptorSetAndBinding{100, 1024},
- DescriptorSetAndBinding{200, 2048}})},
- // 4. \t, \n, \r and spaces before spec id
- {" \n \r\t \t \v \f 100:1024", true,
- VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{100,
- 1024}})},
- // 5. \t, \n, \r and spaces after value string
- {"100:1024 \n \r\t \t \v \f ", true,
- VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{100,
- 1024}})},
- // 6. maximum spec id
- {"4294967295:0", true,
- VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{
- 4294967295, 0}})},
- // 7. minimum spec id
- {"0:100", true,
- VectorOfDescriptorSetAndBindingPairs({DescriptorSetAndBinding{0,
- 100}})},
- // 8. multiple entries
- {"101:1 102:2 103:3 104:4 200:201 9999:1000", true,
- VectorOfDescriptorSetAndBindingPairs(
- {DescriptorSetAndBinding{101, 1}, DescriptorSetAndBinding{102, 2},
- DescriptorSetAndBinding{103, 3}, DescriptorSetAndBinding{104, 4},
- DescriptorSetAndBinding{200, 201},
- DescriptorSetAndBinding{9999, 1000}})},
- }));
- INSTANTIATE_TEST_SUITE_P(
- InvalidString, DescriptorSetAndBindingStringParsingTest,
- ::testing::ValuesIn(
- std::vector<DescriptorSetAndBindingStringParsingTestCase>{
- // 0. missing default value
- {"100:", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 1. descriptor set is not an integer
- {"100.0:200", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 2. descriptor set is not a number
- {"something_not_a_number:1", false,
- VectorOfDescriptorSetAndBindingPairs{}},
- // 3. only descriptor set number
- {"100", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 4. empty descriptor set
- {":3", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 5. only colon
- {":", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 6. descriptor set overflow
- {"4294967296:200", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 7. descriptor set less than 0
- {"-1:200", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 8. nullptr
- {nullptr, false, VectorOfDescriptorSetAndBindingPairs{}},
- // 9. only a number is invalid
- {"1234", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 10. invalid entry separator
- {"12:34;23:14", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 11. invalid descriptor set and default value separator
- {"12@34", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 12. spaces before colon
- {"100 :1024", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 13. spaces after colon
- {"100: 1024", false, VectorOfDescriptorSetAndBindingPairs{}},
- // 14. descriptor set represented in hex float format is invalid
- {"0x3p10:200", false, VectorOfDescriptorSetAndBindingPairs{}},
- }));
- std::string BuildShader(const char* shader_decorate_instructions,
- const char* shader_image_and_sampler_variables,
- const char* shader_body) {
- // Base HLSL code:
- //
- // SamplerState sam : register(s2);
- // Texture2D <float4> texture : register(t5);
- //
- // float4 main() : SV_TARGET {
- // return texture.SampleLevel(sam, float2(1, 2), 10, 2);
- // }
- std::stringstream ss;
- ss << R"(
- OpCapability Shader
- OpMemoryModel Logical GLSL450
- OpEntryPoint Fragment %main "main" %out_var_SV_TARGET
- OpExecutionMode %main OriginUpperLeft
- OpSource HLSL 600
- OpName %type_sampler "type.sampler"
- OpName %type_2d_image "type.2d.image"
- OpName %out_var_SV_TARGET "out.var.SV_TARGET"
- OpName %main "main"
- OpName %type_sampled_image "type.sampled.image"
- OpDecorate %out_var_SV_TARGET Location 0
- )";
- ss << shader_decorate_instructions;
- ss << R"(
- %float = OpTypeFloat 32
- %float_1 = OpConstant %float 1
- %float_2 = OpConstant %float 2
- %v2float = OpTypeVector %float 2
- %12 = OpConstantComposite %v2float %float_1 %float_2
- %float_10 = OpConstant %float 10
- %int = OpTypeInt 32 1
- %int_2 = OpConstant %int 2
- %v2int = OpTypeVector %int 2
- %17 = OpConstantComposite %v2int %int_2 %int_2
- %type_sampler = OpTypeSampler
- %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
- %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
- %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
- %v4float = OpTypeVector %float 4
- %_ptr_Output_v4float = OpTypePointer Output %v4float
- %void = OpTypeVoid
- %23 = OpTypeFunction %void
- %type_sampled_image = OpTypeSampledImage %type_2d_image
- )";
- ss << shader_image_and_sampler_variables;
- ss << R"(
- %out_var_SV_TARGET = OpVariable %_ptr_Output_v4float Output
- %main = OpFunction %void None %23
- %24 = OpLabel
- )";
- ss << shader_body;
- ss << R"(
- OpReturn
- OpFunctionEnd
- )";
- return ss.str();
- }
- using ConvertToSampledImageTest = PassTest<::testing::Test>;
- TEST_F(ConvertToSampledImageTest, Texture2DAndSamplerToSampledImage) {
- const std::string shader = BuildShader(
- R"(
- OpDecorate %sam DescriptorSet 0
- OpDecorate %sam Binding 5
- OpDecorate %texture DescriptorSet 0
- OpDecorate %texture Binding 5
- )",
- R"(
- ; CHECK-NOT: OpVariable %_ptr_UniformConstant_type_2d_image
- ; CHECK: [[tex:%\w+]] = OpVariable %_ptr_UniformConstant_type_sampled_image UniformConstant
- %sam = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
- %texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
- )",
- R"(
- ; CHECK: [[load:%\w+]] = OpLoad %type_sampled_image [[tex]]
- ; CHECK: OpImageSampleExplicitLod %v4float [[load]]
- %25 = OpLoad %type_2d_image %texture
- %26 = OpLoad %type_sampler %sam
- %27 = OpSampledImage %type_sampled_image %25 %26
- %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
- OpStore %out_var_SV_TARGET %28
- )");
- auto result = SinglePassRunAndMatch<ConvertToSampledImagePass>(
- shader, /* do_validate = */ true,
- VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 5}});
- EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
- }
- TEST_F(ConvertToSampledImageTest, Texture2DToSampledImage) {
- const std::string shader = BuildShader(
- R"(
- OpDecorate %sam DescriptorSet 0
- OpDecorate %sam Binding 2
- OpDecorate %texture DescriptorSet 0
- OpDecorate %texture Binding 5
- )",
- R"(
- ; CHECK: [[tex:%\w+]] = OpVariable %_ptr_UniformConstant_type_sampled_image UniformConstant
- %sam = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
- %texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
- )",
- R"(
- ; CHECK: [[load:%\w+]] = OpLoad %type_sampled_image [[tex]]
- ; CHECK: [[image_extraction:%\w+]] = OpImage %type_2d_image [[load]]
- ; CHECK: OpSampledImage %type_sampled_image [[image_extraction]]
- %25 = OpLoad %type_2d_image %texture
- %26 = OpLoad %type_sampler %sam
- %27 = OpSampledImage %type_sampled_image %25 %26
- %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
- OpStore %out_var_SV_TARGET %28
- )");
- auto result = SinglePassRunAndMatch<ConvertToSampledImagePass>(
- shader, /* do_validate = */ true,
- VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 5}});
- EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithChange);
- }
- TEST_F(ConvertToSampledImageTest, SamplerToSampledImage) {
- const std::string shader = BuildShader(
- R"(
- OpDecorate %sam DescriptorSet 0
- OpDecorate %sam Binding 2
- OpDecorate %texture DescriptorSet 0
- OpDecorate %texture Binding 5
- )",
- R"(
- %sam = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
- %texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
- )",
- R"(
- %25 = OpLoad %type_2d_image %texture
- %26 = OpLoad %type_sampler %sam
- %27 = OpSampledImage %type_sampled_image %25 %26
- %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
- OpStore %out_var_SV_TARGET %28
- )");
- auto result = SinglePassRunToBinary<ConvertToSampledImagePass>(
- shader, /* skip_nop = */ false,
- VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 2}});
- EXPECT_EQ(std::get<1>(result), Pass::Status::Failure);
- }
- TEST_F(ConvertToSampledImageTest, TwoImagesWithDuplicatedDescriptorSetBinding) {
- const std::string shader = BuildShader(
- R"(
- OpDecorate %sam DescriptorSet 0
- OpDecorate %sam Binding 2
- OpDecorate %texture0 DescriptorSet 0
- OpDecorate %texture0 Binding 5
- OpDecorate %texture1 DescriptorSet 0
- OpDecorate %texture1 Binding 5
- )",
- R"(
- %sam = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
- %texture0 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
- %texture1 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
- )",
- R"(
- %25 = OpLoad %type_2d_image %texture0
- %26 = OpLoad %type_sampler %sam
- %27 = OpSampledImage %type_sampled_image %25 %26
- %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
- OpStore %out_var_SV_TARGET %28
- )");
- auto result = SinglePassRunToBinary<ConvertToSampledImagePass>(
- shader, /* skip_nop = */ false,
- VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 5}});
- EXPECT_EQ(std::get<1>(result), Pass::Status::Failure);
- }
- TEST_F(ConvertToSampledImageTest,
- TwoSamplersWithDuplicatedDescriptorSetBinding) {
- const std::string shader = BuildShader(
- R"(
- OpDecorate %sam0 DescriptorSet 0
- OpDecorate %sam0 Binding 2
- OpDecorate %sam1 DescriptorSet 0
- OpDecorate %sam1 Binding 2
- OpDecorate %texture DescriptorSet 0
- OpDecorate %texture Binding 5
- )",
- R"(
- %sam0 = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
- %sam1 = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
- %texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
- )",
- R"(
- %25 = OpLoad %type_2d_image %texture
- %26 = OpLoad %type_sampler %sam0
- %27 = OpSampledImage %type_sampled_image %25 %26
- %28 = OpImageSampleExplicitLod %v4float %27 %12 Lod|ConstOffset %float_10 %17
- OpStore %out_var_SV_TARGET %28
- )");
- auto result = SinglePassRunToBinary<ConvertToSampledImagePass>(
- shader, /* skip_nop = */ false,
- VectorOfDescriptorSetAndBindingPairs{DescriptorSetAndBinding{0, 2}});
- EXPECT_EQ(std::get<1>(result), Pass::Status::Failure);
- }
- } // namespace
- } // namespace opt
- } // namespace spvtools
|