| // Copyright (c) 2023 LunarG Inc. | |
| // | |
| // 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. | |
| // Bindless Check Instrumentation Tests. | |
| // Tests ending with V2 use version 2 record format. | |
| #include <string> | |
| #include <vector> | |
| #include "test/opt/pass_fixture.h" | |
| #include "test/opt/pass_utils.h" | |
| namespace spvtools { | |
| namespace opt { | |
| namespace { | |
| using SwitchDescriptorSetTest = PassTest<::testing::Test>; | |
| TEST_F(SwitchDescriptorSetTest, Basic) { | |
| // #version 450 | |
| // #extension GL_EXT_buffer_reference : enable | |
| // | |
| // layout(buffer_reference, buffer_reference_align = 16) buffer bufStruct; | |
| // | |
| // layout(set = 7, binding = 7) uniform ufoo { | |
| // bufStruct data; | |
| // uint offset; | |
| // } u_info; | |
| // | |
| // layout(buffer_reference, std140) buffer bufStruct { | |
| // layout(offset = 0) int a[2]; | |
| // layout(offset = 32) int b; | |
| // }; | |
| // | |
| // void main() { | |
| // u_info.data.b = 0xca7; | |
| // } | |
| const std::string spirv = R"( | |
| OpCapability Shader | |
| OpCapability PhysicalStorageBufferAddresses | |
| OpExtension "SPV_EXT_physical_storage_buffer" | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel PhysicalStorageBuffer64 GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpSource GLSL 450 | |
| OpSourceExtension "GL_EXT_buffer_reference" | |
| OpName %main "main" | |
| OpName %ufoo "ufoo" | |
| OpMemberName %ufoo 0 "data" | |
| OpMemberName %ufoo 1 "offset" | |
| OpName %bufStruct "bufStruct" | |
| OpMemberName %bufStruct 0 "a" | |
| OpMemberName %bufStruct 1 "b" | |
| OpName %u_info "u_info" | |
| OpMemberDecorate %ufoo 0 Offset 0 | |
| OpMemberDecorate %ufoo 1 Offset 8 | |
| OpDecorate %ufoo Block | |
| OpDecorate %_arr_int_uint_2 ArrayStride 16 | |
| OpMemberDecorate %bufStruct 0 Offset 0 | |
| OpMemberDecorate %bufStruct 1 Offset 32 | |
| OpDecorate %bufStruct Block | |
| OpDecorate %u_info DescriptorSet 7 | |
| ;CHECK: OpDecorate %u_info DescriptorSet 31 | |
| OpDecorate %u_info Binding 7 | |
| ;CHECK: OpDecorate %u_info Binding 7 | |
| %void = OpTypeVoid | |
| %3 = OpTypeFunction %void | |
| OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_bufStruct PhysicalStorageBuffer | |
| %uint = OpTypeInt 32 0 | |
| %ufoo = OpTypeStruct %_ptr_PhysicalStorageBuffer_bufStruct %uint | |
| %int = OpTypeInt 32 1 | |
| %uint_2 = OpConstant %uint 2 | |
| %_arr_int_uint_2 = OpTypeArray %int %uint_2 | |
| %bufStruct = OpTypeStruct %_arr_int_uint_2 %int | |
| %_ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer PhysicalStorageBuffer %bufStruct | |
| %_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo | |
| %u_info = OpVariable %_ptr_Uniform_ufoo Uniform | |
| %int_0 = OpConstant %int 0 | |
| %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer Uniform %_ptr_PhysicalStorageBuffer_bufStruct | |
| %int_1 = OpConstant %int 1 | |
| %int_3239 = OpConstant %int 3239 | |
| %_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int | |
| %main = OpFunction %void None %3 | |
| %5 = OpLabel | |
| %17 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0 | |
| %18 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %17 | |
| %22 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %18 %int_1 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| // clang-format off | |
| SinglePassRunAndMatch<SwitchDescriptorSetPass>(spirv, true, 7, 31); | |
| } | |
| // Make sure DescriptorSet decorations that don't match the requested number | |
| // are left unchanged. | |
| TEST_F(SwitchDescriptorSetTest, Unchanged) { | |
| // #version 450 | |
| // #extension GL_EXT_buffer_reference : enable | |
| // | |
| // layout(buffer_reference, buffer_reference_align = 16) buffer bufStruct; | |
| // | |
| // layout(set = 11, binding = 7) uniform ufoo { | |
| // bufStruct data; | |
| // uint offset; | |
| // } u_info; | |
| // | |
| // layout(buffer_reference, std140) buffer bufStruct { | |
| // layout(offset = 0) int a[2]; | |
| // layout(offset = 32) int b; | |
| // }; | |
| // | |
| // void main() { | |
| // u_info.data.b = 0xca7; | |
| // } | |
| const std::string spirv = R"( | |
| OpCapability Shader | |
| OpCapability PhysicalStorageBufferAddresses | |
| OpExtension "SPV_EXT_physical_storage_buffer" | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel PhysicalStorageBuffer64 GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpSource GLSL 450 | |
| OpSourceExtension "GL_EXT_buffer_reference" | |
| OpName %main "main" | |
| OpName %ufoo "ufoo" | |
| OpMemberName %ufoo 0 "data" | |
| OpMemberName %ufoo 1 "offset" | |
| OpName %bufStruct "bufStruct" | |
| OpMemberName %bufStruct 0 "a" | |
| OpMemberName %bufStruct 1 "b" | |
| OpName %u_info "u_info" | |
| OpMemberDecorate %ufoo 0 Offset 0 | |
| OpMemberDecorate %ufoo 1 Offset 8 | |
| OpDecorate %ufoo Block | |
| OpDecorate %_arr_int_uint_2 ArrayStride 16 | |
| OpMemberDecorate %bufStruct 0 Offset 0 | |
| OpMemberDecorate %bufStruct 1 Offset 32 | |
| OpDecorate %bufStruct Block | |
| OpDecorate %u_info DescriptorSet 11 | |
| ;CHECK: OpDecorate %u_info DescriptorSet 11 | |
| OpDecorate %u_info Binding 7 | |
| ;CHECK: OpDecorate %u_info Binding 7 | |
| %void = OpTypeVoid | |
| %3 = OpTypeFunction %void | |
| OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_bufStruct PhysicalStorageBuffer | |
| %uint = OpTypeInt 32 0 | |
| %ufoo = OpTypeStruct %_ptr_PhysicalStorageBuffer_bufStruct %uint | |
| %int = OpTypeInt 32 1 | |
| %uint_2 = OpConstant %uint 2 | |
| %_arr_int_uint_2 = OpTypeArray %int %uint_2 | |
| %bufStruct = OpTypeStruct %_arr_int_uint_2 %int | |
| %_ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer PhysicalStorageBuffer %bufStruct | |
| %_ptr_Uniform_ufoo = OpTypePointer Uniform %ufoo | |
| %u_info = OpVariable %_ptr_Uniform_ufoo Uniform | |
| %int_0 = OpConstant %int 0 | |
| %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct = OpTypePointer Uniform %_ptr_PhysicalStorageBuffer_bufStruct | |
| %int_1 = OpConstant %int 1 | |
| %int_3239 = OpConstant %int 3239 | |
| %_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int | |
| %main = OpFunction %void None %3 | |
| %5 = OpLabel | |
| %17 = OpAccessChain %_ptr_Uniform__ptr_PhysicalStorageBuffer_bufStruct %u_info %int_0 | |
| %18 = OpLoad %_ptr_PhysicalStorageBuffer_bufStruct %17 | |
| %22 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %18 %int_1 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| // clang-format off | |
| SinglePassRunAndMatch<SwitchDescriptorSetPass>(spirv, true, 7, 31); | |
| } | |
| } // namespace | |
| } // namespace opt | |
| } // namespace spvtools |