resolver: Implement element inference of vecN and matNxM

Fixed: tint:1334
Change-Id: Idc94d49ecd41e37354bb93138348e3af3e733932
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/72143
Reviewed-by: David Neto <dneto@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2021-12-09 14:37:37 +00:00
parent f91b02bba1
commit 81b3948649
140 changed files with 1805 additions and 155 deletions

View File

@ -14,6 +14,7 @@
### New Features ### New Features
* Vector and matrix element type can now be inferred from constructor argument types. [tint:1334](https://crbug.com/tint/1334)
* New texture gather builtins: `textureGather()` and `textureGatherCompare()`. [tint:1330](https://crbug.com/tint/1330) * New texture gather builtins: `textureGather()` and `textureGatherCompare()`. [tint:1330](https://crbug.com/tint/1330)
* Shadowing is now fully supported. [tint:819](https://crbug.com/tint/819) * Shadowing is now fully supported. [tint:819](https://crbug.com/tint/819)
* The `dot()` builtin now supports integer vector types. * The `dot()` builtin now supports integer vector types.

View File

@ -28,7 +28,9 @@ class Matrix : public Castable<Matrix, Type> {
/// Constructor /// Constructor
/// @param pid the identifier of the program that owns this node /// @param pid the identifier of the program that owns this node
/// @param src the source of this node /// @param src the source of this node
/// @param subtype type matrix type /// @param subtype the declared type of the matrix components. May be null for
/// matrix constructors, where the element type will be inferred from
/// the constructor arguments
/// @param rows the number of rows in the matrix /// @param rows the number of rows in the matrix
/// @param columns the number of columns in the matrix /// @param columns the number of columns in the matrix
Matrix(ProgramID pid, Matrix(ProgramID pid,
@ -50,7 +52,9 @@ class Matrix : public Castable<Matrix, Type> {
/// @return the newly cloned type /// @return the newly cloned type
const Matrix* Clone(CloneContext* ctx) const override; const Matrix* Clone(CloneContext* ctx) const override;
/// The type of the matrix /// The declared type of the matrix components. May be null for matrix
/// constructors, where the element type will be inferred from the constructor
/// arguments
const Type* const type; const Type* const type;
/// The number of rows in the matrix /// The number of rows in the matrix

View File

@ -37,7 +37,10 @@ Vector::~Vector() = default;
std::string Vector::FriendlyName(const SymbolTable& symbols) const { std::string Vector::FriendlyName(const SymbolTable& symbols) const {
std::ostringstream out; std::ostringstream out;
out << "vec" << width << "<" << type->FriendlyName(symbols) << ">"; out << "vec" << width;
if (type) {
out << "<" << type->FriendlyName(symbols) << ">";
}
return out.str(); return out.str();
} }

View File

@ -28,7 +28,9 @@ class Vector : public Castable<Vector, Type> {
/// Constructor /// Constructor
/// @param pid the identifier of the program that owns this node /// @param pid the identifier of the program that owns this node
/// @param src the source of this node /// @param src the source of this node
/// @param subtype the vector element type /// @param subtype the declared type of the vector components. May be null
/// for vector constructors, where the element type will be inferred
/// from the constructor arguments
/// @param width the number of elements in the vector /// @param width the number of elements in the vector
Vector(ProgramID pid, Source const& src, const Type* subtype, uint32_t width); Vector(ProgramID pid, Source const& src, const Type* subtype, uint32_t width);
/// Move constructor /// Move constructor
@ -45,7 +47,9 @@ class Vector : public Castable<Vector, Type> {
/// @return the newly cloned type /// @return the newly cloned type
const Vector* Clone(CloneContext* ctx) const override; const Vector* Clone(CloneContext* ctx) const override;
/// The type of the vector elements /// The declared type of the vector components. May be null for vector
/// constructors, where the element type will be inferred from the constructor
/// arguments
const Type* const type; const Type* const type;
/// The number of elements in the vector /// The number of elements in the vector

View File

@ -1154,19 +1154,23 @@ Expect<const ast::Type*> ParserImpl::expect_type_decl_atomic(Token t) {
Expect<const ast::Type*> ParserImpl::expect_type_decl_vector(Token t) { Expect<const ast::Type*> ParserImpl::expect_type_decl_vector(Token t) {
uint32_t count = 2; uint32_t count = 2;
if (t.Is(Token::Type::kVec3)) if (t.Is(Token::Type::kVec3)) {
count = 3; count = 3;
else if (t.Is(Token::Type::kVec4)) } else if (t.Is(Token::Type::kVec4)) {
count = 4; count = 4;
}
const ast::Type* subtype = nullptr;
if (peek_is(Token::Type::kLessThan)) {
const char* use = "vector"; const char* use = "vector";
auto ty = expect_lt_gt_block(use, [&] { return expect_type(use); });
auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); }); if (ty.errored) {
if (subtype.errored)
return Failure::kErrored; return Failure::kErrored;
}
subtype = ty.value;
}
return builder_.ty.vec(make_source_range_from(t.source()), subtype.value, return builder_.ty.vec(make_source_range_from(t.source()), subtype, count);
count);
} }
Expect<const ast::Type*> ParserImpl::expect_type_decl_array( Expect<const ast::Type*> ParserImpl::expect_type_decl_array(
@ -1217,14 +1221,18 @@ Expect<const ast::Type*> ParserImpl::expect_type_decl_matrix(Token t) {
rows = 4; rows = 4;
} }
const ast::Type* subtype = nullptr;
if (peek_is(Token::Type::kLessThan)) {
const char* use = "matrix"; const char* use = "matrix";
auto ty = expect_lt_gt_block(use, [&] { return expect_type(use); });
auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); }); if (ty.errored) {
if (subtype.errored)
return Failure::kErrored; return Failure::kErrored;
}
subtype = ty.value;
}
return builder_.ty.mat(make_source_range_from(t.source()), subtype.value, return builder_.ty.mat(make_source_range_from(t.source()), subtype, columns,
columns, rows); rows);
} }
// storage_class // storage_class

View File

@ -975,13 +975,6 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarInvalidIdentifier) {
" ^\n"); " ^\n");
} }
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingLessThan) {
EXPECT("var i : mat4x4;",
"test.wgsl:1:15 error: expected '<' for matrix\n"
"var i : mat4x4;\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingGreaterThan) { TEST_F(ParserImplErrorTest, GlobalDeclVarMatrixMissingGreaterThan) {
EXPECT("var i : mat4x4<u32;", EXPECT("var i : mat4x4<u32;",
"test.wgsl:1:19 error: expected '>' for matrix\n" "test.wgsl:1:19 error: expected '>' for matrix\n"
@ -1066,13 +1059,6 @@ TEST_F(ParserImplErrorTest, GlobalDeclVarStorageDeclMissingGThan) {
" ^\n"); " ^\n");
} }
TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingLessThan) {
EXPECT("var i : vec3;",
"test.wgsl:1:13 error: expected '<' for vector\n"
"var i : vec3;\n"
" ^\n");
}
TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingGreaterThan) { TEST_F(ParserImplErrorTest, GlobalDeclVarVectorMissingGreaterThan) {
EXPECT("var i : vec3<u32;", EXPECT("var i : vec3<u32;",
"test.wgsl:1:17 error: expected '>' for vector\n" "test.wgsl:1:17 error: expected '>' for vector\n"

View File

@ -139,24 +139,6 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
VecData{"vec3<f32", 3, {}}, VecData{"vec3<f32", 3, {}},
VecData{"vec4<f32", 4, {}})); VecData{"vec4<f32", 4, {}}));
class VecMissingLessThanTest : public ParserImplTestWithParam<VecData> {};
TEST_P(VecMissingLessThanTest, Handles_Missing_GreaterThan) {
auto params = GetParam();
auto p = parser(params.input);
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:5: expected '<' for vector");
}
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
VecMissingLessThanTest,
testing::Values(VecData{"vec2", 2, {}},
VecData{"vec3", 3, {}},
VecData{"vec4", 4, {}}));
class VecMissingType : public ParserImplTestWithParam<VecData> {}; class VecMissingType : public ParserImplTestWithParam<VecData> {};
TEST_P(VecMissingType, Handles_Missing_Type) { TEST_P(VecMissingType, Handles_Missing_Type) {
@ -774,30 +756,6 @@ INSTANTIATE_TEST_SUITE_P(ParserImplTest,
MatrixData{"mat4x3<f32", 4, 3, {}}, MatrixData{"mat4x3<f32", 4, 3, {}},
MatrixData{"mat4x4<f32", 4, 4, {}})); MatrixData{"mat4x4<f32", 4, 4, {}}));
class MatrixMissingLessThanTest : public ParserImplTestWithParam<MatrixData> {};
TEST_P(MatrixMissingLessThanTest, Handles_Missing_GreaterThan) {
auto params = GetParam();
auto p = parser(params.input);
auto t = p->type_decl();
EXPECT_TRUE(t.errored);
EXPECT_FALSE(t.matched);
ASSERT_EQ(t.value, nullptr);
ASSERT_TRUE(p->has_error());
ASSERT_EQ(p->error(), "1:8: expected '<' for matrix");
}
INSTANTIATE_TEST_SUITE_P(ParserImplTest,
MatrixMissingLessThanTest,
testing::Values(MatrixData{"mat2x2 f32>", 2, 2, {}},
MatrixData{"mat2x3 f32>", 2, 3, {}},
MatrixData{"mat2x4 f32>", 2, 4, {}},
MatrixData{"mat3x2 f32>", 3, 2, {}},
MatrixData{"mat3x3 f32>", 3, 3, {}},
MatrixData{"mat3x4 f32>", 3, 4, {}},
MatrixData{"mat4x2 f32>", 4, 2, {}},
MatrixData{"mat4x3 f32>", 4, 3, {}},
MatrixData{"mat4x4 f32>", 4, 4, {}}));
class MatrixMissingType : public ParserImplTestWithParam<MatrixData> {}; class MatrixMissingType : public ParserImplTestWithParam<MatrixData> {};
TEST_P(MatrixMissingType, Handles_Missing_Type) { TEST_P(MatrixMissingType, Handles_Missing_Type) {

View File

@ -766,6 +766,28 @@ TEST_F(ResolverFunctionValidationTest, ParametersOverLimit) {
"12:34 error: functions may declare at most 255 parameters"); "12:34 error: functions may declare at most 255 parameters");
} }
TEST_F(ResolverFunctionValidationTest, ParameterVectorNoType) {
// fn f(p : vec3) {}
Func(Source{{12, 34}}, "f",
{Param("p", create<ast::Vector>(Source{{12, 34}}, nullptr, 3))},
ty.void_(), {});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing vector element type");
}
TEST_F(ResolverFunctionValidationTest, ParameterMatrixNoType) {
// fn f(p : vec3) {}
Func(Source{{12, 34}}, "f",
{Param("p", create<ast::Matrix>(Source{{12, 34}}, nullptr, 3, 3))},
ty.void_(), {});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing matrix element type");
}
struct TestParams { struct TestParams {
ast::StorageClass storage_class; ast::StorageClass storage_class;
bool should_pass; bool should_pass;

View File

@ -180,6 +180,10 @@ sem::Type* Resolver::Type(const ast::Type* ty) {
return builder_->create<sem::F32>(); return builder_->create<sem::F32>();
} }
if (auto* t = ty->As<ast::Vector>()) { if (auto* t = ty->As<ast::Vector>()) {
if (!t->type) {
AddError("missing vector element type", t->source.End());
return nullptr;
}
if (auto* el = Type(t->type)) { if (auto* el = Type(t->type)) {
if (auto* vector = builder_->create<sem::Vector>(el, t->width)) { if (auto* vector = builder_->create<sem::Vector>(el, t->width)) {
if (ValidateVector(vector, t->source)) { if (ValidateVector(vector, t->source)) {
@ -190,6 +194,10 @@ sem::Type* Resolver::Type(const ast::Type* ty) {
return nullptr; return nullptr;
} }
if (auto* t = ty->As<ast::Matrix>()) { if (auto* t = ty->As<ast::Matrix>()) {
if (!t->type) {
AddError("missing matrix element type", t->source.End());
return nullptr;
}
if (auto* el = Type(t->type)) { if (auto* el = Type(t->type)) {
if (auto* column_type = builder_->create<sem::Vector>(el, t->rows)) { if (auto* column_type = builder_->create<sem::Vector>(el, t->rows)) {
if (auto* matrix = if (auto* matrix =
@ -1240,6 +1248,10 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
std::vector<const sem::Type*> arg_tys(args.size()); std::vector<const sem::Type*> arg_tys(args.size());
sem::Behaviors arg_behaviors; sem::Behaviors arg_behaviors;
// The element type of all the arguments. Nullptr if argument types are
// different.
const sem::Type* arg_el_ty = nullptr;
for (size_t i = 0; i < expr->args.size(); i++) { for (size_t i = 0; i < expr->args.size(); i++) {
auto* arg = Sem(expr->args[i]); auto* arg = Sem(expr->args[i]);
if (!arg) { if (!arg) {
@ -1248,6 +1260,19 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
args[i] = arg; args[i] = arg;
arg_tys[i] = args[i]->Type(); arg_tys[i] = args[i]->Type();
arg_behaviors.Add(arg->Behaviors()); arg_behaviors.Add(arg->Behaviors());
// Determine the common argument element type
auto* el_ty = arg_tys[i]->UnwrapRef();
if (auto* vec = el_ty->As<sem::Vector>()) {
el_ty = vec->type();
} else if (auto* mat = el_ty->As<sem::Matrix>()) {
el_ty = mat->type();
}
if (i == 0) {
arg_el_ty = el_ty;
} else if (arg_el_ty != el_ty) {
arg_el_ty = nullptr;
}
} }
arg_behaviors.Remove(sem::Behavior::kNext); arg_behaviors.Remove(sem::Behavior::kNext);
@ -1273,10 +1298,71 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
// Resolve the target of the CallExpression to determine whether this is a // Resolve the target of the CallExpression to determine whether this is a
// function call, cast or type constructor expression. // function call, cast or type constructor expression.
if (expr->target.type) { if (expr->target.type) {
auto* ty = Type(expr->target.type); const sem::Type* ty = nullptr;
auto err_cannot_infer_el_ty = [&](std::string name) {
AddError(
"cannot infer " + name +
" element type, as constructor arguments have different types",
expr->source);
for (size_t i = 0; i < args.size(); i++) {
auto* arg = args[i];
AddNote("argument " + std::to_string(i) + " has type " +
arg->Type()->FriendlyName(builder_->Symbols()),
arg->Declaration()->source);
}
};
if (!expr->args.empty()) {
// vecN() without explicit element type?
// Try to infer element type from args
if (auto* vec = expr->target.type->As<ast::Vector>()) {
if (!vec->type) {
if (!arg_el_ty) {
err_cannot_infer_el_ty("vector");
return nullptr;
}
Mark(vec);
auto* v = builder_->create<sem::Vector>(
arg_el_ty, static_cast<uint32_t>(vec->width));
if (!ValidateVector(v, vec->source)) {
return nullptr;
}
builder_->Sem().Add(vec, v);
ty = v;
}
}
// matNxM() without explicit element type?
// Try to infer element type from args
if (auto* mat = expr->target.type->As<ast::Matrix>()) {
if (!mat->type) {
if (!arg_el_ty) {
err_cannot_infer_el_ty("matrix");
return nullptr;
}
Mark(mat);
auto* column_type =
builder_->create<sem::Vector>(arg_el_ty, mat->rows);
auto* m = builder_->create<sem::Matrix>(column_type, mat->columns);
if (!ValidateMatrix(m, mat->source)) {
return nullptr;
}
builder_->Sem().Add(mat, m);
ty = m;
}
}
}
if (ty == nullptr) {
ty = Type(expr->target.type);
if (!ty) { if (!ty) {
return nullptr; return nullptr;
} }
}
return type_ctor_or_conv(ty); return type_ctor_or_conv(ty);
} }
@ -1393,16 +1479,16 @@ sem::Call* Resolver::TypeConversion(const ast::CallExpression* expr,
auto* call_target = utils::GetOrCreate( auto* call_target = utils::GetOrCreate(
type_conversions_, TypeConversionSig{target, source}, type_conversions_, TypeConversionSig{target, source},
[&]() -> sem::TypeConversion* { [&]() -> sem::TypeConversion* {
// Now that the argument types have been determined, make sure that they // Now that the argument types have been determined, make sure that
// obey the conversion rules laid out in // they obey the conversion rules laid out in
// https://gpuweb.github.io/gpuweb/wgsl/#conversion-expr. // https://gpuweb.github.io/gpuweb/wgsl/#conversion-expr.
bool ok = true; bool ok = true;
if (auto* vec_type = target->As<sem::Vector>()) { if (auto* vec_type = target->As<sem::Vector>()) {
ok = ValidateVectorConstructorOrCast(expr, vec_type); ok = ValidateVectorConstructorOrCast(expr, vec_type);
} else if (auto* mat_type = target->As<sem::Matrix>()) { } else if (auto* mat_type = target->As<sem::Matrix>()) {
// Note: Matrix types currently cannot be converted (the element type // Note: Matrix types currently cannot be converted (the element
// must only be f32). We implement this for the day we support other // type must only be f32). We implement this for the day we support
// matrix element types. // other matrix element types.
ok = ValidateMatrixConstructorOrCast(expr, mat_type); ok = ValidateMatrixConstructorOrCast(expr, mat_type);
} else if (target->is_scalar()) { } else if (target->is_scalar()) {
ok = ValidateScalarConstructorOrCast(expr, target); ok = ValidateScalarConstructorOrCast(expr, target);
@ -1452,8 +1538,8 @@ sem::Call* Resolver::TypeConstructor(
auto* call_target = utils::GetOrCreate( auto* call_target = utils::GetOrCreate(
type_ctors_, TypeConstructorSig{ty, arg_tys}, type_ctors_, TypeConstructorSig{ty, arg_tys},
[&]() -> sem::TypeConstructor* { [&]() -> sem::TypeConstructor* {
// Now that the argument types have been determined, make sure that they // Now that the argument types have been determined, make sure that
// obey the constructor type rules laid out in // they obey the constructor type rules laid out in
// https://gpuweb.github.io/gpuweb/wgsl/#type-constructor-expr. // https://gpuweb.github.io/gpuweb/wgsl/#type-constructor-expr.
bool ok = true; bool ok = true;
if (auto* vec_type = ty->As<sem::Vector>()) { if (auto* vec_type = ty->As<sem::Vector>()) {
@ -2359,8 +2445,8 @@ sem::Statement* Resolver::ReturnStatement(const ast::ReturnStatement* stmt) {
behaviors.Add(expr->Behaviors() - sem::Behavior::kNext); behaviors.Add(expr->Behaviors() - sem::Behavior::kNext);
} }
// Validate after processing the return value expression so that its type is // Validate after processing the return value expression so that its type
// available for validation. // is available for validation.
return ValidateReturn(stmt); return ValidateReturn(stmt);
}); });
} }

View File

@ -1853,6 +1853,12 @@ bool Resolver::ValidateMatrixConstructorOrCast(const ast::CallExpression* ctor,
return false; return false;
} }
std::vector<const sem::Type*> arg_tys;
arg_tys.reserve(values.size());
for (auto* value : values) {
arg_tys.emplace_back(TypeOf(value)->UnwrapRef());
}
auto* elem_type = matrix_ty->type(); auto* elem_type = matrix_ty->type();
auto num_elements = matrix_ty->columns() * matrix_ty->rows(); auto num_elements = matrix_ty->columns() * matrix_ty->rows();
@ -1864,7 +1870,14 @@ bool Resolver::ValidateMatrixConstructorOrCast(const ast::CallExpression* ctor,
auto type_name = TypeNameOf(matrix_ty); auto type_name = TypeNameOf(matrix_ty);
auto elem_type_name = TypeNameOf(elem_type); auto elem_type_name = TypeNameOf(elem_type);
std::stringstream ss; std::stringstream ss;
ss << "invalid constructor for " + type_name << std::endl << std::endl; ss << "no matching constructor " + type_name << "(";
for (size_t i = 0; i < values.size(); i++) {
if (i > 0) {
ss << ", ";
}
ss << arg_tys[i]->FriendlyName(builder_->Symbols());
}
ss << ")" << std::endl << std::endl;
ss << "3 candidates available:" << std::endl; ss << "3 candidates available:" << std::endl;
ss << " " << type_name << "()" << std::endl; ss << " " << type_name << "()" << std::endl;
ss << " " << type_name << "(" << elem_type_name << ",...," ss << " " << type_name << "(" << elem_type_name << ",...,"
@ -1893,8 +1906,8 @@ bool Resolver::ValidateMatrixConstructorOrCast(const ast::CallExpression* ctor,
return false; return false;
} }
for (auto* value : values) { for (auto* arg_ty : arg_tys) {
if (TypeOf(value)->UnwrapRef() != expected_arg_type) { if (arg_ty != expected_arg_type) {
print_error(); print_error();
return false; return false;
} }

View File

@ -1821,6 +1821,386 @@ TEST_F(ResolverTypeConstructorValidationTest,
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_F(ResolverTypeConstructorValidationTest, InferVec2ElementTypeFromScalars) {
auto* vec2_bool =
Construct(create<ast::Vector>(nullptr, 2), Expr(true), Expr(false));
auto* vec2_i32 = Construct(create<ast::Vector>(nullptr, 2), Expr(1), Expr(2));
auto* vec2_u32 =
Construct(create<ast::Vector>(nullptr, 2), Expr(1u), Expr(2u));
auto* vec2_f32 =
Construct(create<ast::Vector>(nullptr, 2), Expr(1.0f), Expr(2.0f));
WrapInFunction(vec2_bool, vec2_i32, vec2_u32, vec2_f32);
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(vec2_bool)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec2_i32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec2_u32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec2_f32)->Is<sem::Vector>());
EXPECT_TRUE(TypeOf(vec2_bool)->As<sem::Vector>()->type()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(vec2_i32)->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(vec2_u32)->As<sem::Vector>()->type()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(vec2_f32)->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(TypeOf(vec2_bool)->As<sem::Vector>()->Width(), 2u);
EXPECT_EQ(TypeOf(vec2_i32)->As<sem::Vector>()->Width(), 2u);
EXPECT_EQ(TypeOf(vec2_u32)->As<sem::Vector>()->Width(), 2u);
EXPECT_EQ(TypeOf(vec2_f32)->As<sem::Vector>()->Width(), 2u);
EXPECT_EQ(TypeOf(vec2_bool), TypeOf(vec2_bool->target.type));
EXPECT_EQ(TypeOf(vec2_i32), TypeOf(vec2_i32->target.type));
EXPECT_EQ(TypeOf(vec2_u32), TypeOf(vec2_u32->target.type));
EXPECT_EQ(TypeOf(vec2_f32), TypeOf(vec2_f32->target.type));
}
TEST_F(ResolverTypeConstructorValidationTest, InferVec2ElementTypeFromVec2) {
auto* vec2_bool =
Construct(create<ast::Vector>(nullptr, 2), vec2<bool>(true, false));
auto* vec2_i32 = Construct(create<ast::Vector>(nullptr, 2), vec2<i32>(1, 2));
auto* vec2_u32 =
Construct(create<ast::Vector>(nullptr, 2), vec2<u32>(1u, 2u));
auto* vec2_f32 =
Construct(create<ast::Vector>(nullptr, 2), vec2<f32>(1.0f, 2.0f));
WrapInFunction(vec2_bool, vec2_i32, vec2_u32, vec2_f32);
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(vec2_bool)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec2_i32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec2_u32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec2_f32)->Is<sem::Vector>());
EXPECT_TRUE(TypeOf(vec2_bool)->As<sem::Vector>()->type()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(vec2_i32)->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(vec2_u32)->As<sem::Vector>()->type()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(vec2_f32)->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(TypeOf(vec2_bool)->As<sem::Vector>()->Width(), 2u);
EXPECT_EQ(TypeOf(vec2_i32)->As<sem::Vector>()->Width(), 2u);
EXPECT_EQ(TypeOf(vec2_u32)->As<sem::Vector>()->Width(), 2u);
EXPECT_EQ(TypeOf(vec2_f32)->As<sem::Vector>()->Width(), 2u);
EXPECT_EQ(TypeOf(vec2_bool), TypeOf(vec2_bool->target.type));
EXPECT_EQ(TypeOf(vec2_i32), TypeOf(vec2_i32->target.type));
EXPECT_EQ(TypeOf(vec2_u32), TypeOf(vec2_u32->target.type));
EXPECT_EQ(TypeOf(vec2_f32), TypeOf(vec2_f32->target.type));
}
TEST_F(ResolverTypeConstructorValidationTest, InferVec3ElementTypeFromScalars) {
auto* vec3_bool = Construct(create<ast::Vector>(nullptr, 3), Expr(true),
Expr(false), Expr(true));
auto* vec3_i32 =
Construct(create<ast::Vector>(nullptr, 3), Expr(1), Expr(2), Expr(3));
auto* vec3_u32 =
Construct(create<ast::Vector>(nullptr, 3), Expr(1u), Expr(2u), Expr(3u));
auto* vec3_f32 = Construct(create<ast::Vector>(nullptr, 3), Expr(1.0f),
Expr(2.0f), Expr(3.0f));
WrapInFunction(vec3_bool, vec3_i32, vec3_u32, vec3_f32);
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(vec3_bool)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec3_i32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec3_u32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec3_f32)->Is<sem::Vector>());
EXPECT_TRUE(TypeOf(vec3_bool)->As<sem::Vector>()->type()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(vec3_i32)->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(vec3_u32)->As<sem::Vector>()->type()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(vec3_f32)->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(TypeOf(vec3_bool)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_i32)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_u32)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_f32)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_bool), TypeOf(vec3_bool->target.type));
EXPECT_EQ(TypeOf(vec3_i32), TypeOf(vec3_i32->target.type));
EXPECT_EQ(TypeOf(vec3_u32), TypeOf(vec3_u32->target.type));
EXPECT_EQ(TypeOf(vec3_f32), TypeOf(vec3_f32->target.type));
}
TEST_F(ResolverTypeConstructorValidationTest, InferVec3ElementTypeFromVec3) {
auto* vec3_bool =
Construct(create<ast::Vector>(nullptr, 3), vec3<bool>(true, false, true));
auto* vec3_i32 =
Construct(create<ast::Vector>(nullptr, 3), vec3<i32>(1, 2, 3));
auto* vec3_u32 =
Construct(create<ast::Vector>(nullptr, 3), vec3<u32>(1u, 2u, 3u));
auto* vec3_f32 =
Construct(create<ast::Vector>(nullptr, 3), vec3<f32>(1.0f, 2.0f, 3.0f));
WrapInFunction(vec3_bool, vec3_i32, vec3_u32, vec3_f32);
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(vec3_bool)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec3_i32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec3_u32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec3_f32)->Is<sem::Vector>());
EXPECT_TRUE(TypeOf(vec3_bool)->As<sem::Vector>()->type()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(vec3_i32)->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(vec3_u32)->As<sem::Vector>()->type()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(vec3_f32)->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(TypeOf(vec3_bool)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_i32)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_u32)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_f32)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_bool), TypeOf(vec3_bool->target.type));
EXPECT_EQ(TypeOf(vec3_i32), TypeOf(vec3_i32->target.type));
EXPECT_EQ(TypeOf(vec3_u32), TypeOf(vec3_u32->target.type));
EXPECT_EQ(TypeOf(vec3_f32), TypeOf(vec3_f32->target.type));
}
TEST_F(ResolverTypeConstructorValidationTest,
InferVec3ElementTypeFromScalarAndVec2) {
auto* vec3_bool = Construct(create<ast::Vector>(nullptr, 3), Expr(true),
vec2<bool>(false, true));
auto* vec3_i32 =
Construct(create<ast::Vector>(nullptr, 3), Expr(1), vec2<i32>(2, 3));
auto* vec3_u32 =
Construct(create<ast::Vector>(nullptr, 3), Expr(1u), vec2<u32>(2u, 3u));
auto* vec3_f32 = Construct(create<ast::Vector>(nullptr, 3), Expr(1.0f),
vec2<f32>(2.0f, 3.0f));
WrapInFunction(vec3_bool, vec3_i32, vec3_u32, vec3_f32);
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(vec3_bool)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec3_i32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec3_u32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec3_f32)->Is<sem::Vector>());
EXPECT_TRUE(TypeOf(vec3_bool)->As<sem::Vector>()->type()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(vec3_i32)->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(vec3_u32)->As<sem::Vector>()->type()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(vec3_f32)->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(TypeOf(vec3_bool)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_i32)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_u32)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_f32)->As<sem::Vector>()->Width(), 3u);
EXPECT_EQ(TypeOf(vec3_bool), TypeOf(vec3_bool->target.type));
EXPECT_EQ(TypeOf(vec3_i32), TypeOf(vec3_i32->target.type));
EXPECT_EQ(TypeOf(vec3_u32), TypeOf(vec3_u32->target.type));
EXPECT_EQ(TypeOf(vec3_f32), TypeOf(vec3_f32->target.type));
}
TEST_F(ResolverTypeConstructorValidationTest, InferVec4ElementTypeFromScalars) {
auto* vec4_bool = Construct(create<ast::Vector>(nullptr, 4), Expr(true),
Expr(false), Expr(true), Expr(false));
auto* vec4_i32 = Construct(create<ast::Vector>(nullptr, 4), Expr(1), Expr(2),
Expr(3), Expr(4));
auto* vec4_u32 = Construct(create<ast::Vector>(nullptr, 4), Expr(1u),
Expr(2u), Expr(3u), Expr(4u));
auto* vec4_f32 = Construct(create<ast::Vector>(nullptr, 4), Expr(1.0f),
Expr(2.0f), Expr(3.0f), Expr(4.0f));
WrapInFunction(vec4_bool, vec4_i32, vec4_u32, vec4_f32);
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(vec4_bool)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_i32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_u32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_f32)->Is<sem::Vector>());
EXPECT_TRUE(TypeOf(vec4_bool)->As<sem::Vector>()->type()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(vec4_i32)->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(vec4_u32)->As<sem::Vector>()->type()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(vec4_f32)->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(TypeOf(vec4_bool)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_i32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_u32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_f32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_bool), TypeOf(vec4_bool->target.type));
EXPECT_EQ(TypeOf(vec4_i32), TypeOf(vec4_i32->target.type));
EXPECT_EQ(TypeOf(vec4_u32), TypeOf(vec4_u32->target.type));
EXPECT_EQ(TypeOf(vec4_f32), TypeOf(vec4_f32->target.type));
}
TEST_F(ResolverTypeConstructorValidationTest, InferVec4ElementTypeFromVec4) {
auto* vec4_bool = Construct(create<ast::Vector>(nullptr, 4),
vec4<bool>(true, false, true, false));
auto* vec4_i32 =
Construct(create<ast::Vector>(nullptr, 4), vec4<i32>(1, 2, 3, 4));
auto* vec4_u32 =
Construct(create<ast::Vector>(nullptr, 4), vec4<u32>(1u, 2u, 3u, 4u));
auto* vec4_f32 = Construct(create<ast::Vector>(nullptr, 4),
vec4<f32>(1.0f, 2.0f, 3.0f, 4.0f));
WrapInFunction(vec4_bool, vec4_i32, vec4_u32, vec4_f32);
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(vec4_bool)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_i32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_u32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_f32)->Is<sem::Vector>());
EXPECT_TRUE(TypeOf(vec4_bool)->As<sem::Vector>()->type()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(vec4_i32)->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(vec4_u32)->As<sem::Vector>()->type()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(vec4_f32)->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(TypeOf(vec4_bool)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_i32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_u32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_f32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_bool), TypeOf(vec4_bool->target.type));
EXPECT_EQ(TypeOf(vec4_i32), TypeOf(vec4_i32->target.type));
EXPECT_EQ(TypeOf(vec4_u32), TypeOf(vec4_u32->target.type));
EXPECT_EQ(TypeOf(vec4_f32), TypeOf(vec4_f32->target.type));
}
TEST_F(ResolverTypeConstructorValidationTest,
InferVec4ElementTypeFromScalarAndVec3) {
auto* vec4_bool = Construct(create<ast::Vector>(nullptr, 4), Expr(true),
vec3<bool>(false, true, false));
auto* vec4_i32 =
Construct(create<ast::Vector>(nullptr, 4), Expr(1), vec3<i32>(2, 3, 4));
auto* vec4_u32 = Construct(create<ast::Vector>(nullptr, 4), Expr(1u),
vec3<u32>(2u, 3u, 4u));
auto* vec4_f32 = Construct(create<ast::Vector>(nullptr, 4), Expr(1.0f),
vec3<f32>(2.0f, 3.0f, 4.0f));
WrapInFunction(vec4_bool, vec4_i32, vec4_u32, vec4_f32);
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(vec4_bool)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_i32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_u32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_f32)->Is<sem::Vector>());
EXPECT_TRUE(TypeOf(vec4_bool)->As<sem::Vector>()->type()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(vec4_i32)->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(vec4_u32)->As<sem::Vector>()->type()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(vec4_f32)->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(TypeOf(vec4_bool)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_i32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_u32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_f32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_bool), TypeOf(vec4_bool->target.type));
EXPECT_EQ(TypeOf(vec4_i32), TypeOf(vec4_i32->target.type));
EXPECT_EQ(TypeOf(vec4_u32), TypeOf(vec4_u32->target.type));
EXPECT_EQ(TypeOf(vec4_f32), TypeOf(vec4_f32->target.type));
}
TEST_F(ResolverTypeConstructorValidationTest,
InferVec4ElementTypeFromVec2AndVec2) {
auto* vec4_bool = Construct(create<ast::Vector>(nullptr, 4),
vec2<bool>(true, false), vec2<bool>(true, false));
auto* vec4_i32 = Construct(create<ast::Vector>(nullptr, 4), vec2<i32>(1, 2),
vec2<i32>(3, 4));
auto* vec4_u32 = Construct(create<ast::Vector>(nullptr, 4), vec2<u32>(1u, 2u),
vec2<u32>(3u, 4u));
auto* vec4_f32 = Construct(create<ast::Vector>(nullptr, 4),
vec2<f32>(1.0f, 2.0f), vec2<f32>(3.0f, 4.0f));
WrapInFunction(vec4_bool, vec4_i32, vec4_u32, vec4_f32);
ASSERT_TRUE(r()->Resolve()) << r()->error();
ASSERT_TRUE(TypeOf(vec4_bool)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_i32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_u32)->Is<sem::Vector>());
ASSERT_TRUE(TypeOf(vec4_f32)->Is<sem::Vector>());
EXPECT_TRUE(TypeOf(vec4_bool)->As<sem::Vector>()->type()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(vec4_i32)->As<sem::Vector>()->type()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(vec4_u32)->As<sem::Vector>()->type()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(vec4_f32)->As<sem::Vector>()->type()->Is<sem::F32>());
EXPECT_EQ(TypeOf(vec4_bool)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_i32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_u32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_f32)->As<sem::Vector>()->Width(), 4u);
EXPECT_EQ(TypeOf(vec4_bool), TypeOf(vec4_bool->target.type));
EXPECT_EQ(TypeOf(vec4_i32), TypeOf(vec4_i32->target.type));
EXPECT_EQ(TypeOf(vec4_u32), TypeOf(vec4_u32->target.type));
EXPECT_EQ(TypeOf(vec4_f32), TypeOf(vec4_f32->target.type));
}
TEST_F(ResolverTypeConstructorValidationTest,
CannotInferVectorElementTypeWithoutArgs) {
WrapInFunction(Construct(create<ast::Vector>(Source{{12, 34}}, nullptr, 3)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing vector element type");
}
TEST_F(ResolverTypeConstructorValidationTest,
CannotInferVec2ElementTypeFromScalarsMismatch) {
WrapInFunction(Construct(Source{{1, 1}}, create<ast::Vector>(nullptr, 2),
Expr(Source{{1, 2}}, 1), //
Expr(Source{{1, 3}}, 2u)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
R"(1:1 error: cannot infer vector element type, as constructor arguments have different types
1:2 note: argument 0 has type i32
1:3 note: argument 1 has type u32)");
}
TEST_F(ResolverTypeConstructorValidationTest,
CannotInferVec3ElementTypeFromScalarsMismatch) {
WrapInFunction(Construct(Source{{1, 1}}, create<ast::Vector>(nullptr, 3),
Expr(Source{{1, 2}}, 1), //
Expr(Source{{1, 3}}, 2u), //
Expr(Source{{1, 4}}, 3)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
R"(1:1 error: cannot infer vector element type, as constructor arguments have different types
1:2 note: argument 0 has type i32
1:3 note: argument 1 has type u32
1:4 note: argument 2 has type i32)");
}
TEST_F(ResolverTypeConstructorValidationTest,
CannotInferVec3ElementTypeFromScalarAndVec2Mismatch) {
WrapInFunction(
Construct(Source{{1, 1}}, create<ast::Vector>(nullptr, 3),
Expr(Source{{1, 2}}, 1), //
Construct(Source{{1, 3}}, ty.vec2<f32>(), 2.0f, 3.0f)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
R"(1:1 error: cannot infer vector element type, as constructor arguments have different types
1:2 note: argument 0 has type i32
1:3 note: argument 1 has type vec2<f32>)");
}
TEST_F(ResolverTypeConstructorValidationTest,
CannotInferVec4ElementTypeFromScalarsMismatch) {
WrapInFunction(Construct(Source{{1, 1}}, create<ast::Vector>(nullptr, 4),
Expr(Source{{1, 2}}, 1), //
Expr(Source{{1, 3}}, 2), //
Expr(Source{{1, 4}}, 3.0f), //
Expr(Source{{1, 5}}, 4)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
R"(1:1 error: cannot infer vector element type, as constructor arguments have different types
1:2 note: argument 0 has type i32
1:3 note: argument 1 has type i32
1:4 note: argument 2 has type f32
1:5 note: argument 3 has type i32)");
}
TEST_F(ResolverTypeConstructorValidationTest,
CannotInferVec4ElementTypeFromScalarAndVec3Mismatch) {
WrapInFunction(
Construct(Source{{1, 1}}, create<ast::Vector>(nullptr, 4),
Expr(Source{{1, 2}}, 1), //
Construct(Source{{1, 3}}, ty.vec3<u32>(), 2u, 3u, 4u)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
R"(1:1 error: cannot infer vector element type, as constructor arguments have different types
1:2 note: argument 0 has type i32
1:3 note: argument 1 has type vec3<u32>)");
}
TEST_F(ResolverTypeConstructorValidationTest,
CannotInferVec4ElementTypeFromVec2AndVec2Mismatch) {
WrapInFunction(Construct(Source{{1, 1}}, create<ast::Vector>(nullptr, 4),
Construct(Source{{1, 2}}, ty.vec2<i32>(), 3, 4), //
Construct(Source{{1, 3}}, ty.vec2<u32>(), 3u, 4u)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
R"(1:1 error: cannot infer vector element type, as constructor arguments have different types
1:2 note: argument 0 has type vec2<i32>
1:3 note: argument 1 has type vec2<u32>)");
}
} // namespace VectorConstructor } // namespace VectorConstructor
namespace MatrixConstructor { namespace MatrixConstructor {
@ -1841,10 +2221,15 @@ TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooFewArguments) {
const auto param = GetParam(); const auto param = GetParam();
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns - 1; i++) { for (uint32_t i = 1; i <= param.columns - 1; i++) {
auto* vec_type = ty.vec<f32>(param.rows); auto* vec_type = ty.vec<f32>(param.rows);
args.push_back(Construct(Source{{12, i}}, vec_type)); args.push_back(Construct(Source{{12, i}}, vec_type));
if (i > 1) {
args_tys << ", ";
}
args_tys << "vec" << param.rows << "<f32>";
} }
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
@ -1852,9 +2237,9 @@ TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooFewArguments) {
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooFewArguments) { TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooFewArguments) {
@ -1862,9 +2247,14 @@ TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooFewArguments) {
const auto param = GetParam(); const auto param = GetParam();
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns * param.rows - 1; i++) { for (uint32_t i = 1; i <= param.columns * param.rows - 1; i++) {
args.push_back(Construct(Source{{12, i}}, ty.f32())); args.push_back(Construct(Source{{12, i}}, ty.f32()));
if (i > 1) {
args_tys << ", ";
}
args_tys << "f32";
} }
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
@ -1872,9 +2262,9 @@ TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooFewArguments) {
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooManyArguments) { TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooManyArguments) {
@ -1882,10 +2272,15 @@ TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooManyArguments) {
const auto param = GetParam(); const auto param = GetParam();
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns + 1; i++) { for (uint32_t i = 1; i <= param.columns + 1; i++) {
auto* vec_type = ty.vec<f32>(param.rows); auto* vec_type = ty.vec<f32>(param.rows);
args.push_back(Construct(Source{{12, i}}, vec_type)); args.push_back(Construct(Source{{12, i}}, vec_type));
if (i > 1) {
args_tys << ", ";
}
args_tys << "vec" << param.rows << "<f32>";
} }
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
@ -1893,9 +2288,9 @@ TEST_P(MatrixConstructorTest, Expr_ColumnConstructor_Error_TooManyArguments) {
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooManyArguments) { TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooManyArguments) {
@ -1903,9 +2298,14 @@ TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooManyArguments) {
const auto param = GetParam(); const auto param = GetParam();
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns * param.rows + 1; i++) { for (uint32_t i = 1; i <= param.columns * param.rows + 1; i++) {
args.push_back(Construct(Source{{12, i}}, ty.f32())); args.push_back(Construct(Source{{12, i}}, ty.f32()));
if (i > 1) {
args_tys << ", ";
}
args_tys << "f32";
} }
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
@ -1913,9 +2313,9 @@ TEST_P(MatrixConstructorTest, Expr_ElementConstructor_Error_TooManyArguments) {
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, TEST_P(MatrixConstructorTest,
@ -1924,10 +2324,15 @@ TEST_P(MatrixConstructorTest,
const auto param = GetParam(); const auto param = GetParam();
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns; i++) { for (uint32_t i = 1; i <= param.columns; i++) {
auto* vec_type = ty.vec<u32>(param.rows); auto* vec_type = ty.vec<u32>(param.rows);
args.push_back(Construct(Source{{12, i}}, vec_type)); args.push_back(Construct(Source{{12, i}}, vec_type));
if (i > 1) {
args_tys << ", ";
}
args_tys << "vec" << param.rows << "<u32>";
} }
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
@ -1935,9 +2340,9 @@ TEST_P(MatrixConstructorTest,
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, TEST_P(MatrixConstructorTest,
@ -1946,9 +2351,14 @@ TEST_P(MatrixConstructorTest,
const auto param = GetParam(); const auto param = GetParam();
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns; i++) { for (uint32_t i = 1; i <= param.columns; i++) {
args.push_back(Expr(Source{{12, i}}, 1u)); args.push_back(Expr(Source{{12, i}}, 1u));
if (i > 1) {
args_tys << ", ";
}
args_tys << "u32";
} }
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
@ -1956,9 +2366,9 @@ TEST_P(MatrixConstructorTest,
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, TEST_P(MatrixConstructorTest,
@ -1972,23 +2382,29 @@ TEST_P(MatrixConstructorTest,
return; return;
} }
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns - 1; i++) { for (uint32_t i = 1; i <= param.columns - 1; i++) {
auto* valid_vec_type = ty.vec<f32>(param.rows); auto* valid_vec_type = ty.vec<f32>(param.rows);
args.push_back(Construct(Source{{12, i}}, valid_vec_type)); args.push_back(Construct(Source{{12, i}}, valid_vec_type));
if (i > 1) {
args_tys << ", ";
}
args_tys << "vec" << param.rows << "<f32>";
} }
const size_t kInvalidLoc = 2 * (param.columns - 1); const size_t kInvalidLoc = 2 * (param.columns - 1);
auto* invalid_vec_type = ty.vec<f32>(param.rows - 1); auto* invalid_vec_type = ty.vec<f32>(param.rows - 1);
args.push_back(Construct(Source{{12, kInvalidLoc}}, invalid_vec_type)); args.push_back(Construct(Source{{12, kInvalidLoc}}, invalid_vec_type));
args_tys << ", vec" << (param.rows - 1) << "<f32>";
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
auto* tc = Construct(Source{}, matrix_type, std::move(args)); auto* tc = Construct(Source{}, matrix_type, std::move(args));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, TEST_P(MatrixConstructorTest,
@ -1997,28 +2413,34 @@ TEST_P(MatrixConstructorTest,
const auto param = GetParam(); const auto param = GetParam();
// Skip the test if parameters would have resuled in an invalid vec5 type. // Skip the test if parameters would have resulted in an invalid vec5 type.
if (param.rows == 4) { if (param.rows == 4) {
return; return;
} }
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns - 1; i++) { for (uint32_t i = 1; i <= param.columns - 1; i++) {
auto* valid_vec_type = ty.vec<f32>(param.rows); auto* valid_vec_type = ty.vec<f32>(param.rows);
args.push_back(Construct(Source{{12, i}}, valid_vec_type)); args.push_back(Construct(Source{{12, i}}, valid_vec_type));
if (i > 1) {
args_tys << ", ";
}
args_tys << "vec" << param.rows << "<f32>";
} }
const size_t kInvalidLoc = 2 * (param.columns - 1); const size_t kInvalidLoc = 2 * (param.columns - 1);
auto* invalid_vec_type = ty.vec<f32>(param.rows + 1); auto* invalid_vec_type = ty.vec<f32>(param.rows + 1);
args.push_back(Construct(Source{{12, kInvalidLoc}}, invalid_vec_type)); args.push_back(Construct(Source{{12, kInvalidLoc}}, invalid_vec_type));
args_tys << ", vec" << (param.rows + 1) << "<f32>";
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
auto* tc = Construct(Source{}, matrix_type, std::move(args)); auto* tc = Construct(Source{}, matrix_type, std::move(args));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, Expr_Constructor_ZeroValue_Success) { TEST_P(MatrixConstructorTest, Expr_Constructor_ZeroValue_Success) {
@ -2073,10 +2495,15 @@ TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Error) {
const auto param = GetParam(); const auto param = GetParam();
auto* f32_alias = Alias("Float32", ty.f32()); auto* f32_alias = Alias("Float32", ty.f32());
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns; i++) { for (uint32_t i = 1; i <= param.columns; i++) {
auto* vec_type = ty.vec(ty.u32(), param.rows); auto* vec_type = ty.vec(ty.u32(), param.rows);
args.push_back(Construct(Source{{12, i}}, vec_type)); args.push_back(Construct(Source{{12, i}}, vec_type));
if (i > 1) {
args_tys << ", ";
}
args_tys << "vec" << param.rows << "<u32>";
} }
auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows); auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows);
@ -2084,9 +2511,9 @@ TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Error) {
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Success) { TEST_P(MatrixConstructorTest, Expr_Constructor_ElementTypeAlias_Success) {
@ -2116,8 +2543,9 @@ TEST_F(ResolverTypeConstructorValidationTest,
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(
R"(12:34 error: invalid constructor for mat2x2<f32> r()->error(),
R"(12:34 error: no matching constructor mat2x2<f32>(vec2<u32>, vec2<f32>)
3 candidates available: 3 candidates available:
mat2x2<f32>() mat2x2<f32>()
@ -2148,19 +2576,24 @@ TEST_P(MatrixConstructorTest, Expr_Constructor_ArgumentElementTypeAlias_Error) {
auto* matrix_type = ty.mat<f32>(param.columns, param.rows); auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
auto* f32_alias = Alias("UnsignedInt", ty.u32()); auto* f32_alias = Alias("UnsignedInt", ty.u32());
std::stringstream args_tys;
ast::ExpressionList args; ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns; i++) { for (uint32_t i = 1; i <= param.columns; i++) {
auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows); auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows);
args.push_back(Construct(Source{{12, i}}, vec_type)); args.push_back(Construct(Source{{12, i}}, vec_type));
if (i > 1) {
args_tys << ", ";
}
args_tys << "vec" << param.rows << "<u32>";
} }
auto* tc = Construct(Source{}, matrix_type, std::move(args)); auto* tc = Construct(Source{}, matrix_type, std::move(args));
WrapInFunction(tc); WrapInFunction(tc);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), EXPECT_THAT(r()->error(), HasSubstr("12:1 error: no matching constructor " +
HasSubstr("12:1 error: invalid constructor for " + MatrixStr(param) + "(" + args_tys.str() +
MatrixStr(param) + "\n\n3 candidates available:")); ")\n\n3 candidates available:"));
} }
TEST_P(MatrixConstructorTest, TEST_P(MatrixConstructorTest,
@ -2181,6 +2614,91 @@ TEST_P(MatrixConstructorTest,
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
} }
TEST_P(MatrixConstructorTest, InferElementTypeFromVectors) {
const auto param = GetParam();
ast::ExpressionList args;
for (uint32_t i = 1; i <= param.columns; i++) {
args.push_back(Construct(ty.vec<f32>(param.rows)));
}
auto* matrix_type = create<ast::Matrix>(nullptr, param.rows, param.columns);
auto* tc = Construct(Source{}, matrix_type, std::move(args));
WrapInFunction(tc);
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_P(MatrixConstructorTest, InferElementTypeFromScalars) {
const auto param = GetParam();
ast::ExpressionList args;
for (uint32_t i = 0; i < param.rows * param.columns; i++) {
args.push_back(Expr(static_cast<f32>(i)));
}
auto* matrix_type = create<ast::Matrix>(nullptr, param.rows, param.columns);
WrapInFunction(Construct(Source{{12, 34}}, matrix_type, std::move(args)));
ASSERT_TRUE(r()->Resolve()) << r()->error();
}
TEST_P(MatrixConstructorTest, CannotInferElementTypeFromVectors_Mismatch) {
const auto param = GetParam();
std::stringstream err;
err << "12:34 error: cannot infer matrix element type, as constructor "
"arguments have different types";
ast::ExpressionList args;
for (uint32_t i = 0; i < param.columns; i++) {
err << "\n";
auto src = Source{{1, 10 + i}};
if (i == 1) {
// Odd one out
args.push_back(Construct(src, ty.vec<i32>(param.rows)));
err << src << " note: argument " << i << " has type vec" << param.rows
<< "<i32>";
} else {
args.push_back(Construct(src, ty.vec<f32>(param.rows)));
err << src << " note: argument " << i << " has type vec" << param.rows
<< "<f32>";
}
}
auto* matrix_type = create<ast::Matrix>(nullptr, param.rows, param.columns);
WrapInFunction(Construct(Source{{12, 34}}, matrix_type, std::move(args)));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), err.str());
}
TEST_P(MatrixConstructorTest, CannotInferElementTypeFromScalars_Mismatch) {
const auto param = GetParam();
std::stringstream err;
err << "12:34 error: cannot infer matrix element type, as constructor "
"arguments have different types";
ast::ExpressionList args;
for (uint32_t i = 0; i < param.rows * param.columns; i++) {
err << "\n";
auto src = Source{{1, 10 + i}};
if (i == 3) {
args.push_back(Expr(src, static_cast<i32>(i))); // The odd one out
err << src << " note: argument " << i << " has type i32";
} else {
args.push_back(Expr(src, static_cast<f32>(i)));
err << src << " note: argument " << i << " has type f32";
}
}
auto* matrix_type = create<ast::Matrix>(nullptr, param.rows, param.columns);
WrapInFunction(Construct(Source{{12, 34}}, matrix_type, std::move(args)));
EXPECT_FALSE(r()->Resolve());
EXPECT_THAT(r()->error(), err.str());
}
INSTANTIATE_TEST_SUITE_P(ResolverTypeConstructorValidationTest, INSTANTIATE_TEST_SUITE_P(ResolverTypeConstructorValidationTest,
MatrixConstructorTest, MatrixConstructorTest,
testing::Values(MatrixDimensions{2, 2}, testing::Values(MatrixDimensions{2, 2},

View File

@ -416,6 +416,29 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayInFunction_Fail) {
"a struct"); "a struct");
} }
TEST_F(ResolverTypeValidationTest, Struct_Member_VectorNoType) {
// struct S {
// a: vec3;
// };
Structure("S",
{Member("a", create<ast::Vector>(Source{{12, 34}}, nullptr, 3))});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing vector element type");
}
TEST_F(ResolverTypeValidationTest, Struct_Member_MatrixNoType) {
// struct S {
// a: mat3x3;
// };
Structure(
"S", {Member("a", create<ast::Matrix>(Source{{12, 34}}, nullptr, 3, 3))});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing matrix element type");
}
TEST_F(ResolverTypeValidationTest, Struct_TooBig) { TEST_F(ResolverTypeValidationTest, Struct_TooBig) {
// struct Foo { // struct Foo {
// a: array<f32, 0x20000000>; // a: array<f32, 0x20000000>;
@ -795,9 +818,9 @@ TEST_P(StorageTextureDimensionTest, All) {
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} else { } else {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: cube dimensions for storage textures are not "
"12:34 error: cube dimensions for storage textures are not supported"); "supported");
} }
} }
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest, INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
@ -1064,9 +1087,9 @@ TEST_P(InvalidVectorElementTypes, InvalidElementType) {
Global("a", ty.vec(Source{{12, 34}}, params.elem_ty(*this), params.width), Global("a", ty.vec(Source{{12, 34}}, params.elem_ty(*this), params.width),
ast::StorageClass::kPrivate); ast::StorageClass::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: vector element type must be 'bool', 'f32', 'i32' "
"12:34 error: vector element type must be 'bool', 'f32', 'i32' or 'u32'"); "or 'u32'");
} }
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest, INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
InvalidVectorElementTypes, InvalidVectorElementTypes,

View File

@ -307,6 +307,42 @@ TEST_F(ResolverVarLetValidationTest, InvalidStorageClassForInitializer) {
"storage classes 'private' and 'function'"); "storage classes 'private' and 'function'");
} }
TEST_F(ResolverVarLetValidationTest, VectorLetNoType) {
// let a : mat3x3 = mat3x3<f32>();
WrapInFunction(Const("a", create<ast::Vector>(Source{{12, 34}}, nullptr, 3),
vec3<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing vector element type");
}
TEST_F(ResolverVarLetValidationTest, VectorVarNoType) {
// var a : mat3x3;
WrapInFunction(Var("a", create<ast::Vector>(Source{{12, 34}}, nullptr, 3)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing vector element type");
}
TEST_F(ResolverVarLetValidationTest, MatrixLetNoType) {
// let a : mat3x3 = mat3x3<f32>();
WrapInFunction(Const("a",
create<ast::Matrix>(Source{{12, 34}}, nullptr, 3, 3),
mat3x3<f32>()));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing matrix element type");
}
TEST_F(ResolverVarLetValidationTest, MatrixVarNoType) {
// var a : mat3x3;
WrapInFunction(
Var("a", create<ast::Matrix>(Source{{12, 34}}, nullptr, 3, 3)));
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: missing matrix element type");
}
} // namespace } // namespace
} // namespace resolver } // namespace resolver
} // namespace tint } // namespace tint

View File

@ -393,11 +393,14 @@ bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
} else if (ty->Is<ast::I32>()) { } else if (ty->Is<ast::I32>()) {
out << "i32"; out << "i32";
} else if (auto* mat = ty->As<ast::Matrix>()) { } else if (auto* mat = ty->As<ast::Matrix>()) {
out << "mat" << mat->columns << "x" << mat->rows << "<"; out << "mat" << mat->columns << "x" << mat->rows;
if (!EmitType(out, mat->type)) { if (auto* el_ty = mat->type) {
out << "<";
if (!EmitType(out, el_ty)) {
return false; return false;
} }
out << ">"; out << ">";
}
} else if (auto* ptr = ty->As<ast::Pointer>()) { } else if (auto* ptr = ty->As<ast::Pointer>()) {
out << "ptr<" << ptr->storage_class << ", "; out << "ptr<" << ptr->storage_class << ", ";
if (!EmitType(out, ptr->type)) { if (!EmitType(out, ptr->type)) {
@ -493,11 +496,14 @@ bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
} else if (ty->Is<ast::U32>()) { } else if (ty->Is<ast::U32>()) {
out << "u32"; out << "u32";
} else if (auto* vec = ty->As<ast::Vector>()) { } else if (auto* vec = ty->As<ast::Vector>()) {
out << "vec" << vec->width << "<"; out << "vec" << vec->width;
if (!EmitType(out, vec->type)) { if (auto* el_ty = vec->type) {
out << "<";
if (!EmitType(out, el_ty)) {
return false; return false;
} }
out << ">"; out << ">";
}
} else if (ty->Is<ast::Void>()) { } else if (ty->Is<ast::Void>()) {
out << "void"; out << "void";
} else if (auto* tn = ty->As<ast::TypeName>()) { } else if (auto* tn = ty->As<ast::TypeName>()) {

View File

@ -0,0 +1,2 @@
let m = mat2x2(0.0, 1.0,
2.0, 3.0);

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float2x2 m = float2x2(0.0f, 1.0f, 2.0f, 3.0f);

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float2x2 m = float2x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f));

View File

@ -0,0 +1,27 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 15
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%mat2v2float = OpTypeMatrix %v2float 2
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%6 = OpConstantComposite %v2float %float_0 %float_1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%9 = OpConstantComposite %v2float %float_2 %float_3
%m = OpConstantComposite %mat2v2float %6 %9
%void = OpTypeVoid
%11 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %11
%14 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat2x2(0.0, 1.0, 2.0, 3.0);

View File

@ -0,0 +1,2 @@
let m = mat2x2(vec2<f32>(0.0, 1.0),
vec2<f32>(2.0, 3.0));

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float2x2 m = float2x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f));

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float2x2 m = float2x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f));

View File

@ -0,0 +1,27 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 15
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%mat2v2float = OpTypeMatrix %v2float 2
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%6 = OpConstantComposite %v2float %float_0 %float_1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%9 = OpConstantComposite %v2float %float_2 %float_3
%m = OpConstantComposite %mat2v2float %6 %9
%void = OpTypeVoid
%11 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %11
%14 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat2x2(vec2<f32>(0.0, 1.0), vec2<f32>(2.0, 3.0));

View File

@ -0,0 +1,2 @@
let m = mat2x3(0.0, 1.0, 2.0,
3.0, 4.0, 5.0);

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float2x3 m = float2x3(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f);

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float2x3 m = float2x3(float3(0.0f, 1.0f, 2.0f), float3(3.0f, 4.0f, 5.0f));

View File

@ -0,0 +1,29 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 17
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%mat2v3float = OpTypeMatrix %v3float 2
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%7 = OpConstantComposite %v3float %float_0 %float_1 %float_2
%float_3 = OpConstant %float 3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%11 = OpConstantComposite %v3float %float_3 %float_4 %float_5
%m = OpConstantComposite %mat2v3float %7 %11
%void = OpTypeVoid
%13 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %13
%16 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat2x3(0.0, 1.0, 2.0, 3.0, 4.0, 5.0);

View File

@ -0,0 +1,2 @@
let m = mat2x3(vec3<f32>(0.0, 1.0, 2.0),
vec3<f32>(3.0, 4.0, 5.0));

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float2x3 m = float2x3(float3(0.0f, 1.0f, 2.0f), float3(3.0f, 4.0f, 5.0f));

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float2x3 m = float2x3(float3(0.0f, 1.0f, 2.0f), float3(3.0f, 4.0f, 5.0f));

View File

@ -0,0 +1,29 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 17
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%mat2v3float = OpTypeMatrix %v3float 2
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%7 = OpConstantComposite %v3float %float_0 %float_1 %float_2
%float_3 = OpConstant %float 3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%11 = OpConstantComposite %v3float %float_3 %float_4 %float_5
%m = OpConstantComposite %mat2v3float %7 %11
%void = OpTypeVoid
%13 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %13
%16 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat2x3(vec3<f32>(0.0, 1.0, 2.0), vec3<f32>(3.0, 4.0, 5.0));

View File

@ -0,0 +1,2 @@
let m = mat2x4(0.0, 1.0, 2.0, 3.0,
4.0, 5.0, 6.0, 7.0);

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float2x4 m = float2x4(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f);

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float2x4 m = float2x4(float4(0.0f, 1.0f, 2.0f, 3.0f), float4(4.0f, 5.0f, 6.0f, 7.0f));

View File

@ -0,0 +1,31 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 19
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%mat2v4float = OpTypeMatrix %v4float 2
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%8 = OpConstantComposite %v4float %float_0 %float_1 %float_2 %float_3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%13 = OpConstantComposite %v4float %float_4 %float_5 %float_6 %float_7
%m = OpConstantComposite %mat2v4float %8 %13
%void = OpTypeVoid
%15 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %15
%18 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat2x4(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0);

View File

@ -0,0 +1,2 @@
let m = mat2x4(vec4<f32>(0.0, 1.0, 2.0, 3.0),
vec4<f32>(4.0, 5.0, 6.0, 7.0));

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float2x4 m = float2x4(float4(0.0f, 1.0f, 2.0f, 3.0f), float4(4.0f, 5.0f, 6.0f, 7.0f));

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float2x4 m = float2x4(float4(0.0f, 1.0f, 2.0f, 3.0f), float4(4.0f, 5.0f, 6.0f, 7.0f));

View File

@ -0,0 +1,31 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 19
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%mat2v4float = OpTypeMatrix %v4float 2
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%8 = OpConstantComposite %v4float %float_0 %float_1 %float_2 %float_3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%13 = OpConstantComposite %v4float %float_4 %float_5 %float_6 %float_7
%m = OpConstantComposite %mat2v4float %8 %13
%void = OpTypeVoid
%15 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %15
%18 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat2x4(vec4<f32>(0.0, 1.0, 2.0, 3.0), vec4<f32>(4.0, 5.0, 6.0, 7.0));

View File

@ -0,0 +1,3 @@
let m = mat3x2(0.0, 1.0,
2.0, 3.0,
4.0, 5.0);

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float3x2 m = float3x2(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f);

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float3x2 m = float3x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f), float2(4.0f, 5.0f));

View File

@ -0,0 +1,30 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 18
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%mat3v2float = OpTypeMatrix %v2float 3
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%6 = OpConstantComposite %v2float %float_0 %float_1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%9 = OpConstantComposite %v2float %float_2 %float_3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%12 = OpConstantComposite %v2float %float_4 %float_5
%m = OpConstantComposite %mat3v2float %6 %9 %12
%void = OpTypeVoid
%14 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %14
%17 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat3x2(0.0, 1.0, 2.0, 3.0, 4.0, 5.0);

View File

@ -0,0 +1,3 @@
let m = mat3x2(vec2<f32>(0.0, 1.0),
vec2<f32>(2.0, 3.0),
vec2<f32>(4.0, 5.0));

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float3x2 m = float3x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f), float2(4.0f, 5.0f));

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float3x2 m = float3x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f), float2(4.0f, 5.0f));

View File

@ -0,0 +1,30 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 18
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%mat3v2float = OpTypeMatrix %v2float 3
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%6 = OpConstantComposite %v2float %float_0 %float_1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%9 = OpConstantComposite %v2float %float_2 %float_3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%12 = OpConstantComposite %v2float %float_4 %float_5
%m = OpConstantComposite %mat3v2float %6 %9 %12
%void = OpTypeVoid
%14 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %14
%17 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat3x2(vec2<f32>(0.0, 1.0), vec2<f32>(2.0, 3.0), vec2<f32>(4.0, 5.0));

View File

@ -0,0 +1,3 @@
let m = mat3x3(0.0, 1.0, 2.0,
3.0, 4.0, 5.0,
6.0, 7.0, 8.0);

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float3x3 m = float3x3(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float3x3 m = float3x3(float3(0.0f, 1.0f, 2.0f), float3(3.0f, 4.0f, 5.0f), float3(6.0f, 7.0f, 8.0f));

View File

@ -0,0 +1,33 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 21
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%mat3v3float = OpTypeMatrix %v3float 3
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%7 = OpConstantComposite %v3float %float_0 %float_1 %float_2
%float_3 = OpConstant %float 3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%11 = OpConstantComposite %v3float %float_3 %float_4 %float_5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%float_8 = OpConstant %float 8
%15 = OpConstantComposite %v3float %float_6 %float_7 %float_8
%m = OpConstantComposite %mat3v3float %7 %11 %15
%void = OpTypeVoid
%17 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %17
%20 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat3x3(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);

View File

@ -0,0 +1,3 @@
let m = mat3x3(vec3<f32>(0.0, 1.0, 2.0),
vec3<f32>(3.0, 4.0, 5.0),
vec3<f32>(6.0, 7.0, 8.0));

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float3x3 m = float3x3(float3(0.0f, 1.0f, 2.0f), float3(3.0f, 4.0f, 5.0f), float3(6.0f, 7.0f, 8.0f));

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float3x3 m = float3x3(float3(0.0f, 1.0f, 2.0f), float3(3.0f, 4.0f, 5.0f), float3(6.0f, 7.0f, 8.0f));

View File

@ -0,0 +1,33 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 21
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%mat3v3float = OpTypeMatrix %v3float 3
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%7 = OpConstantComposite %v3float %float_0 %float_1 %float_2
%float_3 = OpConstant %float 3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%11 = OpConstantComposite %v3float %float_3 %float_4 %float_5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%float_8 = OpConstant %float 8
%15 = OpConstantComposite %v3float %float_6 %float_7 %float_8
%m = OpConstantComposite %mat3v3float %7 %11 %15
%void = OpTypeVoid
%17 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %17
%20 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat3x3(vec3<f32>(0.0, 1.0, 2.0), vec3<f32>(3.0, 4.0, 5.0), vec3<f32>(6.0, 7.0, 8.0));

View File

@ -0,0 +1,3 @@
let m = mat3x4(0.0, 1.0, 2.0, 3.0,
4.0, 5.0, 6.0, 7.0,
8.0, 9.0, 10.0, 11.0);

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float3x4 m = float3x4(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f);

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float3x4 m = float3x4(float4(0.0f, 1.0f, 2.0f, 3.0f), float4(4.0f, 5.0f, 6.0f, 7.0f), float4(8.0f, 9.0f, 10.0f, 11.0f));

View File

@ -0,0 +1,36 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 24
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%mat3v4float = OpTypeMatrix %v4float 3
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%8 = OpConstantComposite %v4float %float_0 %float_1 %float_2 %float_3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%13 = OpConstantComposite %v4float %float_4 %float_5 %float_6 %float_7
%float_8 = OpConstant %float 8
%float_9 = OpConstant %float 9
%float_10 = OpConstant %float 10
%float_11 = OpConstant %float 11
%18 = OpConstantComposite %v4float %float_8 %float_9 %float_10 %float_11
%m = OpConstantComposite %mat3v4float %8 %13 %18
%void = OpTypeVoid
%20 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %20
%23 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat3x4(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0);

View File

@ -0,0 +1,3 @@
let m = mat3x4(vec4<f32>(0.0, 1.0, 2.0, 3.0),
vec4<f32>(4.0, 5.0, 6.0, 7.0),
vec4<f32>(8.0, 9.0, 10.0, 11.0));

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float3x4 m = float3x4(float4(0.0f, 1.0f, 2.0f, 3.0f), float4(4.0f, 5.0f, 6.0f, 7.0f), float4(8.0f, 9.0f, 10.0f, 11.0f));

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float3x4 m = float3x4(float4(0.0f, 1.0f, 2.0f, 3.0f), float4(4.0f, 5.0f, 6.0f, 7.0f), float4(8.0f, 9.0f, 10.0f, 11.0f));

View File

@ -0,0 +1,36 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 24
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%mat3v4float = OpTypeMatrix %v4float 3
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%8 = OpConstantComposite %v4float %float_0 %float_1 %float_2 %float_3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%13 = OpConstantComposite %v4float %float_4 %float_5 %float_6 %float_7
%float_8 = OpConstant %float 8
%float_9 = OpConstant %float 9
%float_10 = OpConstant %float 10
%float_11 = OpConstant %float 11
%18 = OpConstantComposite %v4float %float_8 %float_9 %float_10 %float_11
%m = OpConstantComposite %mat3v4float %8 %13 %18
%void = OpTypeVoid
%20 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %20
%23 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat3x4(vec4<f32>(0.0, 1.0, 2.0, 3.0), vec4<f32>(4.0, 5.0, 6.0, 7.0), vec4<f32>(8.0, 9.0, 10.0, 11.0));

View File

@ -0,0 +1,4 @@
let m = mat4x2(0.0, 1.0,
2.0, 3.0,
4.0, 5.0,
6.0, 7.0);

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float4x2 m = float4x2(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f);

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float4x2 m = float4x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f), float2(4.0f, 5.0f), float2(6.0f, 7.0f));

View File

@ -0,0 +1,33 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 21
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%mat4v2float = OpTypeMatrix %v2float 4
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%6 = OpConstantComposite %v2float %float_0 %float_1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%9 = OpConstantComposite %v2float %float_2 %float_3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%12 = OpConstantComposite %v2float %float_4 %float_5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%15 = OpConstantComposite %v2float %float_6 %float_7
%m = OpConstantComposite %mat4v2float %6 %9 %12 %15
%void = OpTypeVoid
%17 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %17
%20 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat4x2(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0);

View File

@ -0,0 +1,4 @@
let m = mat4x2(vec2<f32>(0.0, 1.0),
vec2<f32>(2.0, 3.0),
vec2<f32>(4.0, 5.0),
vec2<f32>(6.0, 7.0));

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float4x2 m = float4x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f), float2(4.0f, 5.0f), float2(6.0f, 7.0f));

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float4x2 m = float4x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f), float2(4.0f, 5.0f), float2(6.0f, 7.0f));

View File

@ -0,0 +1,33 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 21
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v2float = OpTypeVector %float 2
%mat4v2float = OpTypeMatrix %v2float 4
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%6 = OpConstantComposite %v2float %float_0 %float_1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%9 = OpConstantComposite %v2float %float_2 %float_3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%12 = OpConstantComposite %v2float %float_4 %float_5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%15 = OpConstantComposite %v2float %float_6 %float_7
%m = OpConstantComposite %mat4v2float %6 %9 %12 %15
%void = OpTypeVoid
%17 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %17
%20 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat4x2(vec2<f32>(0.0, 1.0), vec2<f32>(2.0, 3.0), vec2<f32>(4.0, 5.0), vec2<f32>(6.0, 7.0));

View File

@ -0,0 +1,4 @@
let m = mat4x3(0.0, 1.0, 2.0,
3.0, 4.0, 5.0,
6.0, 7.0, 8.0,
9.0, 10.0, 11.0);

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float4x3 m = float4x3(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f);

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float4x3 m = float4x3(float3(0.0f, 1.0f, 2.0f), float3(3.0f, 4.0f, 5.0f), float3(6.0f, 7.0f, 8.0f), float3(9.0f, 10.0f, 11.0f));

View File

@ -0,0 +1,37 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 25
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%mat4v3float = OpTypeMatrix %v3float 4
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%7 = OpConstantComposite %v3float %float_0 %float_1 %float_2
%float_3 = OpConstant %float 3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%11 = OpConstantComposite %v3float %float_3 %float_4 %float_5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%float_8 = OpConstant %float 8
%15 = OpConstantComposite %v3float %float_6 %float_7 %float_8
%float_9 = OpConstant %float 9
%float_10 = OpConstant %float 10
%float_11 = OpConstant %float 11
%19 = OpConstantComposite %v3float %float_9 %float_10 %float_11
%m = OpConstantComposite %mat4v3float %7 %11 %15 %19
%void = OpTypeVoid
%21 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %21
%24 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat4x3(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0);

View File

@ -0,0 +1,4 @@
let m = mat4x3(vec3<f32>(0.0, 1.0, 2.0),
vec3<f32>(3.0, 4.0, 5.0),
vec3<f32>(6.0, 7.0, 8.0),
vec3<f32>(9.0, 10.0, 11.0));

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float4x3 m = float4x3(float3(0.0f, 1.0f, 2.0f), float3(3.0f, 4.0f, 5.0f), float3(6.0f, 7.0f, 8.0f), float3(9.0f, 10.0f, 11.0f));

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float4x3 m = float4x3(float3(0.0f, 1.0f, 2.0f), float3(3.0f, 4.0f, 5.0f), float3(6.0f, 7.0f, 8.0f), float3(9.0f, 10.0f, 11.0f));

View File

@ -0,0 +1,37 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 25
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v3float = OpTypeVector %float 3
%mat4v3float = OpTypeMatrix %v3float 4
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%7 = OpConstantComposite %v3float %float_0 %float_1 %float_2
%float_3 = OpConstant %float 3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%11 = OpConstantComposite %v3float %float_3 %float_4 %float_5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%float_8 = OpConstant %float 8
%15 = OpConstantComposite %v3float %float_6 %float_7 %float_8
%float_9 = OpConstant %float 9
%float_10 = OpConstant %float 10
%float_11 = OpConstant %float 11
%19 = OpConstantComposite %v3float %float_9 %float_10 %float_11
%m = OpConstantComposite %mat4v3float %7 %11 %15 %19
%void = OpTypeVoid
%21 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %21
%24 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat4x3(vec3<f32>(0.0, 1.0, 2.0), vec3<f32>(3.0, 4.0, 5.0), vec3<f32>(6.0, 7.0, 8.0), vec3<f32>(9.0, 10.0, 11.0));

View File

@ -0,0 +1,4 @@
let m = mat4x4(0.0, 1.0, 2.0, 3.0,
4.0, 5.0, 6.0, 7.0,
8.0, 9.0, 10.0, 11.0,
12.0, 13.0, 14.0, 15.0);

View File

@ -0,0 +1,6 @@
[numthreads(1, 1, 1)]
void unused_entry_point() {
return;
}
static const float4x4 m = float4x4(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f);

View File

@ -0,0 +1,4 @@
#include <metal_stdlib>
using namespace metal;
constant float4x4 m = float4x4(float4(0.0f, 1.0f, 2.0f, 3.0f), float4(4.0f, 5.0f, 6.0f, 7.0f), float4(8.0f, 9.0f, 10.0f, 11.0f), float4(12.0f, 13.0f, 14.0f, 15.0f));

View File

@ -0,0 +1,41 @@
; SPIR-V
; Version: 1.3
; Generator: Google Tint Compiler; 0
; Bound: 29
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %unused_entry_point "unused_entry_point"
OpExecutionMode %unused_entry_point LocalSize 1 1 1
OpName %m "m"
OpName %unused_entry_point "unused_entry_point"
%float = OpTypeFloat 32
%v4float = OpTypeVector %float 4
%mat4v4float = OpTypeMatrix %v4float 4
%float_0 = OpConstant %float 0
%float_1 = OpConstant %float 1
%float_2 = OpConstant %float 2
%float_3 = OpConstant %float 3
%8 = OpConstantComposite %v4float %float_0 %float_1 %float_2 %float_3
%float_4 = OpConstant %float 4
%float_5 = OpConstant %float 5
%float_6 = OpConstant %float 6
%float_7 = OpConstant %float 7
%13 = OpConstantComposite %v4float %float_4 %float_5 %float_6 %float_7
%float_8 = OpConstant %float 8
%float_9 = OpConstant %float 9
%float_10 = OpConstant %float 10
%float_11 = OpConstant %float 11
%18 = OpConstantComposite %v4float %float_8 %float_9 %float_10 %float_11
%float_12 = OpConstant %float 12
%float_13 = OpConstant %float 13
%float_14 = OpConstant %float 14
%float_15 = OpConstant %float 15
%23 = OpConstantComposite %v4float %float_12 %float_13 %float_14 %float_15
%m = OpConstantComposite %mat4v4float %8 %13 %18 %23
%void = OpTypeVoid
%25 = OpTypeFunction %void
%unused_entry_point = OpFunction %void None %25
%28 = OpLabel
OpReturn
OpFunctionEnd

View File

@ -0,0 +1 @@
let m = mat4x4(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0);

View File

@ -0,0 +1,4 @@
let m = mat4x4(vec4<f32>(0.0, 1.0, 2.0, 3.0),
vec4<f32>(4.0, 5.0, 6.0, 7.0),
vec4<f32>(8.0, 9.0, 10.0, 11.0),
vec4<f32>(12.0, 13.0, 14.0, 15.0));

Some files were not shown because too many files have changed in this diff Show More