[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:
dan sinclair 2020-04-28 20:25:21 +00:00 committed by dan sinclair
parent 563d3e9975
commit 3051bfd6b5
6 changed files with 131 additions and 13 deletions

View File

@ -680,6 +680,9 @@ uint32_t Builder::GenerateConstructorExpression(
}
constructor_is_const = false;
}
}
for (const auto& e : init->values()) {
uint32_t id = 0;
if (constructor_is_const) {
id = GenerateConstructorExpression(e->AsConstructor(), is_global_init);
@ -691,8 +694,32 @@ uint32_t Builder::GenerateConstructorExpression(
return 0;
}
out << "_" << id;
ops.push_back(Operand::Int(id));
auto* result_type = e->result_type()->UnwrapPtrIfNeeded();
// 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();

View File

@ -65,7 +65,11 @@ TEST_F(BuilderTest, Constructor_Type) {
ast::TypeConstructorExpression t(&vec, std::move(vals));
Context ctx;
ast::Module mod;
TypeDeterminer td(&ctx, &mod);
EXPECT_TRUE(td.DetermineResultType(&t)) << td.error();
Builder b(&mod);
EXPECT_EQ(b.GenerateConstructorExpression(&t, true), 5u);
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) {
ast::type::F32Type f32;
ast::type::VectorType vec(&f32, 3);
@ -134,7 +186,11 @@ TEST_F(BuilderTest, Constructor_Type_Dedups) {
ast::TypeConstructorExpression t(&vec, std::move(vals));
Context ctx;
ast::Module mod;
TypeDeterminer td(&ctx, &mod);
EXPECT_TRUE(td.DetermineResultType(&t)) << td.error();
Builder b(&mod);
EXPECT_EQ(b.GenerateConstructorExpression(&t, true), 5u);
EXPECT_EQ(b.GenerateConstructorExpression(&t, true), 5u);

View File

@ -30,6 +30,8 @@
#include "src/ast/type_constructor_expression.h"
#include "src/ast/variable.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/spv_dump.h"
@ -74,10 +76,16 @@ TEST_F(BuilderTest, FunctionVar_WithConstantConstructor) {
auto init =
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);
v.set_constructor(std::move(init));
ast::Module mod;
td.RegisterVariableForTesting(&v);
Builder b(&mod);
b.push_function(Function{});
EXPECT_TRUE(b.GenerateFunctionVariable(&v)) << b.error();
@ -161,11 +169,17 @@ TEST_F(BuilderTest, FunctionVar_Const) {
auto init =
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);
v.set_constructor(std::move(init));
v.set_is_const(true);
ast::Module mod;
td.RegisterVariableForTesting(&v);
Builder b(&mod);
EXPECT_TRUE(b.GenerateFunctionVariable(&v)) << b.error();
ASSERT_FALSE(b.has_error()) << b.error();

View File

@ -29,6 +29,8 @@
#include "src/ast/type_constructor_expression.h"
#include "src/ast/variable.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/spv_dump.h"
@ -84,10 +86,15 @@ TEST_F(BuilderTest, GlobalVar_WithConstructor) {
auto init =
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);
v.set_constructor(std::move(init));
td.RegisterVariableForTesting(&v);
ast::Module mod;
Builder b(&mod);
EXPECT_TRUE(b.GenerateGlobalVariable(&v)) << b.error();
ASSERT_FALSE(b.has_error()) << b.error();
@ -119,11 +126,16 @@ TEST_F(BuilderTest, GlobalVar_Const) {
auto init =
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);
v.set_constructor(std::move(init));
v.set_is_const(true);
td.RegisterVariableForTesting(&v);
ast::Module mod;
Builder b(&mod);
EXPECT_TRUE(b.GenerateGlobalVariable(&v)) << b.error();
ASSERT_FALSE(b.has_error()) << b.error();

View File

@ -52,13 +52,15 @@ TEST_F(BuilderTest, IdentifierExpression_GlobalConst) {
auto init =
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);
v.set_constructor(std::move(init));
v.set_is_const(true);
Context ctx;
ast::Module mod;
TypeDeterminer td(&ctx, &mod);
td.RegisterVariableForTesting(&v);
Builder b(&mod);
@ -117,13 +119,14 @@ TEST_F(BuilderTest, IdentifierExpression_FunctionConst) {
auto init =
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;
ast::Module 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);
Builder b(&mod);

View File

@ -21,6 +21,8 @@
#include "src/ast/type/f32_type.h"
#include "src/ast/type/vector_type.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/spv_dump.h"
@ -61,7 +63,11 @@ TEST_F(BuilderTest, Return_WithValue) {
ast::ReturnStatement ret(std::move(val));
Context ctx;
ast::Module mod;
TypeDeterminer td(&ctx, &mod);
EXPECT_TRUE(td.DetermineResultType(&ret)) << td.error();
Builder b(&mod);
b.push_function(Function{});
EXPECT_TRUE(b.GenerateReturnStatement(&ret));