| // Copyright 2024 The Dawn & Tint Authors | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are met: | |
| // | |
| // 1. Redistributions of source code must retain the above copyright notice, this | |
| // list of conditions and the following disclaimer. | |
| // | |
| // 2. Redistributions in binary form must reproduce the above copyright notice, | |
| // this list of conditions and the following disclaimer in the documentation | |
| // and/or other materials provided with the distribution. | |
| // | |
| // 3. Neither the name of the copyright holder nor the names of its | |
| // contributors may be used to endorse or promote products derived from | |
| // this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| #include "src/tint/lang/spirv/reader/parser/helper_test.h" | |
| namespace tint::spirv::reader { | |
| namespace { | |
| TEST_F(SpirvParserTest, ArrayLength_FromVar) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %myvar "myvar" | |
| OpMemberName %struct 0 "first" | |
| OpMemberName %struct 1 "rtarr" | |
| OpDecorate %myvar DescriptorSet 0 | |
| OpDecorate %myvar Binding 0 | |
| OpDecorate %struct Block | |
| OpDecorate %arr ArrayStride 4 | |
| OpMemberDecorate %struct 0 Offset 0 | |
| OpMemberDecorate %struct 1 Offset 4 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %ep_type = OpTypeFunction %void | |
| %arr = OpTypeRuntimeArray %u32 | |
| %struct = OpTypeStruct %u32 %arr | |
| %ptr_struct = OpTypePointer StorageBuffer %struct | |
| %myvar = OpVariable %ptr_struct StorageBuffer | |
| %main = OpFunction %void None %ep_type | |
| %entry = OpLabel | |
| %1 = OpArrayLength %u32 %myvar 1 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol = struct @align(4) { | |
| first:u32 @offset(0) | |
| rtarr:array<u32> @offset(4) | |
| } | |
| $B1: { # root | |
| %myvar:ptr<storage, tint_symbol, read_write> = var undef @binding_point(0, 0) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B2: { | |
| %3:ptr<storage, array<u32>, read_write> = access %myvar, 1u | |
| %4:u32 = arrayLength %3 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, ArrayLength_FromCopyObject) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %myvar "myvar" | |
| OpMemberName %struct 0 "first" | |
| OpMemberName %struct 1 "rtarr" | |
| OpDecorate %myvar DescriptorSet 0 | |
| OpDecorate %myvar Binding 0 | |
| OpDecorate %struct Block | |
| OpDecorate %arr ArrayStride 4 | |
| OpMemberDecorate %struct 0 Offset 0 | |
| OpMemberDecorate %struct 1 Offset 4 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %ep_type = OpTypeFunction %void | |
| %arr = OpTypeRuntimeArray %u32 | |
| %struct = OpTypeStruct %u32 %arr | |
| %ptr_struct = OpTypePointer StorageBuffer %struct | |
| %myvar = OpVariable %ptr_struct StorageBuffer | |
| %main = OpFunction %void None %ep_type | |
| %entry = OpLabel | |
| %2 = OpCopyObject %ptr_struct %myvar | |
| %1 = OpArrayLength %u32 %2 1 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol = struct @align(4) { | |
| first:u32 @offset(0) | |
| rtarr:array<u32> @offset(4) | |
| } | |
| $B1: { # root | |
| %myvar:ptr<storage, tint_symbol, read_write> = var undef @binding_point(0, 0) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B2: { | |
| %3:ptr<storage, tint_symbol, read_write> = let %myvar | |
| %4:ptr<storage, array<u32>, read_write> = access %3, 1u | |
| %5:u32 = arrayLength %4 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, ArrayLength_FromAccessChain) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %myvar "myvar" | |
| OpMemberName %struct 0 "first" | |
| OpMemberName %struct 1 "rtarr" | |
| OpDecorate %myvar DescriptorSet 0 | |
| OpDecorate %myvar Binding 0 | |
| OpDecorate %struct Block | |
| OpDecorate %arr ArrayStride 4 | |
| OpMemberDecorate %struct 0 Offset 0 | |
| OpMemberDecorate %struct 1 Offset 4 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %ep_type = OpTypeFunction %void | |
| %arr = OpTypeRuntimeArray %u32 | |
| %struct = OpTypeStruct %u32 %arr | |
| %ptr_struct = OpTypePointer StorageBuffer %struct | |
| %myvar = OpVariable %ptr_struct StorageBuffer | |
| %main = OpFunction %void None %ep_type | |
| %entry = OpLabel | |
| %2 = OpAccessChain %ptr_struct %myvar ; no indices | |
| %1 = OpArrayLength %u32 %2 1 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol = struct @align(4) { | |
| first:u32 @offset(0) | |
| rtarr:array<u32> @offset(4) | |
| } | |
| $B1: { # root | |
| %myvar:ptr<storage, tint_symbol, read_write> = var undef @binding_point(0, 0) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B2: { | |
| %3:ptr<storage, array<u32>, read_write> = access %myvar, 1u | |
| %4:u32 = arrayLength %3 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Load_Scalar) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %u32_ptr Function | |
| %load = OpLoad %u32 %var | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, u32, read_write> = var undef | |
| %3:u32 = load %2 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Load_Vector) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %vec4u = OpTypeVector %u32 4 | |
| %vec4u_ptr = OpTypePointer Function %vec4u | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %vec4u_ptr Function | |
| %load = OpLoad %vec4u %var | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, vec4<u32>, read_write> = var undef | |
| %3:vec4<u32> = load %2 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Load_VectorComponent) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %vec4u = OpTypeVector %u32 4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %vec4u_ptr = OpTypePointer Function %vec4u | |
| %u32_2 = OpConstant %u32 2 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %vec4u_ptr Function | |
| %access = OpAccessChain %u32_ptr %var %u32_2 | |
| %load = OpLoad %u32 %access | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, vec4<u32>, read_write> = var undef | |
| %3:ptr<function, u32, read_write> = access %2, 2u | |
| %4:u32 = load %3 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Load_Matrix) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %f32 = OpTypeFloat 32 | |
| %vec4f = OpTypeVector %f32 4 | |
| %mat3x4f = OpTypeMatrix %vec4f 3 | |
| %mat3x4f_ptr = OpTypePointer Function %mat3x4f | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %mat3x4f_ptr Function | |
| %load = OpLoad %mat3x4f %var | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, mat3x4<f32>, read_write> = var undef | |
| %3:mat3x4<f32> = load %2 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Load_MatrixColumn) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %f32 = OpTypeFloat 32 | |
| %vec4f = OpTypeVector %f32 4 | |
| %mat3x4f = OpTypeMatrix %vec4f 3 | |
| %vec4f_ptr = OpTypePointer Function %vec4f | |
| %mat3x4f_ptr = OpTypePointer Function %mat3x4f | |
| %u32_2 = OpConstant %u32 2 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %mat3x4f_ptr Function | |
| %access = OpAccessChain %vec4f_ptr %var %u32_2 | |
| %load = OpLoad %vec4f %access | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, mat3x4<f32>, read_write> = var undef | |
| %3:ptr<function, vec4<f32>, read_write> = access %2, 2u | |
| %4:vec4<f32> = load %3 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Load_Array) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_4 = OpConstant %u32 4 | |
| %arr = OpTypeArray %u32 %u32_4 | |
| %arr_ptr = OpTypePointer Function %arr | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %arr_ptr Function | |
| %load = OpLoad %arr %var | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, array<u32, 4>, read_write> = var undef | |
| %3:array<u32, 4> = load %2 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Load_ArrayElement) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_2 = OpConstant %u32 2 | |
| %u32_4 = OpConstant %u32 4 | |
| %arr = OpTypeArray %u32 %u32_4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %arr_ptr = OpTypePointer Function %arr | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %arr_ptr Function | |
| %access = OpAccessChain %u32_ptr %var %u32_2 | |
| %load = OpLoad %u32 %access | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, array<u32, 4>, read_write> = var undef | |
| %3:ptr<function, u32, read_write> = access %2, 2u | |
| %4:u32 = load %3 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_RuntimeArrayElement) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %sg "sg" | |
| OpName %main "main" | |
| OpName %S "S" | |
| OpMemberName %S 0 "a" | |
| OpDecorate %sg DescriptorSet 0 | |
| OpDecorate %sg Binding 1 | |
| OpDecorate %S Block | |
| OpDecorate %arr ArrayStride 4 | |
| OpMemberDecorate %S 0 Offset 0 | |
| %void = OpTypeVoid | |
| %uint = OpTypeInt 32 0 | |
| %int = OpTypeInt 32 1 | |
| %int_4 = OpConstant %int 4 | |
| %uint_0 = OpConstant %uint 0 | |
| %arr = OpTypeRuntimeArray %uint | |
| %S = OpTypeStruct %arr | |
| %5 = OpTypeFunction %void | |
| %ptr_s = OpTypePointer StorageBuffer %S | |
| %sg = OpVariable %ptr_s StorageBuffer | |
| %ptr_uint = OpTypePointer StorageBuffer %uint | |
| %main = OpFunction %void None %5 | |
| %8 = OpLabel | |
| %12 = OpAccessChain %ptr_uint %sg %uint_0 %int_4 | |
| OpStore %12 %uint_0 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| S = struct @align(4) { | |
| a:array<u32> @offset(0) | |
| } | |
| $B1: { # root | |
| %sg:ptr<storage, S, read_write> = var undef @binding_point(0, 1) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B2: { | |
| %3:ptr<storage, u32, read_write> = access %sg, 0u, 4i | |
| store %3, 0u | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Load_Struct) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %str = OpTypeStruct %u32 %u32 | |
| %str_ptr = OpTypePointer Function %str | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %str_ptr Function | |
| %load = OpLoad %str %var | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol_2 = struct @align(4) { | |
| tint_symbol:u32 @offset(0) | |
| tint_symbol_1:u32 @offset(4) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, tint_symbol_2, read_write> = var undef | |
| %3:tint_symbol_2 = load %2 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Load_StructMember) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_1 = OpConstant %u32 1 | |
| %str = OpTypeStruct %u32 %u32 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %str_ptr = OpTypePointer Function %str | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %str_ptr Function | |
| %access = OpAccessChain %u32_ptr %var %u32_1 | |
| %load = OpLoad %u32 %access | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol_2 = struct @align(4) { | |
| tint_symbol:u32 @offset(0) | |
| tint_symbol_1:u32 @offset(4) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, tint_symbol_2, read_write> = var undef | |
| %3:ptr<function, u32, read_write> = access %2, 1u | |
| %4:u32 = load %3 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_Scalar) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_42 = OpConstant %u32 42 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %u32_ptr Function | |
| OpStore %var %u32_42 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, u32, read_write> = var undef | |
| store %2, 42u | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_Vector) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %vec4u = OpTypeVector %u32 4 | |
| %null = OpConstantNull %vec4u | |
| %vec4u_ptr = OpTypePointer Function %vec4u | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %vec4u_ptr Function | |
| OpStore %var %null | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, vec4<u32>, read_write> = var undef | |
| store %2, vec4<u32>(0u) | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_VectorComponent) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_42 = OpConstant %u32 42 | |
| %vec4u = OpTypeVector %u32 4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %vec4u_ptr = OpTypePointer Function %vec4u | |
| %u32_2 = OpConstant %u32 2 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %vec4u_ptr Function | |
| %access = OpAccessChain %u32_ptr %var %u32_2 | |
| OpStore %access %u32_42 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, vec4<u32>, read_write> = var undef | |
| %3:ptr<function, u32, read_write> = access %2, 2u | |
| store %3, 42u | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_Matrix) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %f32 = OpTypeFloat 32 | |
| %vec4f = OpTypeVector %f32 4 | |
| %mat3x4f = OpTypeMatrix %vec4f 3 | |
| %null = OpConstantNull %mat3x4f | |
| %mat3x4f_ptr = OpTypePointer Function %mat3x4f | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %mat3x4f_ptr Function | |
| OpStore %var %null | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, mat3x4<f32>, read_write> = var undef | |
| store %2, mat3x4<f32>(vec4<f32>(0.0f)) | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_MatrixColumn) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %f32 = OpTypeFloat 32 | |
| %vec4f = OpTypeVector %f32 4 | |
| %mat3x4f = OpTypeMatrix %vec4f 3 | |
| %null = OpConstantNull %vec4f | |
| %vec4f_ptr = OpTypePointer Function %vec4f | |
| %mat3x4f_ptr = OpTypePointer Function %mat3x4f | |
| %u32_2 = OpConstant %u32 2 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %mat3x4f_ptr Function | |
| %access = OpAccessChain %vec4f_ptr %var %u32_2 | |
| OpStore %access %null | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, mat3x4<f32>, read_write> = var undef | |
| %3:ptr<function, vec4<f32>, read_write> = access %2, 2u | |
| store %3, vec4<f32>(0.0f) | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_Array) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_4 = OpConstant %u32 4 | |
| %arr = OpTypeArray %u32 %u32_4 | |
| %null = OpConstantNull %arr | |
| %arr_ptr = OpTypePointer Function %arr | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %arr_ptr Function | |
| OpStore %var %null | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, array<u32, 4>, read_write> = var undef | |
| store %2, array<u32, 4>(0u) | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_ArrayElement) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_2 = OpConstant %u32 2 | |
| %u32_4 = OpConstant %u32 4 | |
| %u32_42 = OpConstant %u32 42 | |
| %arr = OpTypeArray %u32 %u32_4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %arr_ptr = OpTypePointer Function %arr | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %arr_ptr Function | |
| %access = OpAccessChain %u32_ptr %var %u32_2 | |
| OpStore %access %u32_42 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, array<u32, 4>, read_write> = var undef | |
| %3:ptr<function, u32, read_write> = access %2, 2u | |
| store %3, 42u | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_Struct) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %str = OpTypeStruct %u32 %u32 | |
| %null = OpConstantNull %str | |
| %str_ptr = OpTypePointer Function %str | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %str_ptr Function | |
| OpStore %var %null | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol_2 = struct @align(4) { | |
| tint_symbol:u32 @offset(0) | |
| tint_symbol_1:u32 @offset(4) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, tint_symbol_2, read_write> = var undef | |
| store %2, tint_symbol_2(0u) | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Store_StructMember) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_1 = OpConstant %u32 1 | |
| %u32_42 = OpConstant %u32 42 | |
| %str = OpTypeStruct %u32 %u32 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %str_ptr = OpTypePointer Function %str | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %str_ptr Function | |
| %access = OpAccessChain %u32_ptr %var %u32_1 | |
| OpStore %access %u32_42 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol_2 = struct @align(4) { | |
| tint_symbol:u32 @offset(0) | |
| tint_symbol_1:u32 @offset(4) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, tint_symbol_2, read_write> = var undef | |
| %3:ptr<function, u32, read_write> = access %2, 1u | |
| store %3, 42u | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, CopyMemory_Scalar) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %src_var "src_var" | |
| OpName %dst_var "dst_var" | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %src_var = OpVariable %u32_ptr Function | |
| %dst_var = OpVariable %u32_ptr Function | |
| OpCopyMemory %dst_var %src_var | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %src_var:ptr<function, u32, read_write> = var undef | |
| %dst_var:ptr<function, u32, read_write> = var undef | |
| %4:u32 = load %src_var | |
| store %dst_var, %4 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, CopyMemory_Vector) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %src_vec "src_vec" | |
| OpName %dst_vec "dst_vec" | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %vec4u = OpTypeVector %u32 4 | |
| %vec4u_ptr = OpTypePointer Function %vec4u | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %src_vec = OpVariable %vec4u_ptr Function | |
| %dst_vec = OpVariable %vec4u_ptr Function | |
| OpCopyMemory %dst_vec %src_vec | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %src_vec:ptr<function, vec4<u32>, read_write> = var undef | |
| %dst_vec:ptr<function, vec4<u32>, read_write> = var undef | |
| %4:vec4<u32> = load %src_vec | |
| store %dst_vec, %4 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, CopyMemory_VectorComponent) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %src_vec "src_vec" | |
| OpName %dst_vec "dst_vec" | |
| OpName %src "src" | |
| OpName %dst "dst" | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %vec4u = OpTypeVector %u32 4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %vec4u_ptr = OpTypePointer Function %vec4u | |
| %u32_2 = OpConstant %u32 2 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %src_vec = OpVariable %vec4u_ptr Function | |
| %dst_vec = OpVariable %vec4u_ptr Function | |
| %src = OpAccessChain %u32_ptr %src_vec %u32_2 | |
| %dst = OpAccessChain %u32_ptr %dst_vec %u32_2 | |
| OpCopyMemory %dst %src | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %src_vec:ptr<function, vec4<u32>, read_write> = var undef | |
| %dst_vec:ptr<function, vec4<u32>, read_write> = var undef | |
| %src:ptr<function, u32, read_write> = access %src_vec, 2u | |
| %dst:ptr<function, u32, read_write> = access %dst_vec, 2u | |
| %6:u32 = load %src | |
| store %dst, %6 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, CopyMemory_Matrix) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %src_mat "src_mat" | |
| OpName %dst_mat "dst_mat" | |
| %void = OpTypeVoid | |
| %f32 = OpTypeFloat 32 | |
| %vec4f = OpTypeVector %f32 4 | |
| %mat3x4f = OpTypeMatrix %vec4f 3 | |
| %mat3x4f_ptr = OpTypePointer Function %mat3x4f | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %src_mat = OpVariable %mat3x4f_ptr Function | |
| %dst_mat = OpVariable %mat3x4f_ptr Function | |
| OpCopyMemory %dst_mat %src_mat | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %src_mat:ptr<function, mat3x4<f32>, read_write> = var undef | |
| %dst_mat:ptr<function, mat3x4<f32>, read_write> = var undef | |
| %4:mat3x4<f32> = load %src_mat | |
| store %dst_mat, %4 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, CopyMemory_MatrixColumn) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %src_mat "src_mat" | |
| OpName %mat_dst "mat_dst" | |
| OpName %src "src" | |
| OpName %dst "dst" | |
| %void = OpTypeVoid | |
| %f32 = OpTypeFloat 32 | |
| %vec4f = OpTypeVector %f32 4 | |
| %mat3x4f = OpTypeMatrix %vec4f 3 | |
| %vec4f_ptr = OpTypePointer Function %vec4f | |
| %mat3x4f_ptr = OpTypePointer Function %mat3x4f | |
| %u32 = OpTypeInt 32 0 | |
| %u32_2 = OpConstant %u32 2 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %src_mat = OpVariable %mat3x4f_ptr Function | |
| %mat_dst = OpVariable %mat3x4f_ptr Function | |
| %src = OpAccessChain %vec4f_ptr %src_mat %u32_2 | |
| %dst = OpAccessChain %vec4f_ptr %mat_dst %u32_2 | |
| OpCopyMemory %dst %src | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %src_mat:ptr<function, mat3x4<f32>, read_write> = var undef | |
| %mat_dst:ptr<function, mat3x4<f32>, read_write> = var undef | |
| %src:ptr<function, vec4<f32>, read_write> = access %src_mat, 2u | |
| %dst:ptr<function, vec4<f32>, read_write> = access %mat_dst, 2u | |
| %6:vec4<f32> = load %src | |
| store %dst, %6 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, CopyMemory_Array) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %src_arr "src_arr" | |
| OpName %dst_arr "dst_arr" | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_4 = OpConstant %u32 4 | |
| %arr = OpTypeArray %u32 %u32_4 | |
| %arr_ptr = OpTypePointer Function %arr | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %src_arr = OpVariable %arr_ptr Function | |
| %dst_arr = OpVariable %arr_ptr Function | |
| OpCopyMemory %dst_arr %src_arr | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %src_arr:ptr<function, array<u32, 4>, read_write> = var undef | |
| %dst_arr:ptr<function, array<u32, 4>, read_write> = var undef | |
| %4:array<u32, 4> = load %src_arr | |
| store %dst_arr, %4 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, CopyMemory_ArrayElement) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %src_arr "src_arr" | |
| OpName %dst_arr "dst_arr" | |
| OpName %src "src" | |
| OpName %dst "dst" | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_2 = OpConstant %u32 2 | |
| %u32_4 = OpConstant %u32 4 | |
| %arr = OpTypeArray %u32 %u32_4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %arr_ptr = OpTypePointer Function %arr | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %src_arr = OpVariable %arr_ptr Function | |
| %dst_arr = OpVariable %arr_ptr Function | |
| %src = OpAccessChain %u32_ptr %src_arr %u32_2 | |
| %dst = OpAccessChain %u32_ptr %dst_arr %u32_2 | |
| OpCopyMemory %dst %src | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %src_arr:ptr<function, array<u32, 4>, read_write> = var undef | |
| %dst_arr:ptr<function, array<u32, 4>, read_write> = var undef | |
| %src:ptr<function, u32, read_write> = access %src_arr, 2u | |
| %dst:ptr<function, u32, read_write> = access %dst_arr, 2u | |
| %6:u32 = load %src | |
| store %dst, %6 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, CopyMemory_Struct) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %src_str "src_str" | |
| OpName %dst_str "dst_str" | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %str = OpTypeStruct %u32 %u32 | |
| %str_ptr = OpTypePointer Function %str | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %src_str = OpVariable %str_ptr Function | |
| %dst_str = OpVariable %str_ptr Function | |
| OpCopyMemory %dst_str %src_str | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol_2 = struct @align(4) { | |
| tint_symbol:u32 @offset(0) | |
| tint_symbol_1:u32 @offset(4) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %src_str:ptr<function, tint_symbol_2, read_write> = var undef | |
| %dst_str:ptr<function, tint_symbol_2, read_write> = var undef | |
| %4:tint_symbol_2 = load %src_str | |
| store %dst_str, %4 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, CopyMemory_StructMember) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %src_str "src_str" | |
| OpName %dst_str "dst_str" | |
| OpName %src "src" | |
| OpName %dst "dst" | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_1 = OpConstant %u32 1 | |
| %str = OpTypeStruct %u32 %u32 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %str_ptr = OpTypePointer Function %str | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %src_str = OpVariable %str_ptr Function | |
| %dst_str = OpVariable %str_ptr Function | |
| %src = OpAccessChain %u32_ptr %src_str %u32_1 | |
| %dst = OpAccessChain %u32_ptr %dst_str %u32_1 | |
| OpCopyMemory %dst %src | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol_2 = struct @align(4) { | |
| tint_symbol:u32 @offset(0) | |
| tint_symbol_1:u32 @offset(4) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %src_str:ptr<function, tint_symbol_2, read_write> = var undef | |
| %dst_str:ptr<function, tint_symbol_2, read_write> = var undef | |
| %src:ptr<function, u32, read_write> = access %src_str, 1u | |
| %dst:ptr<function, u32, read_write> = access %dst_str, 1u | |
| %6:u32 = load %src | |
| store %dst, %6 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Access_Nested_SingleAccessInstruction) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_1 = OpConstant %u32 1 | |
| %u32_2 = OpConstant %u32 2 | |
| %u32_3 = OpConstant %u32 3 | |
| %u32_4 = OpConstant %u32 4 | |
| %u32_42 = OpConstant %u32 42 | |
| %arr_inner = OpTypeArray %u32 %u32_4 | |
| %str = OpTypeStruct %arr_inner %arr_inner %arr_inner %arr_inner | |
| %arr_outer = OpTypeArray %str %u32_4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %arr_outer_ptr = OpTypePointer Function %arr_outer | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %arr_outer_ptr Function | |
| %access = OpAccessChain %u32_ptr %var %u32_1 %u32_2 %u32_3 | |
| %load = OpLoad %u32 %access | |
| OpStore %access %u32_42 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol:array<u32, 4> @offset(0) | |
| tint_symbol_1:array<u32, 4> @offset(16) | |
| tint_symbol_2:array<u32, 4> @offset(32) | |
| tint_symbol_3:array<u32, 4> @offset(48) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, array<tint_symbol_4, 4>, read_write> = var undef | |
| %3:ptr<function, u32, read_write> = access %2, 1u, 2u, 3u | |
| %4:u32 = load %3 | |
| store %3, 42u | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Access_Nested_SeparateAccessInstructions) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_1 = OpConstant %u32 1 | |
| %u32_2 = OpConstant %u32 2 | |
| %u32_3 = OpConstant %u32 3 | |
| %u32_4 = OpConstant %u32 4 | |
| %u32_42 = OpConstant %u32 42 | |
| %arr_inner = OpTypeArray %u32 %u32_4 | |
| %str = OpTypeStruct %arr_inner %arr_inner %arr_inner %arr_inner | |
| %arr_outer = OpTypeArray %str %u32_4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %arr_inner_ptr = OpTypePointer Function %arr_inner | |
| %str_ptr = OpTypePointer Function %str | |
| %arr_outer_ptr = OpTypePointer Function %arr_outer | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %arr_outer_ptr Function | |
| %access_1 = OpAccessChain %str_ptr %var %u32_1 | |
| %access_2 = OpAccessChain %arr_inner_ptr %access_1 %u32_2 | |
| %access_3 = OpAccessChain %u32_ptr %access_2 %u32_3 | |
| %load = OpLoad %u32 %access_3 | |
| OpStore %access_3 %u32_42 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol:array<u32, 4> @offset(0) | |
| tint_symbol_1:array<u32, 4> @offset(16) | |
| tint_symbol_2:array<u32, 4> @offset(32) | |
| tint_symbol_3:array<u32, 4> @offset(48) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, array<tint_symbol_4, 4>, read_write> = var undef | |
| %3:ptr<function, tint_symbol_4, read_write> = access %2, 1u | |
| %4:ptr<function, array<u32, 4>, read_write> = access %3, 2u | |
| %5:ptr<function, u32, read_write> = access %4, 3u | |
| %6:u32 = load %5 | |
| store %5, 42u | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Access_NoIndices) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %u32_ptr Function | |
| %access_1 = OpAccessChain %u32_ptr %var | |
| %access_2 = OpAccessChain %u32_ptr %access_1 | |
| %load = OpLoad %u32 %access_2 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, u32, read_write> = var undef | |
| %3:u32 = load %2 | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, Access_SignedIndices) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %i32 = OpTypeInt 32 1 | |
| %i32_1 = OpConstant %i32 1 | |
| %u32_2 = OpConstant %u32 2 | |
| %i32_3 = OpConstant %i32 3 | |
| %u32_4 = OpConstant %u32 4 | |
| %u32_42 = OpConstant %u32 42 | |
| %arr_inner = OpTypeArray %u32 %u32_4 | |
| %str = OpTypeStruct %arr_inner %arr_inner %arr_inner %arr_inner | |
| %arr_outer = OpTypeArray %str %u32_4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %arr_outer_ptr = OpTypePointer Function %arr_outer | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %arr_outer_ptr Function | |
| %access = OpAccessChain %u32_ptr %var %i32_1 %u32_2 %i32_3 | |
| %load = OpLoad %u32 %access | |
| OpStore %access %u32_42 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol:array<u32, 4> @offset(0) | |
| tint_symbol_1:array<u32, 4> @offset(16) | |
| tint_symbol_2:array<u32, 4> @offset(32) | |
| tint_symbol_3:array<u32, 4> @offset(48) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, array<tint_symbol_4, 4>, read_write> = var undef | |
| %3:ptr<function, u32, read_write> = access %2, 1i, 2u, 3i | |
| %4:u32 = load %3 | |
| store %3, 42u | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, InBoundsAccessChain) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_1 = OpConstant %u32 1 | |
| %u32_2 = OpConstant %u32 2 | |
| %u32_3 = OpConstant %u32 3 | |
| %u32_4 = OpConstant %u32 4 | |
| %u32_42 = OpConstant %u32 42 | |
| %arr_inner = OpTypeArray %u32 %u32_4 | |
| %str = OpTypeStruct %arr_inner %arr_inner %arr_inner %arr_inner | |
| %arr_outer = OpTypeArray %str %u32_4 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %arr_outer_ptr = OpTypePointer Function %arr_outer | |
| %ep_type = OpTypeFunction %void | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %var = OpVariable %arr_outer_ptr Function | |
| %access = OpInBoundsAccessChain %u32_ptr %var %u32_1 %u32_2 %u32_3 | |
| %load = OpLoad %u32 %access | |
| OpStore %access %u32_42 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol:array<u32, 4> @offset(0) | |
| tint_symbol_1:array<u32, 4> @offset(16) | |
| tint_symbol_2:array<u32, 4> @offset(32) | |
| tint_symbol_3:array<u32, 4> @offset(48) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B1: { | |
| %2:ptr<function, array<tint_symbol_4, 4>, read_write> = var undef | |
| %3:ptr<function, u32, read_write> = access %2, 1u, 2u, 3u | |
| %4:u32 = load %3 | |
| store %3, 42u | |
| ret | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, StorageBufferAccessMode) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpDecorate %str Block | |
| OpMemberDecorate %str 0 Offset 0 | |
| OpDecorate %ro_var NonWritable | |
| OpDecorate %ro_var DescriptorSet 1 | |
| OpDecorate %ro_var Binding 2 | |
| OpDecorate %rw_var DescriptorSet 1 | |
| OpDecorate %rw_var Binding 3 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %str = OpTypeStruct %u32 | |
| %u32_ptr = OpTypePointer StorageBuffer %u32 | |
| %str_ptr = OpTypePointer StorageBuffer %str | |
| %ep_type = OpTypeFunction %void | |
| %u32_0 = OpConstant %u32 0 | |
| %ro_var = OpVariable %str_ptr StorageBuffer | |
| %rw_var = OpVariable %str_ptr StorageBuffer | |
| %main = OpFunction %void None %ep_type | |
| %main_start = OpLabel | |
| %ro_access = OpAccessChain %u32_ptr %ro_var %u32_0 | |
| %rw_access = OpAccessChain %u32_ptr %rw_var %u32_0 | |
| %load = OpLoad %u32 %ro_access | |
| OpStore %rw_access %load | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol_1 = struct @align(4) { | |
| tint_symbol:u32 @offset(0) | |
| } | |
| $B1: { # root | |
| %1:ptr<storage, tint_symbol_1, read> = var undef @binding_point(1, 2) | |
| %2:ptr<storage, tint_symbol_1, read_write> = var undef @binding_point(1, 3) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B2: { | |
| %4:ptr<storage, u32, read> = access %1, 0u | |
| %5:ptr<storage, u32, read_write> = access %2, 0u | |
| %6:u32 = load %4 | |
| store %5, %6 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| TEST_F(SpirvParserTest, RuntimeArray_ArrayStride) { | |
| EXPECT_IR(R"( | |
| OpCapability Shader | |
| OpExtension "SPV_KHR_storage_buffer_storage_class" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint GLCompute %main "main" | |
| OpExecutionMode %main LocalSize 1 1 1 | |
| OpName %myvar "myvar" | |
| OpMemberName %struct 0 "first" | |
| OpMemberName %struct 1 "rtarr" | |
| OpDecorate %myvar DescriptorSet 0 | |
| OpDecorate %myvar Binding 0 | |
| OpDecorate %struct Block | |
| OpDecorate %arr ArrayStride 64 | |
| OpMemberDecorate %struct 0 Offset 0 | |
| OpMemberDecorate %struct 1 Offset 4 | |
| %void = OpTypeVoid | |
| %u32 = OpTypeInt 32 0 | |
| %u32_ptr = OpTypePointer Function %u32 | |
| %ep_type = OpTypeFunction %void | |
| %arr = OpTypeRuntimeArray %u32 | |
| %struct = OpTypeStruct %u32 %arr | |
| %ptr_struct = OpTypePointer StorageBuffer %struct | |
| %myvar = OpVariable %ptr_struct StorageBuffer | |
| %main = OpFunction %void None %ep_type | |
| %entry = OpLabel | |
| %1 = OpArrayLength %u32 %myvar 1 | |
| OpReturn | |
| OpFunctionEnd | |
| )", | |
| R"( | |
| tint_symbol = struct @align(4) { | |
| first:u32 @offset(0) | |
| rtarr:spirv.explicit_layout_array<u32, stride=64> @offset(4) | |
| } | |
| $B1: { # root | |
| %myvar:ptr<storage, tint_symbol, read_write> = var undef @binding_point(0, 0) | |
| } | |
| %main = @compute @workgroup_size(1u, 1u, 1u) func():void { | |
| $B2: { | |
| %3:ptr<storage, spirv.explicit_layout_array<u32, stride=64>, read_write> = access %myvar, 1u | |
| %4:u32 = arrayLength %3 | |
| ret | |
| } | |
| } | |
| )"); | |
| } | |
| } // namespace | |
| } // namespace tint::spirv::reader |