[spirv-writer] Handle building vectors from other vectors.
This Cl updates the composite construction to handle decomposing vectors into smaller parts before building the composite. Bug: tint:61 Change-Id: I7e0ac3a5c966dbcdf6429d508a392756f521b756 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/20541 Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
563d3e9975
commit
3051bfd6b5
|
@ -680,6 +680,9 @@ uint32_t Builder::GenerateConstructorExpression(
|
||||||
}
|
}
|
||||||
constructor_is_const = false;
|
constructor_is_const = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& e : init->values()) {
|
||||||
uint32_t id = 0;
|
uint32_t id = 0;
|
||||||
if (constructor_is_const) {
|
if (constructor_is_const) {
|
||||||
id = GenerateConstructorExpression(e->AsConstructor(), is_global_init);
|
id = GenerateConstructorExpression(e->AsConstructor(), is_global_init);
|
||||||
|
@ -691,8 +694,32 @@ uint32_t Builder::GenerateConstructorExpression(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
out << "_" << id;
|
auto* result_type = e->result_type()->UnwrapPtrIfNeeded();
|
||||||
ops.push_back(Operand::Int(id));
|
|
||||||
|
// If we're putting a vector into the constructed composite we need to
|
||||||
|
// extract each of the values and insert them individually
|
||||||
|
if (result_type->IsVector()) {
|
||||||
|
auto* vec = result_type->AsVector();
|
||||||
|
auto result_type_id = GenerateTypeIfNeeded(vec->type());
|
||||||
|
if (result_type_id == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < vec->size(); ++i) {
|
||||||
|
auto extract = result_op();
|
||||||
|
auto extract_id = extract.to_i();
|
||||||
|
|
||||||
|
push_function_inst(spv::Op::OpCompositeExtract,
|
||||||
|
{Operand::Int(result_type_id), extract,
|
||||||
|
Operand::Int(id), Operand::Int(i)});
|
||||||
|
|
||||||
|
out << "_" << extract_id;
|
||||||
|
ops.push_back(Operand::Int(extract_id));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out << "_" << id;
|
||||||
|
ops.push_back(Operand::Int(id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto str = out.str();
|
auto str = out.str();
|
||||||
|
|
|
@ -65,7 +65,11 @@ TEST_F(BuilderTest, Constructor_Type) {
|
||||||
|
|
||||||
ast::TypeConstructorExpression t(&vec, std::move(vals));
|
ast::TypeConstructorExpression t(&vec, std::move(vals));
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
ast::Module mod;
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(&t)) << td.error();
|
||||||
|
|
||||||
Builder b(&mod);
|
Builder b(&mod);
|
||||||
EXPECT_EQ(b.GenerateConstructorExpression(&t, true), 5u);
|
EXPECT_EQ(b.GenerateConstructorExpression(&t, true), 5u);
|
||||||
ASSERT_FALSE(b.has_error()) << b.error();
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
@ -120,6 +124,54 @@ TEST_F(BuilderTest, Constructor_Type_NonConstructorParam) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest, Constructor_Type_NonConstVector) {
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
ast::type::VectorType vec2(&f32, 2);
|
||||||
|
ast::type::VectorType vec4(&f32, 4);
|
||||||
|
|
||||||
|
auto var = std::make_unique<ast::Variable>(
|
||||||
|
"ident", ast::StorageClass::kFunction, &vec2);
|
||||||
|
|
||||||
|
ast::ExpressionList vals;
|
||||||
|
vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
|
||||||
|
std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
|
||||||
|
vals.push_back(std::make_unique<ast::ScalarConstructorExpression>(
|
||||||
|
std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
|
||||||
|
vals.push_back(std::make_unique<ast::IdentifierExpression>("ident"));
|
||||||
|
|
||||||
|
ast::TypeConstructorExpression t(&vec4, std::move(vals));
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
td.RegisterVariableForTesting(var.get());
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(&t)) << td.error();
|
||||||
|
|
||||||
|
Builder b(&mod);
|
||||||
|
b.push_function(Function{});
|
||||||
|
ASSERT_TRUE(b.GenerateFunctionVariable(var.get())) << b.error();
|
||||||
|
|
||||||
|
EXPECT_EQ(b.GenerateConstructorExpression(&t, false), 10u);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
|
||||||
|
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
|
||||||
|
%3 = OpTypeVector %4 2
|
||||||
|
%2 = OpTypePointer Function %3
|
||||||
|
%5 = OpTypeVector %4 4
|
||||||
|
%6 = OpConstant %4 1
|
||||||
|
)");
|
||||||
|
EXPECT_EQ(DumpInstructions(b.functions()[0].variables()),
|
||||||
|
R"(%1 = OpVariable %2 Function
|
||||||
|
)");
|
||||||
|
|
||||||
|
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
||||||
|
R"(%7 = OpLoad %3 %1
|
||||||
|
%8 = OpCompositeExtract %4 %7 0
|
||||||
|
%9 = OpCompositeExtract %4 %7 1
|
||||||
|
%10 = OpCompositeConstruct %5 %6 %6 %8 %9
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(BuilderTest, Constructor_Type_Dedups) {
|
TEST_F(BuilderTest, Constructor_Type_Dedups) {
|
||||||
ast::type::F32Type f32;
|
ast::type::F32Type f32;
|
||||||
ast::type::VectorType vec(&f32, 3);
|
ast::type::VectorType vec(&f32, 3);
|
||||||
|
@ -134,7 +186,11 @@ TEST_F(BuilderTest, Constructor_Type_Dedups) {
|
||||||
|
|
||||||
ast::TypeConstructorExpression t(&vec, std::move(vals));
|
ast::TypeConstructorExpression t(&vec, std::move(vals));
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
ast::Module mod;
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(&t)) << td.error();
|
||||||
|
|
||||||
Builder b(&mod);
|
Builder b(&mod);
|
||||||
EXPECT_EQ(b.GenerateConstructorExpression(&t, true), 5u);
|
EXPECT_EQ(b.GenerateConstructorExpression(&t, true), 5u);
|
||||||
EXPECT_EQ(b.GenerateConstructorExpression(&t, true), 5u);
|
EXPECT_EQ(b.GenerateConstructorExpression(&t, true), 5u);
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
#include "src/ast/type_constructor_expression.h"
|
#include "src/ast/type_constructor_expression.h"
|
||||||
#include "src/ast/variable.h"
|
#include "src/ast/variable.h"
|
||||||
#include "src/ast/variable_decoration.h"
|
#include "src/ast/variable_decoration.h"
|
||||||
|
#include "src/context.h"
|
||||||
|
#include "src/type_determiner.h"
|
||||||
#include "src/writer/spirv/builder.h"
|
#include "src/writer/spirv/builder.h"
|
||||||
#include "src/writer/spirv/spv_dump.h"
|
#include "src/writer/spirv/spv_dump.h"
|
||||||
|
|
||||||
|
@ -74,10 +76,16 @@ TEST_F(BuilderTest, FunctionVar_WithConstantConstructor) {
|
||||||
auto init =
|
auto init =
|
||||||
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(init.get())) << td.error();
|
||||||
|
|
||||||
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
||||||
v.set_constructor(std::move(init));
|
v.set_constructor(std::move(init));
|
||||||
|
|
||||||
ast::Module mod;
|
td.RegisterVariableForTesting(&v);
|
||||||
|
|
||||||
Builder b(&mod);
|
Builder b(&mod);
|
||||||
b.push_function(Function{});
|
b.push_function(Function{});
|
||||||
EXPECT_TRUE(b.GenerateFunctionVariable(&v)) << b.error();
|
EXPECT_TRUE(b.GenerateFunctionVariable(&v)) << b.error();
|
||||||
|
@ -161,11 +169,17 @@ TEST_F(BuilderTest, FunctionVar_Const) {
|
||||||
auto init =
|
auto init =
|
||||||
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(init.get())) << td.error();
|
||||||
|
|
||||||
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
||||||
v.set_constructor(std::move(init));
|
v.set_constructor(std::move(init));
|
||||||
v.set_is_const(true);
|
v.set_is_const(true);
|
||||||
|
|
||||||
ast::Module mod;
|
td.RegisterVariableForTesting(&v);
|
||||||
|
|
||||||
Builder b(&mod);
|
Builder b(&mod);
|
||||||
EXPECT_TRUE(b.GenerateFunctionVariable(&v)) << b.error();
|
EXPECT_TRUE(b.GenerateFunctionVariable(&v)) << b.error();
|
||||||
ASSERT_FALSE(b.has_error()) << b.error();
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include "src/ast/type_constructor_expression.h"
|
#include "src/ast/type_constructor_expression.h"
|
||||||
#include "src/ast/variable.h"
|
#include "src/ast/variable.h"
|
||||||
#include "src/ast/variable_decoration.h"
|
#include "src/ast/variable_decoration.h"
|
||||||
|
#include "src/context.h"
|
||||||
|
#include "src/type_determiner.h"
|
||||||
#include "src/writer/spirv/builder.h"
|
#include "src/writer/spirv/builder.h"
|
||||||
#include "src/writer/spirv/spv_dump.h"
|
#include "src/writer/spirv/spv_dump.h"
|
||||||
|
|
||||||
|
@ -84,10 +86,15 @@ TEST_F(BuilderTest, GlobalVar_WithConstructor) {
|
||||||
auto init =
|
auto init =
|
||||||
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(init.get())) << td.error();
|
||||||
|
|
||||||
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
||||||
v.set_constructor(std::move(init));
|
v.set_constructor(std::move(init));
|
||||||
|
td.RegisterVariableForTesting(&v);
|
||||||
|
|
||||||
ast::Module mod;
|
|
||||||
Builder b(&mod);
|
Builder b(&mod);
|
||||||
EXPECT_TRUE(b.GenerateGlobalVariable(&v)) << b.error();
|
EXPECT_TRUE(b.GenerateGlobalVariable(&v)) << b.error();
|
||||||
ASSERT_FALSE(b.has_error()) << b.error();
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
@ -119,11 +126,16 @@ TEST_F(BuilderTest, GlobalVar_Const) {
|
||||||
auto init =
|
auto init =
|
||||||
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(init.get())) << td.error();
|
||||||
|
|
||||||
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
||||||
v.set_constructor(std::move(init));
|
v.set_constructor(std::move(init));
|
||||||
v.set_is_const(true);
|
v.set_is_const(true);
|
||||||
|
td.RegisterVariableForTesting(&v);
|
||||||
|
|
||||||
ast::Module mod;
|
|
||||||
Builder b(&mod);
|
Builder b(&mod);
|
||||||
EXPECT_TRUE(b.GenerateGlobalVariable(&v)) << b.error();
|
EXPECT_TRUE(b.GenerateGlobalVariable(&v)) << b.error();
|
||||||
ASSERT_FALSE(b.has_error()) << b.error();
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
|
|
@ -52,13 +52,15 @@ TEST_F(BuilderTest, IdentifierExpression_GlobalConst) {
|
||||||
auto init =
|
auto init =
|
||||||
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(init.get())) << td.error();
|
||||||
|
|
||||||
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
||||||
v.set_constructor(std::move(init));
|
v.set_constructor(std::move(init));
|
||||||
v.set_is_const(true);
|
v.set_is_const(true);
|
||||||
|
|
||||||
Context ctx;
|
|
||||||
ast::Module mod;
|
|
||||||
TypeDeterminer td(&ctx, &mod);
|
|
||||||
td.RegisterVariableForTesting(&v);
|
td.RegisterVariableForTesting(&v);
|
||||||
|
|
||||||
Builder b(&mod);
|
Builder b(&mod);
|
||||||
|
@ -117,13 +119,14 @@ TEST_F(BuilderTest, IdentifierExpression_FunctionConst) {
|
||||||
auto init =
|
auto init =
|
||||||
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(vals));
|
||||||
|
|
||||||
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
|
||||||
v.set_constructor(std::move(init));
|
|
||||||
v.set_is_const(true);
|
|
||||||
|
|
||||||
Context ctx;
|
Context ctx;
|
||||||
ast::Module mod;
|
ast::Module mod;
|
||||||
TypeDeterminer td(&ctx, &mod);
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(init.get())) << td.error();
|
||||||
|
|
||||||
|
ast::Variable v("var", ast::StorageClass::kOutput, &f32);
|
||||||
|
v.set_constructor(std::move(init));
|
||||||
|
v.set_is_const(true);
|
||||||
td.RegisterVariableForTesting(&v);
|
td.RegisterVariableForTesting(&v);
|
||||||
|
|
||||||
Builder b(&mod);
|
Builder b(&mod);
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include "src/ast/type/f32_type.h"
|
#include "src/ast/type/f32_type.h"
|
||||||
#include "src/ast/type/vector_type.h"
|
#include "src/ast/type/vector_type.h"
|
||||||
#include "src/ast/type_constructor_expression.h"
|
#include "src/ast/type_constructor_expression.h"
|
||||||
|
#include "src/context.h"
|
||||||
|
#include "src/type_determiner.h"
|
||||||
#include "src/writer/spirv/builder.h"
|
#include "src/writer/spirv/builder.h"
|
||||||
#include "src/writer/spirv/spv_dump.h"
|
#include "src/writer/spirv/spv_dump.h"
|
||||||
|
|
||||||
|
@ -61,7 +63,11 @@ TEST_F(BuilderTest, Return_WithValue) {
|
||||||
|
|
||||||
ast::ReturnStatement ret(std::move(val));
|
ast::ReturnStatement ret(std::move(val));
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
ast::Module mod;
|
ast::Module mod;
|
||||||
|
TypeDeterminer td(&ctx, &mod);
|
||||||
|
EXPECT_TRUE(td.DetermineResultType(&ret)) << td.error();
|
||||||
|
|
||||||
Builder b(&mod);
|
Builder b(&mod);
|
||||||
b.push_function(Function{});
|
b.push_function(Function{});
|
||||||
EXPECT_TRUE(b.GenerateReturnStatement(&ret));
|
EXPECT_TRUE(b.GenerateReturnStatement(&ret));
|
||||||
|
|
Loading…
Reference in New Issue