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:
parent
f91b02bba1
commit
81b3948649
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 char* use = "vector";
|
const ast::Type* subtype = nullptr;
|
||||||
|
if (peek_is(Token::Type::kLessThan)) {
|
||||||
|
const char* use = "vector";
|
||||||
|
auto ty = expect_lt_gt_block(use, [&] { return expect_type(use); });
|
||||||
|
if (ty.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
subtype = ty.value;
|
||||||
|
}
|
||||||
|
|
||||||
auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); });
|
return builder_.ty.vec(make_source_range_from(t.source()), subtype, count);
|
||||||
if (subtype.errored)
|
|
||||||
return Failure::kErrored;
|
|
||||||
|
|
||||||
return builder_.ty.vec(make_source_range_from(t.source()), subtype.value,
|
|
||||||
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 char* use = "matrix";
|
const ast::Type* subtype = nullptr;
|
||||||
|
if (peek_is(Token::Type::kLessThan)) {
|
||||||
|
const char* use = "matrix";
|
||||||
|
auto ty = expect_lt_gt_block(use, [&] { return expect_type(use); });
|
||||||
|
if (ty.errored) {
|
||||||
|
return Failure::kErrored;
|
||||||
|
}
|
||||||
|
subtype = ty.value;
|
||||||
|
}
|
||||||
|
|
||||||
auto subtype = expect_lt_gt_block(use, [&] { return expect_type(use); });
|
return builder_.ty.mat(make_source_range_from(t.source()), subtype, columns,
|
||||||
if (subtype.errored)
|
rows);
|
||||||
return Failure::kErrored;
|
|
||||||
|
|
||||||
return builder_.ty.mat(make_source_range_from(t.source()), subtype.value,
|
|
||||||
columns, rows);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storage_class
|
// storage_class
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
if (!ty) {
|
|
||||||
return 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) {
|
||||||
|
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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
return false;
|
out << "<";
|
||||||
|
if (!EmitType(out, el_ty)) {
|
||||||
|
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) {
|
||||||
return false;
|
out << "<";
|
||||||
|
if (!EmitType(out, el_ty)) {
|
||||||
|
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>()) {
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
let m = mat2x2(0.0, 1.0,
|
||||||
|
2.0, 3.0);
|
|
@ -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);
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
constant float2x2 m = float2x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f));
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
let m = mat2x2(0.0, 1.0, 2.0, 3.0);
|
|
@ -0,0 +1,2 @@
|
||||||
|
let m = mat2x2(vec2<f32>(0.0, 1.0),
|
||||||
|
vec2<f32>(2.0, 3.0));
|
|
@ -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));
|
|
@ -0,0 +1,4 @@
|
||||||
|
#include <metal_stdlib>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
constant float2x2 m = float2x2(float2(0.0f, 1.0f), float2(2.0f, 3.0f));
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
let m = mat2x2(vec2<f32>(0.0, 1.0), vec2<f32>(2.0, 3.0));
|
|
@ -0,0 +1,2 @@
|
||||||
|
let m = mat2x3(0.0, 1.0, 2.0,
|
||||||
|
3.0, 4.0, 5.0);
|
|
@ -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);
|
|
@ -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));
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
let m = mat2x3(0.0, 1.0, 2.0, 3.0, 4.0, 5.0);
|
|
@ -0,0 +1,2 @@
|
||||||
|
let m = mat2x3(vec3<f32>(0.0, 1.0, 2.0),
|
||||||
|
vec3<f32>(3.0, 4.0, 5.0));
|
|
@ -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));
|
|
@ -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));
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
let m = mat2x3(vec3<f32>(0.0, 1.0, 2.0), vec3<f32>(3.0, 4.0, 5.0));
|
|
@ -0,0 +1,2 @@
|
||||||
|
let m = mat2x4(0.0, 1.0, 2.0, 3.0,
|
||||||
|
4.0, 5.0, 6.0, 7.0);
|
|
@ -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);
|
|
@ -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));
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
let m = mat2x4(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0);
|
|
@ -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));
|
|
@ -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));
|
|
@ -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));
|
|
@ -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
|
|
@ -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));
|
|
@ -0,0 +1,3 @@
|
||||||
|
let m = mat3x2(0.0, 1.0,
|
||||||
|
2.0, 3.0,
|
||||||
|
4.0, 5.0);
|
|
@ -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);
|
|
@ -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));
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
let m = mat3x2(0.0, 1.0, 2.0, 3.0, 4.0, 5.0);
|
|
@ -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));
|
|
@ -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));
|
|
@ -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));
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
let m = mat3x2(vec2<f32>(0.0, 1.0), vec2<f32>(2.0, 3.0), vec2<f32>(4.0, 5.0));
|
|
@ -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);
|
|
@ -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);
|
|
@ -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));
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
let m = mat3x3(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
|
|
@ -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));
|
|
@ -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));
|
|
@ -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));
|
|
@ -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
|
|
@ -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));
|
|
@ -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);
|
|
@ -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);
|
|
@ -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));
|
|
@ -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
|
|
@ -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);
|
|
@ -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));
|
|
@ -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));
|
|
@ -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));
|
|
@ -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
|
|
@ -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));
|
|
@ -0,0 +1,4 @@
|
||||||
|
let m = mat4x2(0.0, 1.0,
|
||||||
|
2.0, 3.0,
|
||||||
|
4.0, 5.0,
|
||||||
|
6.0, 7.0);
|
|
@ -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);
|
|
@ -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));
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
let m = mat4x2(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0);
|
|
@ -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));
|
|
@ -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));
|
|
@ -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));
|
|
@ -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
|
|
@ -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));
|
|
@ -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);
|
|
@ -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);
|
|
@ -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));
|
|
@ -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
|
|
@ -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);
|
|
@ -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));
|
|
@ -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));
|
|
@ -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));
|
|
@ -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
|
|
@ -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));
|
|
@ -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);
|
|
@ -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);
|
|
@ -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));
|
|
@ -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
|
|
@ -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);
|
|
@ -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
Loading…
Reference in New Issue