// Copyright 2021 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/hlsl.h" #include "src/transform/test_helper.h" namespace tint { namespace transform { namespace { using HlslTest = TransformTest; TEST_F(HlslTest, PromoteArrayInitializerToConstVar_Basic) { auto* src = R"( [[stage(vertex)]] fn main() -> void { var f0 : f32 = 1.0; var f1 : f32 = 2.0; var f2 : f32 = 3.0; var f3 : f32 = 4.0; var i : i32 = array(f0, f1, f2, f3)[2]; } )"; auto* expect = R"( [[stage(vertex)]] fn main() -> void { var f0 : f32 = 1.0; var f1 : f32 = 2.0; var f2 : f32 = 3.0; var f3 : f32 = 4.0; const tint_symbol_1 : array = array(f0, f1, f2, f3); var i : i32 = tint_symbol_1[2]; } )"; auto got = Run(src); EXPECT_EQ(expect, str(got)); } TEST_F(HlslTest, PromoteArrayInitializerToConstVar_ArrayInArray) { auto* src = R"( [[stage(vertex)]] fn main() -> void { var i : i32 = array, 2>(array(1.0, 2.0), array(3.0, 4.0))[0][1]; } )"; auto* expect = R"( [[stage(vertex)]] fn main() -> void { const tint_symbol_1 : array = array(1.0, 2.0); const tint_symbol_2 : array = array(3.0, 4.0); const tint_symbol_3 : array, 2> = array, 2>(tint_symbol_1, tint_symbol_2); var i : i32 = tint_symbol_3[0][1]; } )"; auto got = Run(src); EXPECT_EQ(expect, str(got)); } TEST_F(HlslTest, PromoteArrayInitializerToConstVar_NoChangeOnArrayVarDecl) { auto* src = R"( [[stage(vertex)]] fn main() -> void { var local_arr : array = array(0.0, 1.0, 2.0, 3.0); } const module_arr : array = array(0.0, 1.0, 2.0, 3.0); )"; auto* expect = src; auto got = Run(src); EXPECT_EQ(expect, str(got)); } TEST_F(HlslTest, PromoteArrayInitializerToConstVar_Bug406) { // See crbug.com/tint/406 auto* src = R"( [[block]] struct Uniforms { transform : mat2x2; }; [[group(0), binding(0)]] var ubo : Uniforms; [[builtin(vertex_index)]] var vertex_index : u32; [[builtin(position)]] var position : vec4; [[stage(vertex)]] fn main() -> void { const transform : mat2x2 = ubo.transform; var coord : array, 3> = array, 3>( vec2(-1.0, 1.0), vec2( 1.0, 1.0), vec2(-1.0, -1.0) )[vertex_index]; position = vec4(transform * coord, 0.0, 1.0); } )"; auto* expect = R"( [[block]] struct Uniforms { transform : mat2x2; }; [[group(0), binding(0)]] var ubo : Uniforms; [[builtin(vertex_index)]] var vertex_index : u32; [[builtin(position)]] var position : vec4; [[stage(vertex)]] fn main() -> void { const transform : mat2x2 = ubo.transform; const tint_symbol_1 : array, 3> = array, 3>(vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(-1.0, -1.0)); var coord : array, 3> = tint_symbol_1[vertex_index]; position = vec4((transform * coord), 0.0, 1.0); } )"; auto got = Run(src); EXPECT_EQ(expect, str(got)); } TEST_F(HlslTest, HandleEntryPointIOTypes_Parameters) { auto* src = R"( struct FragIn { [[location(2)]] loc2 : f32; }; [[stage(fragment)]] fn frag_main([[builtin(frag_coord)]] coord : vec4, [[location(1)]] loc1 : f32, frag_in : FragIn) -> void { var col : f32 = (coord.x * loc1 + frag_in.loc2); } )"; auto* expect = R"( struct tint_symbol_3 { [[builtin(frag_coord)]] coord : vec4; [[location(1)]] loc1 : f32; }; struct FragIn { [[location(2)]] loc2 : f32; }; [[stage(fragment)]] fn frag_main(tint_symbol_4 : tint_symbol_3, frag_in : FragIn) -> void { const coord : vec4 = tint_symbol_4.coord; const loc1 : f32 = tint_symbol_4.loc1; var col : f32 = ((coord.x * loc1) + frag_in.loc2); } )"; auto got = Transform(src); EXPECT_EQ(expect, str(got)); } TEST_F(HlslTest, HandleEntryPointIOTypes_OnlyStructParameters) { // Expect no change. auto* src = R"( struct FragBuiltins { [[builtin(frag_coord)]] coord : vec4; }; struct FragInputs { [[location(1)]] loc1 : f32; [[location(2)]] loc2 : vec4; }; [[stage(fragment)]] fn frag_main(builtins : FragBuiltins, inputs : FragInputs) -> void { var col : f32 = (builtins.coord.x * inputs.loc1); } )"; auto got = Transform(src); EXPECT_EQ(src, str(got)); } TEST_F(HlslTest, HandleEntryPointIOTypes_Parameters_EmptyBody) { auto* src = R"( [[stage(fragment)]] fn frag_main([[builtin(frag_coord)]] coord : vec4, [[location(1)]] loc1 : f32, [[location(2)]] loc2 : vec4) -> void { } )"; auto* expect = R"( struct tint_symbol_4 { [[builtin(frag_coord)]] coord : vec4; [[location(1)]] loc1 : f32; [[location(2)]] loc2 : vec4; }; [[stage(fragment)]] fn frag_main(tint_symbol_5 : tint_symbol_4) -> void { const coord : vec4 = tint_symbol_5.coord; const loc1 : f32 = tint_symbol_5.loc1; const loc2 : vec4 = tint_symbol_5.loc2; } )"; auto got = Transform(src); EXPECT_EQ(expect, str(got)); } } // namespace } // namespace transform } // namespace tint