[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;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue