diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index 081a3a2bd3..f9dd6b44c7 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -1224,7 +1224,7 @@ uint32_t Builder::GenerateTypeConstructorExpression( result_type->AsVector()->size() == value_type->AsVector()->size()); } if (can_cast_or_copy) { - return GenerateCastOrCopy(result_type, values[0]); + return GenerateCastOrCopyOrPassthrough(result_type, values[0]); } auto type_id = GenerateTypeIfNeeded(init->type()); @@ -1268,7 +1268,7 @@ uint32_t Builder::GenerateTypeConstructorExpression( // Both scalars, but not the same type so we need to generate a conversion // of the value. if (value_type->is_scalar() && result_type->is_scalar()) { - id = GenerateCastOrCopy(result_type, values[0]); + id = GenerateCastOrCopyOrPassthrough(result_type, values[0]); out << "_" << id; ops.push_back(Operand::Int(id)); continue; @@ -1351,8 +1351,8 @@ uint32_t Builder::GenerateTypeConstructorExpression( return result.to_i(); } -uint32_t Builder::GenerateCastOrCopy(ast::type::Type* to_type, - ast::Expression* from_expr) { +uint32_t Builder::GenerateCastOrCopyOrPassthrough(ast::type::Type* to_type, + ast::Expression* from_expr) { auto result = result_op(); auto result_id = result.to_i(); @@ -1388,8 +1388,9 @@ uint32_t Builder::GenerateCastOrCopy(ast::type::Type* to_type, } else if ((from_type->IsBool() && to_type->IsBool()) || (from_type->IsU32() && to_type->IsU32()) || (from_type->IsI32() && to_type->IsI32()) || - (from_type->IsF32() && to_type->IsF32())) { - op = spv::Op::OpCopyObject; + (from_type->IsF32() && to_type->IsF32()) || + (from_type->IsVector() && (from_type == to_type))) { + return val_id; } else if ((from_type->IsI32() && to_type->IsU32()) || (from_type->IsU32() && to_type->IsI32()) || (from_type->is_signed_integer_vector() && diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h index ac3f452561..7be24c6446 100644 --- a/src/writer/spirv/builder.h +++ b/src/writer/spirv/builder.h @@ -350,12 +350,14 @@ class Builder { uint32_t GenerateSampledImage(ast::type::Type* texture_type, Operand texture_operand, Operand sampler_operand); - /// Generates a cast or object copy for the expression result + /// Generates a cast or object copy for the expression result, + /// or return the ID generated the expression if it is already + /// of the right type. /// @param to_type the type we're casting too /// @param from_expr the expression to cast /// @returns the expression ID on success or 0 otherwise - uint32_t GenerateCastOrCopy(ast::type::Type* to_type, - ast::Expression* from_expr); + uint32_t GenerateCastOrCopyOrPassthrough(ast::type::Type* to_type, + ast::Expression* from_expr); /// Generates a loop statement /// @param stmt the statement to generate /// @returns true on successful generation diff --git a/src/writer/spirv/builder_constructor_expression_test.cc b/src/writer/spirv/builder_constructor_expression_test.cc index 308dd5057d..4ac92c047b 100644 --- a/src/writer/spirv/builder_constructor_expression_test.cc +++ b/src/writer/spirv/builder_constructor_expression_test.cc @@ -193,15 +193,13 @@ TEST_F(SpvBuilderConstructorTest, Type_Bool_With_Bool) { b.push_function(Function{}); - EXPECT_EQ(b.GenerateExpression(&cast), 1u); + EXPECT_EQ(b.GenerateExpression(&cast), 3u); ASSERT_FALSE(b.has_error()) << b.error(); EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeBool %3 = OpConstantTrue %2 )"); - EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), - R"(%1 = OpCopyObject %2 %3 -)"); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()"); } TEST_F(SpvBuilderConstructorTest, Type_I32_With_I32) { @@ -210,14 +208,12 @@ TEST_F(SpvBuilderConstructorTest, Type_I32_With_I32) { ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error(); b.push_function(Function{}); - EXPECT_EQ(b.GenerateExpression(&cast), 1u); + EXPECT_EQ(b.GenerateExpression(&cast), 3u); EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1 %3 = OpConstant %2 2 )"); - EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), - R"(%1 = OpCopyObject %2 %3 -)"); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()"); } TEST_F(SpvBuilderConstructorTest, Type_U32_With_U32) { @@ -226,14 +222,12 @@ TEST_F(SpvBuilderConstructorTest, Type_U32_With_U32) { ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error(); b.push_function(Function{}); - EXPECT_EQ(b.GenerateExpression(&cast), 1u); + EXPECT_EQ(b.GenerateExpression(&cast), 3u); EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 0 %3 = OpConstant %2 2 )"); - EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), - R"(%1 = OpCopyObject %2 %3 -)"); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()"); } TEST_F(SpvBuilderConstructorTest, Type_F32_With_F32) { @@ -242,14 +236,12 @@ TEST_F(SpvBuilderConstructorTest, Type_F32_With_F32) { ASSERT_TRUE(td.DetermineResultType(&cast)) << td.error(); b.push_function(Function{}); - EXPECT_EQ(b.GenerateExpression(&cast), 1u); + EXPECT_EQ(b.GenerateExpression(&cast), 3u); EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32 %3 = OpConstant %2 2 )"); - EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), - R"(%1 = OpCopyObject %2 %3 -)"); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()"); } TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F32_F32) { @@ -267,6 +259,23 @@ TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_F32_F32) { )"); } +TEST_F(SpvBuilderConstructorTest, Type_Vec2_With_Vec2) { + auto* value = vec2(2.0f, 2.0f); + auto* cast = vec2(value); + + ASSERT_TRUE(td.DetermineResultType(cast)) << td.error(); + + b.push_function(Function{}); + EXPECT_EQ(b.GenerateExpression(cast), 5u); + + EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 +%2 = OpTypeVector %3 2 +%4 = OpConstant %3 2 +%5 = OpConstantComposite %2 %4 %4 +)"); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()"); +} + TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_F32_F32_F32) { auto* cast = vec3(2.0f, 2.0f, 2.0f); @@ -324,6 +333,23 @@ TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec2_F32) { )"); } +TEST_F(SpvBuilderConstructorTest, Type_Vec3_With_Vec3) { + auto* value = vec3(2.0f, 2.0f, 2.0f); + auto* cast = vec3(value); + + ASSERT_TRUE(td.DetermineResultType(cast)) << td.error(); + + b.push_function(Function{}); + EXPECT_EQ(b.GenerateExpression(cast), 5u); + + EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 +%2 = OpTypeVector %3 3 +%4 = OpConstant %3 2 +%5 = OpConstantComposite %2 %4 %4 %4 +)"); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()"); +} + TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_F32_F32_F32_F32) { auto* cast = vec4(2.0f, 2.0f, 2.0f, 2.0f); @@ -469,6 +495,68 @@ TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec3_F32) { )"); } +TEST_F(SpvBuilderConstructorTest, Type_Vec4_With_Vec4) { + auto* value = vec4(2.0f, 2.0f, 2.0f, 2.0f); + auto* cast = vec4(value); + + ASSERT_TRUE(td.DetermineResultType(cast)) << td.error(); + + b.push_function(Function{}); + EXPECT_EQ(b.GenerateExpression(cast), 5u); + + EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 +%2 = OpTypeVector %3 4 +%4 = OpConstant %3 2 +%5 = OpConstantComposite %2 %4 %4 %4 %4 +)"); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"()"); +} + +TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec2_With_Vec2) { + auto* cast = vec2(vec2(2.0f, 2.0f)); + + ASSERT_TRUE(td.DetermineResultType(cast)) << td.error(); + + b.push_function(Function{}); + EXPECT_EQ(b.GenerateConstructorExpression(nullptr, cast, true), 5u); + + EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 +%2 = OpTypeVector %3 2 +%4 = OpConstant %3 2 +%5 = OpConstantComposite %2 %4 %4 +)"); +} + +TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec3_With_Vec3) { + auto* cast = vec3(vec3(2.0f, 2.0f, 2.0f)); + + ASSERT_TRUE(td.DetermineResultType(cast)) << td.error(); + + b.push_function(Function{}); + EXPECT_EQ(b.GenerateConstructorExpression(nullptr, cast, true), 5u); + + EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 +%2 = OpTypeVector %3 3 +%4 = OpConstant %3 2 +%5 = OpConstantComposite %2 %4 %4 %4 +)"); +} + +TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec4_With_Vec4) { + auto* cast = vec4(vec4(2.0f, 2.0f, 2.0f, 2.0f)); + + ASSERT_TRUE(td.DetermineResultType(cast)) << td.error(); + + b.push_function(Function{}); + EXPECT_EQ(b.GenerateConstructorExpression(nullptr, cast, true), 5u); + + EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 +%2 = OpTypeVector %3 4 +%4 = OpConstant %3 2 +%5 = OpConstantComposite %2 %4 %4 %4 %4 +)"); +} + TEST_F(SpvBuilderConstructorTest, Type_ModuleScope_Vec3_With_F32_Vec2) { auto* cast = vec3(2.0f, vec2(2.0f, 2.0f));