writer/msl: Fix swizzling on packed vectors

Metal 1.x does not support swizzling on packed_vec types.
Use array-index for single element selection (permitted on LHS and RHS of assignment)
Cast the packed_vec to a vec for multiple element swizzles (not permitted as the LHS of an assignment).

Fixed: tint:1249
Change-Id: I70cbb0c22a935b06b3905d24484bdc2edfb95fc2
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/67060
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Ben Clayton <bclayton@google.com>
Reviewed-by: James Price <jrprice@google.com>
This commit is contained in:
Ben Clayton
2021-10-20 16:12:33 +00:00
committed by Tint LUCI CQ
parent 8645953be2
commit 7103f51603
103 changed files with 9204 additions and 679 deletions

View File

@@ -1953,28 +1953,55 @@ bool GeneratorImpl::EmitIf(const ast::IfStatement* stmt) {
bool GeneratorImpl::EmitMemberAccessor(
std::ostream& out,
const ast::MemberAccessorExpression* expr) {
bool paren_lhs =
!expr->structure
->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
ast::IdentifierExpression, ast::MemberAccessorExpression,
ast::TypeConstructorExpression>();
if (paren_lhs) {
out << "(";
}
if (!EmitExpression(out, expr->structure)) {
return false;
}
if (paren_lhs) {
out << ")";
}
auto write_lhs = [&] {
bool paren_lhs =
!expr->structure
->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
ast::IdentifierExpression, ast::MemberAccessorExpression,
ast::TypeConstructorExpression>();
if (paren_lhs) {
out << "(";
}
if (!EmitExpression(out, expr->structure)) {
return false;
}
if (paren_lhs) {
out << ")";
}
return true;
};
out << ".";
auto& sem = program_->Sem();
// Swizzles get written out directly
if (program_->Sem().Get(expr)->Is<sem::Swizzle>()) {
out << program_->Symbols().NameFor(expr->member->symbol);
} else if (!EmitExpression(out, expr->member)) {
return false;
if (auto* swizzle = sem.Get(expr)->As<sem::Swizzle>()) {
// Metal 1.x does not support swizzling of packed vector types.
// For single element swizzles, we can use the index operator.
// For multi-element swizzles, we need to cast to a regular vector type
// first. Note that we do not currently allow assignments to swizzles, so
// the casting which will convert the l-value to r-value is fine.
if (swizzle->Indices().size() == 1) {
if (!write_lhs()) {
return false;
}
out << "[" << swizzle->Indices()[0] << "]";
} else {
if (!EmitType(out, sem.Get(expr->structure)->Type()->UnwrapRef(), "")) {
return false;
}
out << "(";
if (!write_lhs()) {
return false;
}
out << ")." << program_->Symbols().NameFor(expr->member->symbol);
}
} else {
if (!write_lhs()) {
return false;
}
out << ".";
if (!EmitExpression(out, expr->member)) {
return false;
}
}
return true;

View File

@@ -147,7 +147,7 @@ struct tint_symbol {
};
float frag_main_inner(float4 coord) {
return coord.x;
return coord[0];
}
fragment tint_symbol frag_main(float4 coord [[position]]) {
@@ -457,7 +457,7 @@ struct UBO {
};
float sub_func(constant UBO& ubo, float param) {
return ubo.coord.x;
return ubo.coord[0];
}
fragment void frag_main(constant UBO& ubo [[buffer(0)]]) {

View File

@@ -43,7 +43,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor_Swizzle_xyz) {
GeneratorImpl& gen = Build();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "my_vec.xyz");
EXPECT_EQ(out.str(), "float4(my_vec).xyz");
}
TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor_Swizzle_gbr) {
@@ -55,7 +55,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor_Swizzle_gbr) {
GeneratorImpl& gen = Build();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "my_vec.gbr");
EXPECT_EQ(out.str(), "float4(my_vec).gbr");
}
} // namespace