// Copyright 2020 The Tint Authors. // // 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 "src/transform/vertex_pulling.h" #include #include "src/transform/test_helper.h" namespace tint { namespace transform { namespace { using VertexPullingTest = TransformTest; TEST_F(VertexPullingTest, Error_NoEntryPoint) { auto* src = ""; auto* expect = "error: Vertex stage entry point not found"; DataMap data; data.Add(); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, Error_InvalidEntryPoint) { auto* src = R"( [[stage(vertex)]] fn main() -> [[builtin(position)]] vec4 { return vec4(); } )"; auto* expect = "error: Vertex stage entry point not found"; VertexPulling::Config cfg; cfg.entry_point_name = "_"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, Error_EntryPointWrongStage) { auto* src = R"( [[stage(fragment)]] fn main() {} )"; auto* expect = "error: Vertex stage entry point not found"; VertexPulling::Config cfg; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, Error_BadStride) { auto* src = R"( [[stage(vertex)]] fn main([[location(0)]] var_a : f32) -> [[builtin(position)]] vec4 { return vec4(var_a, 0.0, 0.0, 1.0); } )"; auto* expect = "error: WebGPU requires that vertex stride must be a multiple of 4 " "bytes, but VertexPulling array stride for buffer 0 was 15 bytes"; VertexPulling::Config cfg; cfg.vertex_state = { {{15, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}}}}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, BasicModule) { auto* src = R"( [[stage(vertex)]] fn main() -> [[builtin(position)]] vec4 { return vec4(); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[stage(vertex)]] fn main() -> [[builtin(position)]] vec4 { return vec4(); } )"; VertexPulling::Config cfg; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, OneAttribute) { auto* src = R"( [[stage(vertex)]] fn main([[location(0)]] var_a : f32) -> [[builtin(position)]] vec4 { return vec4(var_a, 0.0, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[stage(vertex)]] fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4 { var var_a : f32; { let buffer_array_base_0 = tint_pulling_vertex_index; var_a = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]); } return vec4(var_a, 0.0, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = { {{4, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}}}}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, OneInstancedAttribute) { auto* src = R"( [[stage(vertex)]] fn main([[location(0)]] var_a : f32) -> [[builtin(position)]] vec4 { return vec4(var_a, 0.0, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[stage(vertex)]] fn main([[builtin(instance_index)]] tint_pulling_instance_index : u32) -> [[builtin(position)]] vec4 { var var_a : f32; { let buffer_array_base_0 = tint_pulling_instance_index; var_a = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]); } return vec4(var_a, 0.0, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = { {{4, VertexStepMode::kInstance, {{VertexFormat::kFloat32, 0, 0}}}}}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, OneAttributeDifferentOutputSet) { auto* src = R"( [[stage(vertex)]] fn main([[location(0)]] var_a : f32) -> [[builtin(position)]] vec4 { return vec4(var_a, 0.0, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(5)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[stage(vertex)]] fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4 { var var_a : f32; { let buffer_array_base_0 = tint_pulling_vertex_index; var_a = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]); } return vec4(var_a, 0.0, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = { {{4, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}}}}; cfg.pulling_group = 5; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, OneAttribute_Struct) { auto* src = R"( struct Inputs { [[location(0)]] var_a : f32; }; [[stage(vertex)]] fn main(inputs : Inputs) -> [[builtin(position)]] vec4 { return vec4(inputs.var_a, 0.0, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; struct Inputs { [[location(0)]] var_a : f32; }; [[stage(vertex)]] fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4 { var inputs : Inputs; { let buffer_array_base_0 = tint_pulling_vertex_index; inputs.var_a = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]); } return vec4(inputs.var_a, 0.0, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = { {{4, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}}}}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } // We expect the transform to use an existing builtin variables if it finds them TEST_F(VertexPullingTest, ExistingVertexIndexAndInstanceIndex) { auto* src = R"( [[stage(vertex)]] fn main([[location(0)]] var_a : f32, [[location(1)]] var_b : f32, [[builtin(vertex_index)]] custom_vertex_index : u32, [[builtin(instance_index)]] custom_instance_index : u32 ) -> [[builtin(position)]] vec4 { return vec4(var_a, var_b, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[binding(1), group(4)]] var tint_pulling_vertex_buffer_1 : TintVertexData; [[stage(vertex)]] fn main([[builtin(vertex_index)]] custom_vertex_index : u32, [[builtin(instance_index)]] custom_instance_index : u32) -> [[builtin(position)]] vec4 { var var_a : f32; var var_b : f32; { let buffer_array_base_0 = custom_vertex_index; var_a = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]); let buffer_array_base_1 = custom_instance_index; var_b = bitcast(tint_pulling_vertex_buffer_1.tint_vertex_data[buffer_array_base_1]); } return vec4(var_a, var_b, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = {{ { 4, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}, }, { 4, VertexStepMode::kInstance, {{VertexFormat::kFloat32, 0, 1}}, }, }}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, ExistingVertexIndexAndInstanceIndex_Struct) { auto* src = R"( struct Inputs { [[location(0)]] var_a : f32; [[location(1)]] var_b : f32; [[builtin(vertex_index)]] custom_vertex_index : u32; [[builtin(instance_index)]] custom_instance_index : u32; }; [[stage(vertex)]] fn main(inputs : Inputs) -> [[builtin(position)]] vec4 { return vec4(inputs.var_a, inputs.var_b, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[binding(1), group(4)]] var tint_pulling_vertex_buffer_1 : TintVertexData; struct tint_symbol { [[builtin(vertex_index)]] custom_vertex_index : u32; [[builtin(instance_index)]] custom_instance_index : u32; }; struct Inputs { [[location(0)]] var_a : f32; [[location(1)]] var_b : f32; [[builtin(vertex_index)]] custom_vertex_index : u32; [[builtin(instance_index)]] custom_instance_index : u32; }; [[stage(vertex)]] fn main(tint_symbol_1 : tint_symbol) -> [[builtin(position)]] vec4 { var inputs : Inputs; inputs.custom_vertex_index = tint_symbol_1.custom_vertex_index; inputs.custom_instance_index = tint_symbol_1.custom_instance_index; { let buffer_array_base_0 = inputs.custom_vertex_index; inputs.var_a = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]); let buffer_array_base_1 = inputs.custom_instance_index; inputs.var_b = bitcast(tint_pulling_vertex_buffer_1.tint_vertex_data[buffer_array_base_1]); } return vec4(inputs.var_a, inputs.var_b, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = {{ { 4, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}, }, { 4, VertexStepMode::kInstance, {{VertexFormat::kFloat32, 0, 1}}, }, }}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, ExistingVertexIndexAndInstanceIndex_SeparateStruct) { auto* src = R"( struct Inputs { [[location(0)]] var_a : f32; [[location(1)]] var_b : f32; }; struct Indices { [[builtin(vertex_index)]] custom_vertex_index : u32; [[builtin(instance_index)]] custom_instance_index : u32; }; [[stage(vertex)]] fn main(inputs : Inputs, indices : Indices) -> [[builtin(position)]] vec4 { return vec4(inputs.var_a, inputs.var_b, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[binding(1), group(4)]] var tint_pulling_vertex_buffer_1 : TintVertexData; struct Inputs { [[location(0)]] var_a : f32; [[location(1)]] var_b : f32; }; struct Indices { [[builtin(vertex_index)]] custom_vertex_index : u32; [[builtin(instance_index)]] custom_instance_index : u32; }; [[stage(vertex)]] fn main(indices : Indices) -> [[builtin(position)]] vec4 { var inputs : Inputs; { let buffer_array_base_0 = indices.custom_vertex_index; inputs.var_a = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]); let buffer_array_base_1 = indices.custom_instance_index; inputs.var_b = bitcast(tint_pulling_vertex_buffer_1.tint_vertex_data[buffer_array_base_1]); } return vec4(inputs.var_a, inputs.var_b, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = {{ { 4, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}}, }, { 4, VertexStepMode::kInstance, {{VertexFormat::kFloat32, 0, 1}}, }, }}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, TwoAttributesSameBuffer) { auto* src = R"( [[stage(vertex)]] fn main([[location(0)]] var_a : f32, [[location(1)]] var_b : vec4) -> [[builtin(position)]] vec4 { return vec4(); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[stage(vertex)]] fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4 { var var_a : f32; var var_b : vec4; { let buffer_array_base_0 = (tint_pulling_vertex_index * 4u); var_a = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]); var_b = vec4(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 1u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 2u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 3u)])); } return vec4(); } )"; VertexPulling::Config cfg; cfg.vertex_state = { {{16, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}, {VertexFormat::kFloat32x4, 0, 1}}}}}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, FloatVectorAttributes) { auto* src = R"( [[stage(vertex)]] fn main([[location(0)]] var_a : vec2, [[location(1)]] var_b : vec3, [[location(2)]] var_c : vec4 ) -> [[builtin(position)]] vec4 { return vec4(); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[binding(1), group(4)]] var tint_pulling_vertex_buffer_1 : TintVertexData; [[binding(2), group(4)]] var tint_pulling_vertex_buffer_2 : TintVertexData; [[stage(vertex)]] fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4 { var var_a : vec2; var var_b : vec3; var var_c : vec4; { let buffer_array_base_0 = (tint_pulling_vertex_index * 2u); var_a = vec2(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[buffer_array_base_0]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 1u)])); let buffer_array_base_1 = (tint_pulling_vertex_index * 3u); var_b = vec3(bitcast(tint_pulling_vertex_buffer_1.tint_vertex_data[buffer_array_base_1]), bitcast(tint_pulling_vertex_buffer_1.tint_vertex_data[(buffer_array_base_1 + 1u)]), bitcast(tint_pulling_vertex_buffer_1.tint_vertex_data[(buffer_array_base_1 + 2u)])); let buffer_array_base_2 = (tint_pulling_vertex_index * 4u); var_c = vec4(bitcast(tint_pulling_vertex_buffer_2.tint_vertex_data[buffer_array_base_2]), bitcast(tint_pulling_vertex_buffer_2.tint_vertex_data[(buffer_array_base_2 + 1u)]), bitcast(tint_pulling_vertex_buffer_2.tint_vertex_data[(buffer_array_base_2 + 2u)]), bitcast(tint_pulling_vertex_buffer_2.tint_vertex_data[(buffer_array_base_2 + 3u)])); } return vec4(); } )"; VertexPulling::Config cfg; cfg.vertex_state = {{ {8, VertexStepMode::kVertex, {{VertexFormat::kFloat32x2, 0, 0}}}, {12, VertexStepMode::kVertex, {{VertexFormat::kFloat32x3, 0, 1}}}, {16, VertexStepMode::kVertex, {{VertexFormat::kFloat32x4, 0, 2}}}, }}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, AttemptSymbolCollision) { auto* src = R"( [[stage(vertex)]] fn main([[location(0)]] var_a : f32, [[location(1)]] var_b : vec4) -> [[builtin(position)]] vec4 { var tint_pulling_vertex_index : i32; var tint_pulling_vertex_buffer_0 : i32; var tint_vertex_data : i32; var tint_pulling_pos : i32; return vec4(); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data_1 : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0_1 : TintVertexData; [[stage(vertex)]] fn main([[builtin(vertex_index)]] tint_pulling_vertex_index_1 : u32) -> [[builtin(position)]] vec4 { var var_a : f32; var var_b : vec4; { let buffer_array_base_0 = (tint_pulling_vertex_index_1 * 4u); var_a = bitcast(tint_pulling_vertex_buffer_0_1.tint_vertex_data_1[buffer_array_base_0]); var_b = vec4(bitcast(tint_pulling_vertex_buffer_0_1.tint_vertex_data_1[buffer_array_base_0]), bitcast(tint_pulling_vertex_buffer_0_1.tint_vertex_data_1[(buffer_array_base_0 + 1u)]), bitcast(tint_pulling_vertex_buffer_0_1.tint_vertex_data_1[(buffer_array_base_0 + 2u)]), bitcast(tint_pulling_vertex_buffer_0_1.tint_vertex_data_1[(buffer_array_base_0 + 3u)])); } var tint_pulling_vertex_index : i32; var tint_pulling_vertex_buffer_0 : i32; var tint_vertex_data : i32; var tint_pulling_pos : i32; return vec4(); } )"; VertexPulling::Config cfg; cfg.vertex_state = { {{16, VertexStepMode::kVertex, {{VertexFormat::kFloat32, 0, 0}, {VertexFormat::kFloat32x4, 0, 1}}}}}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, std::move(data)); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, FormatsAligned) { auto* src = R"( [[stage(vertex)]] fn main( [[location(0)]] uint8x2 : vec2, [[location(1)]] uint8x4 : vec4, [[location(2)]] sint8x2 : vec2, [[location(3)]] sint8x4 : vec4, [[location(4)]] unorm8x2 : vec2, [[location(5)]] unorm8x4 : vec4, [[location(6)]] snorm8x2 : vec2, [[location(7)]] snorm8x4 : vec4, [[location(8)]] uint16x2 : vec2, [[location(9)]] uint16x4 : vec4, [[location(10)]] sint16x2 : vec2, [[location(11)]] sint16x4 : vec4, [[location(12)]] unorm16x2 : vec2, [[location(13)]] unorm16x4 : vec4, [[location(14)]] snorm16x2 : vec2, [[location(15)]] snorm16x4 : vec4, [[location(16)]] float16x2 : vec2, [[location(17)]] float16x4 : vec4, [[location(18)]] float32 : f32, [[location(19)]] float32x2 : vec2, [[location(20)]] float32x3 : vec3, [[location(21)]] float32x4 : vec4, [[location(22)]] uint32 : u32, [[location(23)]] uint32x2 : vec2, [[location(24)]] uint32x3 : vec3, [[location(25)]] uint32x4 : vec4, [[location(26)]] sint32 : i32, [[location(27)]] sint32x2 : vec2, [[location(28)]] sint32x3 : vec3, [[location(29)]] sint32x4 : vec4 ) -> [[builtin(position)]] vec4 { return vec4(0.0, 0.0, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[stage(vertex)]] fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4 { var uint8x2 : vec2; var uint8x4 : vec4; var sint8x2 : vec2; var sint8x4 : vec4; var unorm8x2 : vec2; var unorm8x4 : vec4; var snorm8x2 : vec2; var snorm8x4 : vec4; var uint16x2 : vec2; var uint16x4 : vec4; var sint16x2 : vec2; var sint16x4 : vec4; var unorm16x2 : vec2; var unorm16x4 : vec4; var snorm16x2 : vec2; var snorm16x4 : vec4; var float16x2 : vec2; var float16x4 : vec4; var float32 : f32; var float32x2 : vec2; var float32x3 : vec3; var float32x4 : vec4; var uint32 : u32; var uint32x2 : vec2; var uint32x3 : vec3; var uint32x4 : vec4; var sint32 : i32; var sint32x2 : vec2; var sint32x3 : vec3; var sint32x4 : vec4; { let buffer_array_base_0 = (tint_pulling_vertex_index * 64u); uint8x2 = ((vec2((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 16u)) << vec2(8u, 0u)) >> vec2(24u)); uint8x4 = ((vec4(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]) << vec4(24u, 16u, 8u, 0u)) >> vec4(24u)); sint8x2 = ((vec2(bitcast((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 16u))) << vec2(8u, 0u)) >> vec2(24u)); sint8x4 = ((vec4(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)])) << vec4(24u, 16u, 8u, 0u)) >> vec4(24u)); unorm8x2 = unpack4x8unorm((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] & 65535u)).xy; unorm8x4 = unpack4x8unorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]); snorm8x2 = unpack4x8snorm((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] & 65535u)).xy; snorm8x4 = unpack4x8snorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]); uint16x2 = ((vec2(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]) << vec2(16u, 0u)) >> vec2(16u)); uint16x4 = ((vec2(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]).xxyy << vec4(16u, 0u, 16u, 0u)) >> vec4(16u)); sint16x2 = ((vec2(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)])) << vec2(16u, 0u)) >> vec2(16u)); sint16x4 = ((vec2(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])).xxyy << vec4(16u, 0u, 16u, 0u)) >> vec4(16u)); unorm16x2 = unpack2x16unorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]); unorm16x4 = vec4(unpack2x16unorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), unpack2x16unorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])); snorm16x2 = unpack2x16snorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]); snorm16x4 = vec4(unpack2x16snorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), unpack2x16snorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])); float16x2 = unpack2x16float(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]); float16x4 = vec4(unpack2x16float(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), unpack2x16float(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])); float32 = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]); float32x2 = vec2(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])); float32x3 = vec3(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)])); float32x4 = vec4(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)])); uint32 = tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]; uint32x2 = vec2(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]); uint32x3 = vec3(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]); uint32x4 = vec4(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)]); sint32 = bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]); sint32x2 = vec2(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])); sint32x3 = vec3(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)])); sint32x4 = vec4(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)])); } return vec4(0.0, 0.0, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = {{{256, VertexStepMode::kVertex, { {VertexFormat::kUint8x2, 64, 0}, {VertexFormat::kUint8x4, 64, 1}, {VertexFormat::kSint8x2, 64, 2}, {VertexFormat::kSint8x4, 64, 3}, {VertexFormat::kUnorm8x2, 64, 4}, {VertexFormat::kUnorm8x4, 64, 5}, {VertexFormat::kSnorm8x2, 64, 6}, {VertexFormat::kSnorm8x4, 64, 7}, {VertexFormat::kUint16x2, 64, 8}, {VertexFormat::kUint16x4, 64, 9}, {VertexFormat::kSint16x2, 64, 10}, {VertexFormat::kSint16x4, 64, 11}, {VertexFormat::kUnorm16x2, 64, 12}, {VertexFormat::kUnorm16x4, 64, 13}, {VertexFormat::kSnorm16x2, 64, 14}, {VertexFormat::kSnorm16x4, 64, 15}, {VertexFormat::kFloat16x2, 64, 16}, {VertexFormat::kFloat16x4, 64, 17}, {VertexFormat::kFloat32, 64, 18}, {VertexFormat::kFloat32x2, 64, 19}, {VertexFormat::kFloat32x3, 64, 20}, {VertexFormat::kFloat32x4, 64, 21}, {VertexFormat::kUint32, 64, 22}, {VertexFormat::kUint32x2, 64, 23}, {VertexFormat::kUint32x3, 64, 24}, {VertexFormat::kUint32x4, 64, 25}, {VertexFormat::kSint32, 64, 26}, {VertexFormat::kSint32x2, 64, 27}, {VertexFormat::kSint32x3, 64, 28}, {VertexFormat::kSint32x4, 64, 29}, }}}}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, FormatsStrideUnaligned) { auto* src = R"( [[stage(vertex)]] fn main( [[location(0)]] uint8x2 : vec2, [[location(1)]] uint8x4 : vec4, [[location(2)]] sint8x2 : vec2, [[location(3)]] sint8x4 : vec4, [[location(4)]] unorm8x2 : vec2, [[location(5)]] unorm8x4 : vec4, [[location(6)]] snorm8x2 : vec2, [[location(7)]] snorm8x4 : vec4, [[location(8)]] uint16x2 : vec2, [[location(9)]] uint16x4 : vec4, [[location(10)]] sint16x2 : vec2, [[location(11)]] sint16x4 : vec4, [[location(12)]] unorm16x2 : vec2, [[location(13)]] unorm16x4 : vec4, [[location(14)]] snorm16x2 : vec2, [[location(15)]] snorm16x4 : vec4, [[location(16)]] float16x2 : vec2, [[location(17)]] float16x4 : vec4, [[location(18)]] float32 : f32, [[location(19)]] float32x2 : vec2, [[location(20)]] float32x3 : vec3, [[location(21)]] float32x4 : vec4, [[location(22)]] uint32 : u32, [[location(23)]] uint32x2 : vec2, [[location(24)]] uint32x3 : vec3, [[location(25)]] uint32x4 : vec4, [[location(26)]] sint32 : i32, [[location(27)]] sint32x2 : vec2, [[location(28)]] sint32x3 : vec3, [[location(29)]] sint32x4 : vec4 ) -> [[builtin(position)]] vec4 { return vec4(0.0, 0.0, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[stage(vertex)]] fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4 { var uint8x2 : vec2; var uint8x4 : vec4; var sint8x2 : vec2; var sint8x4 : vec4; var unorm8x2 : vec2; var unorm8x4 : vec4; var snorm8x2 : vec2; var snorm8x4 : vec4; var uint16x2 : vec2; var uint16x4 : vec4; var sint16x2 : vec2; var sint16x4 : vec4; var unorm16x2 : vec2; var unorm16x4 : vec4; var snorm16x2 : vec2; var snorm16x4 : vec4; var float16x2 : vec2; var float16x4 : vec4; var float32 : f32; var float32x2 : vec2; var float32x3 : vec3; var float32x4 : vec4; var uint32 : u32; var uint32x2 : vec2; var uint32x3 : vec3; var uint32x4 : vec4; var sint32 : i32; var sint32x2 : vec2; var sint32x3 : vec3; var sint32x4 : vec4; { let buffer_array_base_0 = (tint_pulling_vertex_index * 64u); uint8x2 = ((vec2((((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 8u)) & 4294901760u)) << vec2(8u, 0u)) >> vec2(24u)); uint8x4 = ((vec4(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))) << vec4(24u, 16u, 8u, 0u)) >> vec4(24u)); sint8x2 = ((vec2(bitcast((((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 8u)) & 4294901760u))) << vec2(8u, 0u)) >> vec2(24u)); sint8x4 = ((vec4(bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u)))) << vec4(24u, 16u, 8u, 0u)) >> vec4(24u)); unorm8x2 = unpack4x8unorm((((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u)) & 65535u)).xy; unorm8x4 = unpack4x8unorm(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))); snorm8x2 = unpack4x8snorm((((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u)) & 65535u)).xy; snorm8x4 = unpack4x8snorm(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))); uint16x2 = ((vec2(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))) << vec2(16u, 0u)) >> vec2(16u)); uint16x4 = ((vec2(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u)), ((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u))).xxyy << vec4(16u, 0u, 16u, 0u)) >> vec4(16u)); sint16x2 = ((vec2(bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u)))) << vec2(16u, 0u)) >> vec2(16u)); sint16x4 = ((vec2(bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u)))).xxyy << vec4(16u, 0u, 16u, 0u)) >> vec4(16u)); unorm16x2 = unpack2x16unorm(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))); unorm16x4 = vec4(unpack2x16unorm(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), unpack2x16unorm(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u)))); snorm16x2 = unpack2x16snorm(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))); snorm16x4 = vec4(unpack2x16snorm(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), unpack2x16snorm(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u)))); float16x2 = unpack2x16float(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))); float16x4 = vec4(unpack2x16float(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), unpack2x16float(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u)))); float32 = bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))); float32x2 = vec2(bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u)))); float32x3 = vec3(bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] << 8u)))); float32x4 = vec4(bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)] << 8u)))); uint32 = ((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u)); uint32x2 = vec2(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u)), ((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u))); uint32x3 = vec3(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u)), ((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u)), ((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] << 8u))); uint32x4 = vec4(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u)), ((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u)), ((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] << 8u)), ((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)] << 8u))); sint32 = bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))); sint32x2 = vec2(bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u)))); sint32x3 = vec3(bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] << 8u)))); sint32x4 = vec4(bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 15u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] << 8u))), bitcast(((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)] >> 24u) | (tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)] << 8u)))); } return vec4(0.0, 0.0, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = {{{256, VertexStepMode::kVertex, { {VertexFormat::kUint8x2, 63, 0}, {VertexFormat::kUint8x4, 63, 1}, {VertexFormat::kSint8x2, 63, 2}, {VertexFormat::kSint8x4, 63, 3}, {VertexFormat::kUnorm8x2, 63, 4}, {VertexFormat::kUnorm8x4, 63, 5}, {VertexFormat::kSnorm8x2, 63, 6}, {VertexFormat::kSnorm8x4, 63, 7}, {VertexFormat::kUint16x2, 63, 8}, {VertexFormat::kUint16x4, 63, 9}, {VertexFormat::kSint16x2, 63, 10}, {VertexFormat::kSint16x4, 63, 11}, {VertexFormat::kUnorm16x2, 63, 12}, {VertexFormat::kUnorm16x4, 63, 13}, {VertexFormat::kSnorm16x2, 63, 14}, {VertexFormat::kSnorm16x4, 63, 15}, {VertexFormat::kFloat16x2, 63, 16}, {VertexFormat::kFloat16x4, 63, 17}, {VertexFormat::kFloat32, 63, 18}, {VertexFormat::kFloat32x2, 63, 19}, {VertexFormat::kFloat32x3, 63, 20}, {VertexFormat::kFloat32x4, 63, 21}, {VertexFormat::kUint32, 63, 22}, {VertexFormat::kUint32x2, 63, 23}, {VertexFormat::kUint32x3, 63, 24}, {VertexFormat::kUint32x4, 63, 25}, {VertexFormat::kSint32, 63, 26}, {VertexFormat::kSint32x2, 63, 27}, {VertexFormat::kSint32x3, 63, 28}, {VertexFormat::kSint32x4, 63, 29}, }}}}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } TEST_F(VertexPullingTest, FormatsWithVectorsResized) { auto* src = R"( [[stage(vertex)]] fn main( [[location(0)]] uint8x2 : vec3, [[location(1)]] uint8x4 : vec2, [[location(2)]] sint8x2 : i32, [[location(3)]] sint8x4 : vec2, [[location(4)]] unorm8x2 : vec4, [[location(5)]] unorm8x4 : f32, [[location(6)]] snorm8x2 : vec3, [[location(7)]] snorm8x4 : f32, [[location(8)]] uint16x2 : vec3, [[location(9)]] uint16x4 : vec2, [[location(10)]] sint16x2 : vec4, [[location(11)]] sint16x4 : i32, [[location(12)]] unorm16x2 : vec3, [[location(13)]] unorm16x4 : f32, [[location(14)]] snorm16x2 : vec4, [[location(15)]] snorm16x4 : vec3, [[location(16)]] float16x2 : vec4, [[location(17)]] float16x4 : f32, [[location(18)]] float32 : vec4, [[location(19)]] float32x2 : vec4, [[location(20)]] float32x3 : vec2, [[location(21)]] float32x4 : vec3, [[location(22)]] uint32 : vec3, [[location(23)]] uint32x2 : vec4, [[location(24)]] uint32x3 : vec4, [[location(25)]] uint32x4 : vec2, [[location(26)]] sint32 : vec4, [[location(27)]] sint32x2 : vec3, [[location(28)]] sint32x3 : i32, [[location(29)]] sint32x4 : vec2 ) -> [[builtin(position)]] vec4 { return vec4(0.0, 0.0, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct TintVertexData { tint_vertex_data : [[stride(4)]] array; }; [[binding(0), group(4)]] var tint_pulling_vertex_buffer_0 : TintVertexData; [[stage(vertex)]] fn main([[builtin(vertex_index)]] tint_pulling_vertex_index : u32) -> [[builtin(position)]] vec4 { var uint8x2 : vec3; var uint8x4 : vec2; var sint8x2 : i32; var sint8x4 : vec2; var unorm8x2 : vec4; var unorm8x4 : f32; var snorm8x2 : vec3; var snorm8x4 : f32; var uint16x2 : vec3; var uint16x4 : vec2; var sint16x2 : vec4; var sint16x4 : i32; var unorm16x2 : vec3; var unorm16x4 : f32; var snorm16x2 : vec4; var snorm16x4 : vec3; var float16x2 : vec4; var float16x4 : f32; var float32 : vec4; var float32x2 : vec4; var float32x3 : vec2; var float32x4 : vec3; var uint32 : vec3; var uint32x2 : vec4; var uint32x3 : vec4; var uint32x4 : vec2; var sint32 : vec4; var sint32x2 : vec3; var sint32x3 : i32; var sint32x4 : vec2; { let buffer_array_base_0 = (tint_pulling_vertex_index * 64u); uint8x2 = vec3(((vec2((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 16u)) << vec2(8u, 0u)) >> vec2(24u)), 0u); uint8x4 = (((vec4(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]) << vec4(24u, 16u, 8u, 0u)) >> vec4(24u))).xy; sint8x2 = (((vec2(bitcast((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] << 16u))) << vec2(8u, 0u)) >> vec2(24u))).x; sint8x4 = (((vec4(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)])) << vec4(24u, 16u, 8u, 0u)) >> vec4(24u))).xy; unorm8x2 = vec4(unpack4x8unorm((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] & 65535u)).xy, 0.0, 1.0); unorm8x4 = unpack4x8unorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]).x; snorm8x2 = vec3(unpack4x8snorm((tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)] & 65535u)).xy, 0.0); snorm8x4 = unpack4x8snorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]).x; uint16x2 = vec3(((vec2(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]) << vec2(16u, 0u)) >> vec2(16u)), 0u); uint16x4 = (((vec2(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]).xxyy << vec4(16u, 0u, 16u, 0u)) >> vec4(16u))).xy; sint16x2 = vec4(((vec2(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)])) << vec2(16u, 0u)) >> vec2(16u)), 0, 1); sint16x4 = (((vec2(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])).xxyy << vec4(16u, 0u, 16u, 0u)) >> vec4(16u))).x; unorm16x2 = vec3(unpack2x16unorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), 0.0); unorm16x4 = vec4(unpack2x16unorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), unpack2x16unorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])).x; snorm16x2 = vec4(unpack2x16snorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), 0.0, 1.0); snorm16x4 = vec4(unpack2x16snorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), unpack2x16snorm(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])).xyz; float16x2 = vec4(unpack2x16float(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), 0.0, 1.0); float16x4 = vec4(unpack2x16float(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), unpack2x16float(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])).x; float32 = vec4(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), 0.0, 0.0, 1.0); float32x2 = vec4(vec2(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])), 0.0, 1.0); float32x3 = vec3(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)])).xy; float32x4 = vec4(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)])).xyz; uint32 = vec3(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)], 0u, 0u); uint32x2 = vec4(vec2(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), 0u, 1u); uint32x3 = vec4(vec3(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]), 1u); uint32x4 = vec4(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)], tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)]).xy; sint32 = vec4(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), 0, 0, 1); sint32x2 = vec3(vec2(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)])), 0); sint32x3 = vec3(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)])).x; sint32x4 = vec4(bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 16u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 17u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 18u)]), bitcast(tint_pulling_vertex_buffer_0.tint_vertex_data[(buffer_array_base_0 + 19u)])).xy; } return vec4(0.0, 0.0, 0.0, 1.0); } )"; VertexPulling::Config cfg; cfg.vertex_state = {{{256, VertexStepMode::kVertex, { {VertexFormat::kUint8x2, 64, 0}, {VertexFormat::kUint8x4, 64, 1}, {VertexFormat::kSint8x2, 64, 2}, {VertexFormat::kSint8x4, 64, 3}, {VertexFormat::kUnorm8x2, 64, 4}, {VertexFormat::kUnorm8x4, 64, 5}, {VertexFormat::kSnorm8x2, 64, 6}, {VertexFormat::kSnorm8x4, 64, 7}, {VertexFormat::kUint16x2, 64, 8}, {VertexFormat::kUint16x4, 64, 9}, {VertexFormat::kSint16x2, 64, 10}, {VertexFormat::kSint16x4, 64, 11}, {VertexFormat::kUnorm16x2, 64, 12}, {VertexFormat::kUnorm16x4, 64, 13}, {VertexFormat::kSnorm16x2, 64, 14}, {VertexFormat::kSnorm16x4, 64, 15}, {VertexFormat::kFloat16x2, 64, 16}, {VertexFormat::kFloat16x4, 64, 17}, {VertexFormat::kFloat32, 64, 18}, {VertexFormat::kFloat32x2, 64, 19}, {VertexFormat::kFloat32x3, 64, 20}, {VertexFormat::kFloat32x4, 64, 21}, {VertexFormat::kUint32, 64, 22}, {VertexFormat::kUint32x2, 64, 23}, {VertexFormat::kUint32x3, 64, 24}, {VertexFormat::kUint32x4, 64, 25}, {VertexFormat::kSint32, 64, 26}, {VertexFormat::kSint32x2, 64, 27}, {VertexFormat::kSint32x3, 64, 28}, {VertexFormat::kSint32x4, 64, 29}, }}}}; cfg.entry_point_name = "main"; DataMap data; data.Add(cfg); auto got = Run(src, data); EXPECT_EQ(expect, str(got)); } } // namespace } // namespace transform } // namespace tint