tint/resolver: Add f16 types, constructor, and conversions

This patch add f16 types and their constructors and conversions in
resolver and intrinsic table. Also implement relating unit tests.

Bug: tint:1473, tint:1502
Change-Id: Ida1336193a72a73959e50e6a3eb12be44c0396b5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94642
Commit-Queue: Zhaoming Jiang <zhaoming.jiang@intel.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Zhaoming Jiang 2022-06-28 14:03:36 +00:00 committed by Dawn LUCI CQ
parent 53af158366
commit 6058882d4b
45 changed files with 6086 additions and 4399 deletions

View File

@ -71,11 +71,12 @@ enum texel_format {
// https://gpuweb.github.io/gpuweb/wgsl/#plain-types-section // https://gpuweb.github.io/gpuweb/wgsl/#plain-types-section
type bool type bool
@precedence(4) @display("abstract-float") type af @precedence(5) @display("abstract-float") type af
@precedence(3) @display("abstract-int") type ai @precedence(4) @display("abstract-int") type ai
@precedence(2) type i32 @precedence(3) type i32
@precedence(1) type u32 @precedence(2) type u32
@precedence(0) type f32 @precedence(1) type f32
@precedence(0) type f16
type vec2<T> type vec2<T>
type vec3<T> type vec3<T>
type vec4<T> type vec4<T>
@ -126,16 +127,19 @@ type __atomic_compare_exchange_result<T>
// A type matcher that can match one or more types. // // A type matcher that can match one or more types. //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
match f32f16: f32 | f16
match fiu32: f32 | i32 | u32 match fiu32: f32 | i32 | u32
match fi32: f32 | i32 match fi32: f32 | i32
match iu32: i32 | u32 match iu32: i32 | u32
match scalar: f32 | i32 | u32 | bool match scalar: f32 | f16 | i32 | u32 | bool
match abstract_or_scalar: ai | af | f32 | i32 | u32 | bool match abstract_or_scalar: ai | af | f32 | f16 | i32 | u32 | bool
match af_f32: af | f32 match af_f32: af | f32
match scalar_no_f32: i32 | u32 | bool match af_f32f16: af | f32 | f16
match scalar_no_i32: f32 | u32 | bool match scalar_no_f32: i32 | f16 | u32 | bool
match scalar_no_u32: f32 | i32 | bool match scalar_no_f16: f32 | i32 | u32 | bool
match scalar_no_bool: f32 | i32 | u32 match scalar_no_i32: f32 | f16 | u32 | bool
match scalar_no_u32: f32 | f16 | i32 | bool
match scalar_no_bool: f32 | f16 | i32 | u32
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Enum matchers // // Enum matchers //
@ -437,9 +441,9 @@ fn reverseBits<T: iu32>(T) -> T
fn reverseBits<N: num, T: iu32>(vec<N, T>) -> vec<N, T> fn reverseBits<N: num, T: iu32>(vec<N, T>) -> vec<N, T>
fn round(f32) -> f32 fn round(f32) -> f32
fn round<N: num>(vec<N, f32>) -> vec<N, f32> fn round<N: num>(vec<N, f32>) -> vec<N, f32>
fn select<T: scalar>(T, T, bool) -> T fn select<T: scalar_no_f16>(T, T, bool) -> T
fn select<T: scalar, N: num>(vec<N, T>, vec<N, T>, bool) -> vec<N, T> fn select<T: scalar_no_f16, N: num>(vec<N, T>, vec<N, T>, bool) -> vec<N, T>
fn select<N: num, T: scalar>(vec<N, T>, vec<N, T>, vec<N, bool>) -> vec<N, T> fn select<N: num, T: scalar_no_f16>(vec<N, T>, vec<N, T>, vec<N, bool>) -> vec<N, T>
fn sign(f32) -> f32 fn sign(f32) -> f32
fn sign<N: num>(vec<N, f32>) -> vec<N, f32> fn sign<N: num>(vec<N, f32>) -> vec<N, f32>
fn sin(f32) -> f32 fn sin(f32) -> f32
@ -629,37 +633,39 @@ fn textureLoad(texture: texture_external, coords: vec2<i32>) -> vec4<f32>
ctor i32() -> i32 ctor i32() -> i32
ctor u32() -> u32 ctor u32() -> u32
ctor f32() -> f32 ctor f32() -> f32
ctor f16() -> f16
ctor bool() -> bool ctor bool() -> bool
ctor vec2<T: scalar>() -> vec2<T> ctor vec2<T: scalar>() -> vec2<T>
ctor vec3<T: scalar>() -> vec3<T> ctor vec3<T: scalar>() -> vec3<T>
ctor vec4<T: scalar>() -> vec4<T> ctor vec4<T: scalar>() -> vec4<T>
ctor mat2x2() -> mat2x2<f32> ctor mat2x2<T: f32f16>() -> mat2x2<T>
ctor mat2x3() -> mat2x3<f32> ctor mat2x3<T: f32f16>() -> mat2x3<T>
ctor mat2x4() -> mat2x4<f32> ctor mat2x4<T: f32f16>() -> mat2x4<T>
ctor mat3x2() -> mat3x2<f32> ctor mat3x2<T: f32f16>() -> mat3x2<T>
ctor mat3x3() -> mat3x3<f32> ctor mat3x3<T: f32f16>() -> mat3x3<T>
ctor mat3x4() -> mat3x4<f32> ctor mat3x4<T: f32f16>() -> mat3x4<T>
ctor mat4x2() -> mat4x2<f32> ctor mat4x2<T: f32f16>() -> mat4x2<T>
ctor mat4x3() -> mat4x3<f32> ctor mat4x3<T: f32f16>() -> mat4x3<T>
ctor mat4x4() -> mat4x4<f32> ctor mat4x4<T: f32f16>() -> mat4x4<T>
// Identity constructors // Identity constructors
ctor i32(i32) -> i32 ctor i32(i32) -> i32
ctor u32(u32) -> u32 ctor u32(u32) -> u32
ctor f32(f32) -> f32 ctor f32(f32) -> f32
ctor f16(f16) -> f16
ctor bool(bool) -> bool ctor bool(bool) -> bool
ctor vec2<T: scalar>(vec2<T>) -> vec2<T> ctor vec2<T: scalar>(vec2<T>) -> vec2<T>
ctor vec3<T: scalar>(vec3<T>) -> vec3<T> ctor vec3<T: scalar>(vec3<T>) -> vec3<T>
ctor vec4<T: scalar>(vec4<T>) -> vec4<T> ctor vec4<T: scalar>(vec4<T>) -> vec4<T>
ctor mat2x2<f32>(mat2x2<f32>) -> mat2x2<f32> ctor mat2x2<T: f32f16>(mat2x2<T>) -> mat2x2<T>
ctor mat2x3<f32>(mat2x3<f32>) -> mat2x3<f32> ctor mat2x3<T: f32f16>(mat2x3<T>) -> mat2x3<T>
ctor mat2x4<f32>(mat2x4<f32>) -> mat2x4<f32> ctor mat2x4<T: f32f16>(mat2x4<T>) -> mat2x4<T>
ctor mat3x2<f32>(mat3x2<f32>) -> mat3x2<f32> ctor mat3x2<T: f32f16>(mat3x2<T>) -> mat3x2<T>
ctor mat3x3<f32>(mat3x3<f32>) -> mat3x3<f32> ctor mat3x3<T: f32f16>(mat3x3<T>) -> mat3x3<T>
ctor mat3x4<f32>(mat3x4<f32>) -> mat3x4<f32> ctor mat3x4<T: f32f16>(mat3x4<T>) -> mat3x4<T>
ctor mat4x2<f32>(mat4x2<f32>) -> mat4x2<f32> ctor mat4x2<T: f32f16>(mat4x2<T>) -> mat4x2<T>
ctor mat4x3<f32>(mat4x3<f32>) -> mat4x3<f32> ctor mat4x3<T: f32f16>(mat4x3<T>) -> mat4x3<T>
ctor mat4x4<f32>(mat4x4<f32>) -> mat4x4<f32> ctor mat4x4<T: f32f16>(mat4x4<T>) -> mat4x4<T>
// Vector constructors // Vector constructors
ctor vec2<T: abstract_or_scalar>(T) -> vec2<T> ctor vec2<T: abstract_or_scalar>(T) -> vec2<T>
@ -679,82 +685,106 @@ ctor vec4<T: abstract_or_scalar>(x: T, zyw: vec3<T>) -> vec4<T>
// Matrix constructors // Matrix constructors
ctor mat2x2<T: af_f32>(T) -> mat2x2<T> ctor mat2x2<T: af_f32>(T) -> mat2x2<T>
ctor mat2x2<T: af_f32>(T, T,
T, T) -> mat2x2<T>
ctor mat2x2<T: af_f32>(vec2<T>, vec2<T>) -> mat2x2<T>
ctor mat2x3<T: af_f32>(T) -> mat2x3<T> ctor mat2x3<T: af_f32>(T) -> mat2x3<T>
ctor mat2x3<T: af_f32>(T, T, T,
T, T, T) -> mat2x3<T>
ctor mat2x3<T: af_f32>(vec3<T>, vec3<T>) -> mat2x3<T>
ctor mat2x4<T: af_f32>(T) -> mat2x4<T> ctor mat2x4<T: af_f32>(T) -> mat2x4<T>
ctor mat2x4<T: af_f32>(T, T, T, T,
T, T, T, T) -> mat2x4<T>
ctor mat2x4<T: af_f32>(vec4<T>, vec4<T>) -> mat2x4<T>
ctor mat3x2<T: af_f32>(T) -> mat3x2<T> ctor mat3x2<T: af_f32>(T) -> mat3x2<T>
ctor mat3x2<T: af_f32>(T, T,
T, T,
T, T) -> mat3x2<T>
ctor mat3x2<T: af_f32>(vec2<T>, vec2<T>, vec2<T>) -> mat3x2<T>
ctor mat3x3<T: af_f32>(T) -> mat3x3<T> ctor mat3x3<T: af_f32>(T) -> mat3x3<T>
ctor mat3x3<T: af_f32>(T, T, T,
T, T, T,
T, T, T) -> mat3x3<T>
ctor mat3x3<T: af_f32>(vec3<T>, vec3<T>, vec3<T>) -> mat3x3<T>
ctor mat3x4<T: af_f32>(T) -> mat3x4<T> ctor mat3x4<T: af_f32>(T) -> mat3x4<T>
ctor mat3x4<T: af_f32>(T, T, T, T,
T, T, T, T,
T, T, T, T) -> mat3x4<T>
ctor mat3x4<T: af_f32>(vec4<T>, vec4<T>, vec4<T>) -> mat3x4<T>
ctor mat4x2<T: af_f32>(T) -> mat4x2<T> ctor mat4x2<T: af_f32>(T) -> mat4x2<T>
ctor mat4x2<T: af_f32>(T, T,
T, T,
T, T,
T, T) -> mat4x2<T>
ctor mat4x2<T: af_f32>(vec2<T>, vec2<T>, vec2<T>, vec2<T>) -> mat4x2<T>
ctor mat4x3<T: af_f32>(T) -> mat4x3<T> ctor mat4x3<T: af_f32>(T) -> mat4x3<T>
ctor mat4x3<T: af_f32>(T, T, T,
T, T, T,
T, T, T,
T, T, T) -> mat4x3<T>
ctor mat4x3<T: af_f32>(vec3<T>, vec3<T>, vec3<T>, vec3<T>) -> mat4x3<T>
ctor mat4x4<T: af_f32>(T) -> mat4x4<T> ctor mat4x4<T: af_f32>(T) -> mat4x4<T>
ctor mat4x4<T: af_f32>(T, T, T, T,
T, T, T, T, ctor mat2x2<T: af_f32f16>(T, T,
T, T, T, T, T, T) -> mat2x2<T>
T, T, T, T) -> mat4x4<T> ctor mat2x2<T: af_f32f16>(vec2<T>, vec2<T>) -> mat2x2<T>
ctor mat4x4<T: af_f32>(vec4<T>, vec4<T>, vec4<T>, vec4<T>) -> mat4x4<T>
ctor mat2x3<T: af_f32f16>(T, T, T,
T, T, T) -> mat2x3<T>
ctor mat2x3<T: af_f32f16>(vec3<T>, vec3<T>) -> mat2x3<T>
ctor mat2x4<T: af_f32f16>(T, T, T, T,
T, T, T, T) -> mat2x4<T>
ctor mat2x4<T: af_f32f16>(vec4<T>, vec4<T>) -> mat2x4<T>
ctor mat3x2<T: af_f32f16>(T, T,
T, T,
T, T) -> mat3x2<T>
ctor mat3x2<T: af_f32f16>(vec2<T>, vec2<T>, vec2<T>) -> mat3x2<T>
ctor mat3x3<T: af_f32f16>(T, T, T,
T, T, T,
T, T, T) -> mat3x3<T>
ctor mat3x3<T: af_f32f16>(vec3<T>, vec3<T>, vec3<T>) -> mat3x3<T>
ctor mat3x4<T: af_f32f16>(T, T, T, T,
T, T, T, T,
T, T, T, T) -> mat3x4<T>
ctor mat3x4<T: af_f32f16>(vec4<T>, vec4<T>, vec4<T>) -> mat3x4<T>
ctor mat4x2<T: af_f32f16>(T, T,
T, T,
T, T,
T, T) -> mat4x2<T>
ctor mat4x2<T: af_f32f16>(vec2<T>, vec2<T>, vec2<T>, vec2<T>) -> mat4x2<T>
ctor mat4x3<T: af_f32f16>(T, T, T,
T, T, T,
T, T, T,
T, T, T) -> mat4x3<T>
ctor mat4x3<T: af_f32f16>(vec3<T>, vec3<T>, vec3<T>, vec3<T>) -> mat4x3<T>
ctor mat4x4<T: af_f32f16>(T, T, T, T,
T, T, T, T,
T, T, T, T,
T, T, T, T) -> mat4x4<T>
ctor mat4x4<T: af_f32f16>(vec4<T>, vec4<T>, vec4<T>, vec4<T>) -> mat4x4<T>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Type conversions // // Type conversions //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
conv f32<T: scalar_no_f32>(T) -> f32 conv f32<T: scalar_no_f32>(T) -> f32
conv f16<T: scalar_no_f16>(T) -> f16
conv i32<T: scalar_no_i32>(T) -> i32 conv i32<T: scalar_no_i32>(T) -> i32
conv u32<T: scalar_no_u32>(T) -> u32 conv u32<T: scalar_no_u32>(T) -> u32
conv bool<T: scalar_no_bool>(T) -> bool conv bool<T: scalar_no_bool>(T) -> bool
conv vec2<T: f32, U: scalar_no_f32>(vec2<U>) -> vec2<f32> conv vec2<T: f32, U: scalar_no_f32>(vec2<U>) -> vec2<f32>
conv vec2<T: f16, U: scalar_no_f16>(vec2<U>) -> vec2<f16>
conv vec2<T: i32, U: scalar_no_i32>(vec2<U>) -> vec2<i32> conv vec2<T: i32, U: scalar_no_i32>(vec2<U>) -> vec2<i32>
conv vec2<T: u32, U: scalar_no_u32>(vec2<U>) -> vec2<u32> conv vec2<T: u32, U: scalar_no_u32>(vec2<U>) -> vec2<u32>
conv vec2<T: bool, U: scalar_no_bool>(vec2<U>) -> vec2<bool> conv vec2<T: bool, U: scalar_no_bool>(vec2<U>) -> vec2<bool>
conv vec3<T: f32, U: scalar_no_f32>(vec3<U>) -> vec3<f32> conv vec3<T: f32, U: scalar_no_f32>(vec3<U>) -> vec3<f32>
conv vec3<T: f16, U: scalar_no_f16>(vec3<U>) -> vec3<f16>
conv vec3<T: i32, U: scalar_no_i32>(vec3<U>) -> vec3<i32> conv vec3<T: i32, U: scalar_no_i32>(vec3<U>) -> vec3<i32>
conv vec3<T: u32, U: scalar_no_u32>(vec3<U>) -> vec3<u32> conv vec3<T: u32, U: scalar_no_u32>(vec3<U>) -> vec3<u32>
conv vec3<T: bool, U: scalar_no_bool>(vec3<U>) -> vec3<bool> conv vec3<T: bool, U: scalar_no_bool>(vec3<U>) -> vec3<bool>
conv vec4<T: f32, U: scalar_no_f32>(vec4<U>) -> vec4<f32> conv vec4<T: f32, U: scalar_no_f32>(vec4<U>) -> vec4<f32>
conv vec4<T: f16, U: scalar_no_f16>(vec4<U>) -> vec4<f16>
conv vec4<T: i32, U: scalar_no_i32>(vec4<U>) -> vec4<i32> conv vec4<T: i32, U: scalar_no_i32>(vec4<U>) -> vec4<i32>
conv vec4<T: u32, U: scalar_no_u32>(vec4<U>) -> vec4<u32> conv vec4<T: u32, U: scalar_no_u32>(vec4<U>) -> vec4<u32>
conv vec4<T: bool, U: scalar_no_bool>(vec4<U>) -> vec4<bool> conv vec4<T: bool, U: scalar_no_bool>(vec4<U>) -> vec4<bool>
conv mat2x2<T: f16>(mat2x2<f32>) -> mat2x2<f16>
conv mat2x2<T: f32>(mat2x2<f16>) -> mat2x2<f32>
conv mat2x3<T: f16>(mat2x3<f32>) -> mat2x3<f16>
conv mat2x3<T: f32>(mat2x3<f16>) -> mat2x3<f32>
conv mat2x4<T: f16>(mat2x4<f32>) -> mat2x4<f16>
conv mat2x4<T: f32>(mat2x4<f16>) -> mat2x4<f32>
conv mat3x2<T: f16>(mat3x2<f32>) -> mat3x2<f16>
conv mat3x2<T: f32>(mat3x2<f16>) -> mat3x2<f32>
conv mat3x3<T: f16>(mat3x3<f32>) -> mat3x3<f16>
conv mat3x3<T: f32>(mat3x3<f16>) -> mat3x3<f32>
conv mat3x4<T: f16>(mat3x4<f32>) -> mat3x4<f16>
conv mat3x4<T: f32>(mat3x4<f16>) -> mat3x4<f32>
conv mat4x2<T: f16>(mat4x2<f32>) -> mat4x2<f16>
conv mat4x2<T: f32>(mat4x2<f16>) -> mat4x2<f32>
conv mat4x3<T: f16>(mat4x3<f32>) -> mat4x3<f16>
conv mat4x3<T: f32>(mat4x3<f16>) -> mat4x3<f32>
conv mat4x4<T: f16>(mat4x4<f32>) -> mat4x4<f16>
conv mat4x4<T: f32>(mat4x4<f16>) -> mat4x4<f32>
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Operators // // Operators //
// // // //

View File

@ -351,7 +351,8 @@ class Token {
bool IsLiteral() const { bool IsLiteral() const {
return type_ == Type::kIntLiteral || type_ == Type::kIntLiteral_I || return type_ == Type::kIntLiteral || type_ == Type::kIntLiteral_I ||
type_ == Type::kIntLiteral_U || type_ == Type::kFalse || type_ == Type::kTrue || type_ == Type::kIntLiteral_U || type_ == Type::kFalse || type_ == Type::kTrue ||
type_ == Type::kFloatLiteral || type_ == Type::kFloatLiteral_F; type_ == Type::kFloatLiteral || type_ == Type::kFloatLiteral_F ||
type_ == Type::kFloatLiteral_H;
} }
/// @returns true if token is a 'matNxM' /// @returns true if token is a 'matNxM'
bool IsMatrix() const { bool IsMatrix() const {

View File

@ -85,6 +85,8 @@ TEST_F(TokenTest, ToStr) {
EXPECT_THAT(Token(Token::Type::kFloatLiteral, Source{}, d).to_str(), Not(EndsWith("f"))); EXPECT_THAT(Token(Token::Type::kFloatLiteral, Source{}, d).to_str(), Not(EndsWith("f")));
EXPECT_THAT(Token(Token::Type::kFloatLiteral_F, Source{}, d).to_str(), StartsWith("123")); EXPECT_THAT(Token(Token::Type::kFloatLiteral_F, Source{}, d).to_str(), StartsWith("123"));
EXPECT_THAT(Token(Token::Type::kFloatLiteral_F, Source{}, d).to_str(), EndsWith("f")); EXPECT_THAT(Token(Token::Type::kFloatLiteral_F, Source{}, d).to_str(), EndsWith("f"));
EXPECT_THAT(Token(Token::Type::kFloatLiteral_H, Source{}, d).to_str(), StartsWith("123"));
EXPECT_THAT(Token(Token::Type::kFloatLiteral_H, Source{}, d).to_str(), EndsWith("h"));
EXPECT_EQ(Token(Token::Type::kIntLiteral, Source{}, i).to_str(), "123"); EXPECT_EQ(Token(Token::Type::kIntLiteral, Source{}, i).to_str(), "123");
EXPECT_EQ(Token(Token::Type::kIntLiteral_I, Source{}, i).to_str(), "123i"); EXPECT_EQ(Token(Token::Type::kIntLiteral_I, Source{}, i).to_str(), "123i");
EXPECT_EQ(Token(Token::Type::kIntLiteral_U, Source{}, i).to_str(), "123u"); EXPECT_EQ(Token(Token::Type::kIntLiteral_U, Source{}, i).to_str(), "123u");

View File

@ -71,6 +71,7 @@ static constexpr Params all_param_types[] = {
ParamsFor<u32>(), // ParamsFor<u32>(), //
ParamsFor<i32>(), // ParamsFor<i32>(), //
ParamsFor<f32>(), // ParamsFor<f32>(), //
ParamsFor<f16>(), //
ParamsFor<vec3<bool>>(), // ParamsFor<vec3<bool>>(), //
ParamsFor<vec3<i32>>(), // ParamsFor<vec3<i32>>(), //
ParamsFor<vec3<u32>>(), // ParamsFor<vec3<u32>>(), //
@ -81,6 +82,8 @@ static constexpr Params all_param_types[] = {
}; };
TEST_F(ResolverCallTest, Valid) { TEST_F(ResolverCallTest, Valid) {
Enable(ast::Extension::kF16);
ast::ParameterList params; ast::ParameterList params;
ast::ExpressionList args; ast::ExpressionList args;
for (auto& p : all_param_types) { for (auto& p : all_param_types) {

View File

@ -36,6 +36,8 @@ const char* str(CtorConvIntrinsic i) {
return "u32"; return "u32";
case CtorConvIntrinsic::kF32: case CtorConvIntrinsic::kF32:
return "f32"; return "f32";
case CtorConvIntrinsic::kF16:
return "f16";
case CtorConvIntrinsic::kBool: case CtorConvIntrinsic::kBool:
return "bool"; return "bool";
case CtorConvIntrinsic::kVec2: case CtorConvIntrinsic::kVec2:

View File

@ -36,6 +36,7 @@ enum class CtorConvIntrinsic {
kI32, kI32,
kU32, kU32,
kF32, kF32,
kF16,
kBool, kBool,
kVec2, kVec2,
kVec3, kVec3,

View File

@ -104,15 +104,19 @@ TEST_F(ResolverHostShareableValidationTest, NestedStructures) {
} }
TEST_F(ResolverHostShareableValidationTest, NoError) { TEST_F(ResolverHostShareableValidationTest, NoError) {
Enable(ast::Extension::kF16);
auto* i1 = Structure("I1", { auto* i1 = Structure("I1", {
Member(Source{{1, 1}}, "x1", ty.f32()), Member(Source{{1, 1}}, "w1", ty.f16()),
Member(Source{{2, 1}}, "y1", ty.vec3<f32>()), Member(Source{{2, 1}}, "x1", ty.f32()),
Member(Source{{3, 1}}, "z1", ty.array<i32, 4>()), Member(Source{{3, 1}}, "y1", ty.vec3<f32>()),
Member(Source{{4, 1}}, "z1", ty.array<i32, 4>()),
}); });
auto* a1 = Alias("a1", ty.Of(i1)); auto* a1 = Alias("a1", ty.Of(i1));
auto* i2 = Structure("I2", { auto* i2 = Structure("I2", {
Member(Source{{4, 1}}, "x2", ty.mat2x2<f32>()), Member(Source{{5, 1}}, "x2", ty.mat2x2<f32>()),
Member(Source{{5, 1}}, "y2", ty.Of(i1)), Member(Source{{6, 1}}, "w2", ty.mat3x4<f16>()),
Member(Source{{7, 1}}, "z2", ty.Of(i1)),
}); });
auto* a2 = Alias("a2", ty.Of(i2)); auto* a2 = Alias("a2", ty.Of(i2));
auto* i3 = Structure("I3", { auto* i3 = Structure("I3", {

View File

@ -341,6 +341,14 @@ const sem::Bool* build_bool(MatchState& state) {
return state.builder.create<sem::Bool>(); return state.builder.create<sem::Bool>();
} }
const sem::F16* build_f16(MatchState& state) {
return state.builder.create<sem::F16>();
}
bool match_f16(const sem::Type* ty) {
return ty->IsAnyOf<Any, sem::F16, sem::AbstractNumeric>();
}
const sem::F32* build_f32(MatchState& state) { const sem::F32* build_f32(MatchState& state) {
return state.builder.create<sem::F32>(); return state.builder.create<sem::F32>();
} }

File diff suppressed because it is too large Load Diff

View File

@ -709,18 +709,19 @@ TEST_F(IntrinsicTableTest, MismatchTypeConstructorImplicit) {
EXPECT_EQ(Diagnostics().str(), R"(12:34 error: no matching constructor for vec3(i32, f32, i32) EXPECT_EQ(Diagnostics().str(), R"(12:34 error: no matching constructor for vec3(i32, f32, i32)
6 candidate constructors: 6 candidate constructors:
vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(xy: vec2<T>, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(xy: vec2<T>, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(x: T, yz: vec2<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(x: T, yz: vec2<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(T) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(vec3<T>) -> vec3<T> where: T is f32, i32, u32 or bool vec3(vec3<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
vec3() -> vec3<T> where: T is f32, i32, u32 or bool vec3() -> vec3<T> where: T is f32, f16, i32, u32 or bool
4 candidate conversions: 5 candidate conversions:
vec3(vec3<U>) -> vec3<f32> where: T is f32, U is i32, u32 or bool vec3(vec3<U>) -> vec3<f32> where: T is f32, U is i32, f16, u32 or bool
vec3(vec3<U>) -> vec3<i32> where: T is i32, U is f32, u32 or bool vec3(vec3<U>) -> vec3<f16> where: T is f16, U is f32, i32, u32 or bool
vec3(vec3<U>) -> vec3<u32> where: T is u32, U is f32, i32 or bool vec3(vec3<U>) -> vec3<i32> where: T is i32, U is f32, f16, u32 or bool
vec3(vec3<U>) -> vec3<bool> where: T is bool, U is f32, i32 or u32 vec3(vec3<U>) -> vec3<u32> where: T is u32, U is f32, f16, i32 or bool
vec3(vec3<U>) -> vec3<bool> where: T is bool, U is f32, f16, i32 or u32
)"); )");
} }
@ -733,18 +734,19 @@ TEST_F(IntrinsicTableTest, MismatchTypeConstructorExplicit) {
R"(12:34 error: no matching constructor for vec3<i32>(i32, f32, i32) R"(12:34 error: no matching constructor for vec3<i32>(i32, f32, i32)
6 candidate constructors: 6 candidate constructors:
vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(x: T, yz: vec2<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(x: T, yz: vec2<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(T) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(xy: vec2<T>, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(xy: vec2<T>, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(vec3<T>) -> vec3<T> where: T is f32, i32, u32 or bool vec3(vec3<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
vec3() -> vec3<T> where: T is f32, i32, u32 or bool vec3() -> vec3<T> where: T is f32, f16, i32, u32 or bool
4 candidate conversions: 5 candidate conversions:
vec3(vec3<U>) -> vec3<f32> where: T is f32, U is i32, u32 or bool vec3(vec3<U>) -> vec3<f32> where: T is f32, U is i32, f16, u32 or bool
vec3(vec3<U>) -> vec3<i32> where: T is i32, U is f32, u32 or bool vec3(vec3<U>) -> vec3<f16> where: T is f16, U is f32, i32, u32 or bool
vec3(vec3<U>) -> vec3<u32> where: T is u32, U is f32, i32 or bool vec3(vec3<U>) -> vec3<i32> where: T is i32, U is f32, f16, u32 or bool
vec3(vec3<U>) -> vec3<bool> where: T is bool, U is f32, i32 or u32 vec3(vec3<U>) -> vec3<u32> where: T is u32, U is f32, f16, i32 or bool
vec3(vec3<U>) -> vec3<bool> where: T is bool, U is f32, f16, i32 or u32
)"); )");
} }
@ -770,18 +772,19 @@ TEST_F(IntrinsicTableTest, MismatchTypeConversion) {
R"(12:34 error: no matching constructor for vec3<f32>(array<u32>) R"(12:34 error: no matching constructor for vec3<f32>(array<u32>)
6 candidate constructors: 6 candidate constructors:
vec3(vec3<T>) -> vec3<T> where: T is f32, i32, u32 or bool vec3(vec3<T>) -> vec3<T> where: T is f32, f16, i32, u32 or bool
vec3(T) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3() -> vec3<T> where: T is f32, i32, u32 or bool vec3() -> vec3<T> where: T is f32, f16, i32, u32 or bool
vec3(xy: vec2<T>, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(xy: vec2<T>, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(x: T, yz: vec2<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(x: T, yz: vec2<T>) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, i32, u32 or bool vec3(x: T, y: T, z: T) -> vec3<T> where: T is abstract-int, abstract-float, f32, f16, i32, u32 or bool
4 candidate conversions: 5 candidate conversions:
vec3(vec3<U>) -> vec3<f32> where: T is f32, U is i32, u32 or bool vec3(vec3<U>) -> vec3<f32> where: T is f32, U is i32, f16, u32 or bool
vec3(vec3<U>) -> vec3<i32> where: T is i32, U is f32, u32 or bool vec3(vec3<U>) -> vec3<f16> where: T is f16, U is f32, i32, u32 or bool
vec3(vec3<U>) -> vec3<u32> where: T is u32, U is f32, i32 or bool vec3(vec3<U>) -> vec3<i32> where: T is i32, U is f32, f16, u32 or bool
vec3(vec3<U>) -> vec3<bool> where: T is bool, U is f32, i32 or u32 vec3(vec3<U>) -> vec3<u32> where: T is u32, U is f32, f16, i32 or bool
vec3(vec3<U>) -> vec3<bool> where: T is bool, U is f32, f16, i32 or u32
)"); )");
} }

View File

@ -35,6 +35,7 @@ TEST_F(ResolverIsHostShareable, NumericScalar) {
EXPECT_TRUE(r()->IsHostShareable(create<sem::I32>())); EXPECT_TRUE(r()->IsHostShareable(create<sem::I32>()));
EXPECT_TRUE(r()->IsHostShareable(create<sem::U32>())); EXPECT_TRUE(r()->IsHostShareable(create<sem::U32>()));
EXPECT_TRUE(r()->IsHostShareable(create<sem::F32>())); EXPECT_TRUE(r()->IsHostShareable(create<sem::F32>()));
EXPECT_TRUE(r()->IsHostShareable(create<sem::F16>()));
} }
TEST_F(ResolverIsHostShareable, NumericVector) { TEST_F(ResolverIsHostShareable, NumericVector) {
@ -47,6 +48,9 @@ TEST_F(ResolverIsHostShareable, NumericVector) {
EXPECT_TRUE(r()->IsHostShareable(create<sem::Vector>(create<sem::F32>(), 2u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Vector>(create<sem::F32>(), 2u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Vector>(create<sem::F32>(), 3u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Vector>(create<sem::F32>(), 3u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Vector>(create<sem::F32>(), 4u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Vector>(create<sem::F32>(), 4u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Vector>(create<sem::F16>(), 2u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Vector>(create<sem::F16>(), 3u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Vector>(create<sem::F16>(), 4u)));
} }
TEST_F(ResolverIsHostShareable, BoolVector) { TEST_F(ResolverIsHostShareable, BoolVector) {
@ -62,19 +66,32 @@ TEST_F(ResolverIsHostShareable, BoolVector) {
} }
TEST_F(ResolverIsHostShareable, Matrix) { TEST_F(ResolverIsHostShareable, Matrix) {
auto* vec2 = create<sem::Vector>(create<sem::F32>(), 2u); auto* vec2_f32 = create<sem::Vector>(create<sem::F32>(), 2u);
auto* vec3 = create<sem::Vector>(create<sem::F32>(), 3u); auto* vec3_f32 = create<sem::Vector>(create<sem::F32>(), 3u);
auto* vec4 = create<sem::Vector>(create<sem::F32>(), 4u); auto* vec4_f32 = create<sem::Vector>(create<sem::F32>(), 4u);
auto* vec2_f16 = create<sem::Vector>(create<sem::F16>(), 2u);
auto* vec3_f16 = create<sem::Vector>(create<sem::F16>(), 3u);
auto* vec4_f16 = create<sem::Vector>(create<sem::F16>(), 4u);
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec2, 2u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec2_f32, 2u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec2, 3u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec2_f32, 3u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec2, 4u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec2_f32, 4u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec3, 2u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec3_f32, 2u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec3, 3u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec3_f32, 3u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec3, 4u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec3_f32, 4u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec4, 2u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec4_f32, 2u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec4, 3u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec4_f32, 3u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec4, 4u))); EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec4_f32, 4u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec2_f16, 2u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec2_f16, 3u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec2_f16, 4u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec3_f16, 2u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec3_f16, 3u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec3_f16, 4u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec4_f16, 2u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec4_f16, 3u)));
EXPECT_TRUE(r()->IsHostShareable(create<sem::Matrix>(vec4_f16, 4u)));
} }
TEST_F(ResolverIsHostShareable, Pointer) { TEST_F(ResolverIsHostShareable, Pointer) {

View File

@ -32,6 +32,7 @@ TEST_F(ResolverIsStorableTest, Scalar) {
EXPECT_TRUE(r()->IsStorable(create<sem::I32>())); EXPECT_TRUE(r()->IsStorable(create<sem::I32>()));
EXPECT_TRUE(r()->IsStorable(create<sem::U32>())); EXPECT_TRUE(r()->IsStorable(create<sem::U32>()));
EXPECT_TRUE(r()->IsStorable(create<sem::F32>())); EXPECT_TRUE(r()->IsStorable(create<sem::F32>()));
EXPECT_TRUE(r()->IsStorable(create<sem::F16>()));
} }
TEST_F(ResolverIsStorableTest, Vector) { TEST_F(ResolverIsStorableTest, Vector) {
@ -44,21 +45,36 @@ TEST_F(ResolverIsStorableTest, Vector) {
EXPECT_TRUE(r()->IsStorable(create<sem::Vector>(create<sem::F32>(), 2u))); EXPECT_TRUE(r()->IsStorable(create<sem::Vector>(create<sem::F32>(), 2u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Vector>(create<sem::F32>(), 3u))); EXPECT_TRUE(r()->IsStorable(create<sem::Vector>(create<sem::F32>(), 3u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Vector>(create<sem::F32>(), 4u))); EXPECT_TRUE(r()->IsStorable(create<sem::Vector>(create<sem::F32>(), 4u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Vector>(create<sem::F16>(), 2u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Vector>(create<sem::F16>(), 3u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Vector>(create<sem::F16>(), 4u)));
} }
TEST_F(ResolverIsStorableTest, Matrix) { TEST_F(ResolverIsStorableTest, Matrix) {
auto* vec2 = create<sem::Vector>(create<sem::F32>(), 2u); auto* vec2_f32 = create<sem::Vector>(create<sem::F32>(), 2u);
auto* vec3 = create<sem::Vector>(create<sem::F32>(), 3u); auto* vec3_f32 = create<sem::Vector>(create<sem::F32>(), 3u);
auto* vec4 = create<sem::Vector>(create<sem::F32>(), 4u); auto* vec4_f32 = create<sem::Vector>(create<sem::F32>(), 4u);
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec2, 2u))); auto* vec2_f16 = create<sem::Vector>(create<sem::F16>(), 2u);
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec2, 3u))); auto* vec3_f16 = create<sem::Vector>(create<sem::F16>(), 3u);
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec2, 4u))); auto* vec4_f16 = create<sem::Vector>(create<sem::F16>(), 4u);
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec3, 2u))); EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec2_f32, 2u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec3, 3u))); EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec2_f32, 3u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec3, 4u))); EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec2_f32, 4u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec4, 2u))); EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec3_f32, 2u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec4, 3u))); EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec3_f32, 3u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec4, 4u))); EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec3_f32, 4u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec4_f32, 2u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec4_f32, 3u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec4_f32, 4u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec2_f16, 2u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec2_f16, 3u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec2_f16, 4u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec3_f16, 2u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec3_f16, 3u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec3_f16, 4u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec4_f16, 2u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec4_f16, 3u)));
EXPECT_TRUE(r()->IsStorable(create<sem::Matrix>(vec4_f16, 4u)));
} }
TEST_F(ResolverIsStorableTest, Pointer) { TEST_F(ResolverIsStorableTest, Pointer) {

View File

@ -41,11 +41,16 @@ constexpr double kHighestI32 = static_cast<double>(i32::kHighest);
constexpr double kLowestI32 = static_cast<double>(i32::kLowest); constexpr double kLowestI32 = static_cast<double>(i32::kLowest);
constexpr double kHighestF32 = static_cast<double>(f32::kHighest); constexpr double kHighestF32 = static_cast<double>(f32::kHighest);
constexpr double kLowestF32 = static_cast<double>(f32::kLowest); constexpr double kLowestF32 = static_cast<double>(f32::kLowest);
// constexpr double kHighestF16 = static_cast<double>(f16::kHighest);
// constexpr double kLowestF16 = static_cast<double>(f16::kLowest);
constexpr double kTooBigF32 = static_cast<double>(3.5e+38); constexpr double kTooBigF32 = static_cast<double>(3.5e+38);
// constexpr double kTooBigF16 = static_cast<double>(6.6e+4);
constexpr double kPiF64 = 3.141592653589793; constexpr double kPiF64 = 3.141592653589793;
constexpr double kPiF32 = 3.1415927410125732; // kPiF64 quantized to f32 constexpr double kPiF32 = 3.1415927410125732; // kPiF64 quantized to f32
// constexpr double kPiF16 = 3.140625; // kPiF64 quantized to f16
constexpr double kSubnormalF32 = 0x1.0p-128; constexpr double kSubnormalF32 = 0x1.0p-128;
// constexpr double kSubnormalF16 = 0x1.0p-16;
enum class Expectation { enum class Expectation {
kMaterialize, kMaterialize,
@ -245,7 +250,7 @@ using MaterializeAbstractNumericToConcreteType =
resolver::ResolverTestWithParam<std::tuple<Expectation, Method, Data>>; resolver::ResolverTestWithParam<std::tuple<Expectation, Method, Data>>;
TEST_P(MaterializeAbstractNumericToConcreteType, Test) { TEST_P(MaterializeAbstractNumericToConcreteType, Test) {
// Once F16 is properly supported, we'll need to enable this: // Once built-in and ops using f16 is properly supported, we'll need to enable this:
// Enable(ast::Extension::kF16); // Enable(ast::Extension::kF16);
const auto& param = GetParam(); const auto& param = GetParam();
@ -418,23 +423,28 @@ INSTANTIATE_TEST_SUITE_P(
testing::Combine(testing::Values(Expectation::kMaterialize), testing::Combine(testing::Values(Expectation::kMaterialize),
testing::ValuesIn(kScalarMethods), testing::ValuesIn(kScalarMethods),
testing::ValuesIn(std::vector<Data>{ testing::ValuesIn(std::vector<Data>{
Types<i32, AInt>(0_a, 0.0), // Types<i32, AInt>(0_a, 0.0), //
Types<i32, AInt>(1_a, 1.0), // Types<i32, AInt>(1_a, 1.0), //
Types<i32, AInt>(-1_a, -1.0), // Types<i32, AInt>(-1_a, -1.0), //
Types<i32, AInt>(AInt(kHighestI32), kHighestI32), // Types<i32, AInt>(AInt(kHighestI32), kHighestI32), //
Types<i32, AInt>(AInt(kLowestI32), kLowestI32), // Types<i32, AInt>(AInt(kLowestI32), kLowestI32), //
Types<u32, AInt>(0_a, 0.0), // Types<u32, AInt>(0_a, 0.0), //
Types<u32, AInt>(1_a, 1.0), // Types<u32, AInt>(1_a, 1.0), //
Types<u32, AInt>(AInt(kHighestU32), kHighestU32), // Types<u32, AInt>(AInt(kHighestU32), kHighestU32), //
Types<u32, AInt>(AInt(kLowestU32), kLowestU32), // Types<u32, AInt>(AInt(kLowestU32), kLowestU32), //
Types<f32, AFloat>(0.0_a, 0.0), // Types<f32, AFloat>(0.0_a, 0.0), //
Types<f32, AFloat>(AFloat(kHighestF32), kHighestF32), // Types<f32, AFloat>(AFloat(kHighestF32), kHighestF32), //
Types<f32, AFloat>(AFloat(kLowestF32), kLowestF32), // Types<f32, AFloat>(AFloat(kLowestF32), kLowestF32), //
Types<f32, AFloat>(AFloat(kPiF32), kPiF64), // Types<f32, AFloat>(AFloat(kPiF32), kPiF64), //
Types<f32, AFloat>(AFloat(kSubnormalF32), kSubnormalF32), // Types<f32, AFloat>(AFloat(kSubnormalF32), kSubnormalF32), //
Types<f32, AFloat>(AFloat(-kSubnormalF32), -kSubnormalF32), // Types<f32, AFloat>(AFloat(-kSubnormalF32), -kSubnormalF32), //
/* Types<f16, AFloat>(1.0_a), */ // /* Types<f16, AFloat>(0.0_a, 0.0), */ //
/* Types<f16, AFloat>(1.0_a), */ // /* Types<f16, AFloat>(1.0_a, 1.0), */ //
/* Types<f16, AFloat>(AFloat(kHighestF16), kHighestF16), */ //
/* Types<f16, AFloat>(AFloat(kLowestF16), kLowestF16), */ //
/* Types<f16, AFloat>(AFloat(kPiF16), kPiF64), */ //
/* Types<f16, AFloat>(AFloat(kSubnormalF16), kSubnormalF16), */ //
/* Types<f16, AFloat>(AFloat(-kSubnormalF16), -kSubnormalF16), */ //
}))); })));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
@ -443,25 +453,31 @@ INSTANTIATE_TEST_SUITE_P(
testing::Combine(testing::Values(Expectation::kMaterialize), testing::Combine(testing::Values(Expectation::kMaterialize),
testing::ValuesIn(kVectorMethods), testing::ValuesIn(kVectorMethods),
testing::ValuesIn(std::vector<Data>{ testing::ValuesIn(std::vector<Data>{
Types<i32V, AIntV>(0_a, 0.0), // Types<i32V, AIntV>(0_a, 0.0), //
Types<i32V, AIntV>(1_a, 1.0), // Types<i32V, AIntV>(1_a, 1.0), //
Types<i32V, AIntV>(-1_a, -1.0), // Types<i32V, AIntV>(-1_a, -1.0), //
Types<i32V, AIntV>(AInt(kHighestI32), kHighestI32), // Types<i32V, AIntV>(AInt(kHighestI32), kHighestI32), //
Types<i32V, AIntV>(AInt(kLowestI32), kLowestI32), // Types<i32V, AIntV>(AInt(kLowestI32), kLowestI32), //
Types<u32V, AIntV>(0_a, 0.0), // Types<u32V, AIntV>(0_a, 0.0), //
Types<u32V, AIntV>(1_a, 1.0), // Types<u32V, AIntV>(1_a, 1.0), //
Types<u32V, AIntV>(AInt(kHighestU32), kHighestU32), // Types<u32V, AIntV>(AInt(kHighestU32), kHighestU32), //
Types<u32V, AIntV>(AInt(kLowestU32), kLowestU32), // Types<u32V, AIntV>(AInt(kLowestU32), kLowestU32), //
Types<f32V, AFloatV>(0.0_a, 0.0), // Types<f32V, AFloatV>(0.0_a, 0.0), //
Types<f32V, AFloatV>(1.0_a, 1.0), // Types<f32V, AFloatV>(1.0_a, 1.0), //
Types<f32V, AFloatV>(-1.0_a, -1.0), // Types<f32V, AFloatV>(-1.0_a, -1.0), //
Types<f32V, AFloatV>(AFloat(kHighestF32), kHighestF32), // Types<f32V, AFloatV>(AFloat(kHighestF32), kHighestF32), //
Types<f32V, AFloatV>(AFloat(kLowestF32), kLowestF32), // Types<f32V, AFloatV>(AFloat(kLowestF32), kLowestF32), //
Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), // Types<f32V, AFloatV>(AFloat(kPiF32), kPiF64), //
Types<f32V, AFloatV>(AFloat(kSubnormalF32), kSubnormalF32), // Types<f32V, AFloatV>(AFloat(kSubnormalF32), kSubnormalF32), //
Types<f32V, AFloatV>(AFloat(-kSubnormalF32), -kSubnormalF32), // Types<f32V, AFloatV>(AFloat(-kSubnormalF32), -kSubnormalF32), //
/* Types<f16V, AFloatV>(1.0_a), */ // /* Types<f16V, AFloatV>(0.0_a, 0.0), */ //
/* Types<f16V, AFloatV>(1.0_a), */ // /* Types<f16V, AFloatV>(1.0_a, 1.0), */ //
/* Types<f16V, AFloatV>(-1.0_a, -1.0), */ //
/* Types<f16V, AFloatV>(AFloat(kHighestF16), kHighestF16), */ //
/* Types<f16V, AFloatV>(AFloat(kLowestF16), kLowestF16), */ //
/* Types<f16V, AFloatV>(AFloat(kPiF16), kPiF64), */ //
/* Types<f16V, AFloatV>(AFloat(kSubnormalF16), kSubnormalF16), */ //
/* Types<f16V, AFloatV>(AFloat(-kSubnormalF16), -kSubnormalF16), */ //
}))); })));
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
@ -470,15 +486,22 @@ INSTANTIATE_TEST_SUITE_P(
testing::Combine(testing::Values(Expectation::kMaterialize), testing::Combine(testing::Values(Expectation::kMaterialize),
testing::ValuesIn(kMatrixMethods), testing::ValuesIn(kMatrixMethods),
testing::ValuesIn(std::vector<Data>{ testing::ValuesIn(std::vector<Data>{
Types<f32M, AFloatM>(0.0_a, 0.0), // Types<f32M, AFloatM>(0.0_a, 0.0), //
Types<f32M, AFloatM>(1.0_a, 1.0), // Types<f32M, AFloatM>(1.0_a, 1.0), //
Types<f32M, AFloatM>(-1.0_a, -1.0), // Types<f32M, AFloatM>(-1.0_a, -1.0), //
Types<f32M, AFloatM>(AFloat(kHighestF32), kHighestF32), // Types<f32M, AFloatM>(AFloat(kHighestF32), kHighestF32), //
Types<f32M, AFloatM>(AFloat(kLowestF32), kLowestF32), // Types<f32M, AFloatM>(AFloat(kLowestF32), kLowestF32), //
Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), // Types<f32M, AFloatM>(AFloat(kPiF32), kPiF64), //
Types<f32M, AFloatM>(AFloat(kSubnormalF32), kSubnormalF32), // Types<f32M, AFloatM>(AFloat(kSubnormalF32), kSubnormalF32), //
Types<f32M, AFloatM>(AFloat(-kSubnormalF32), -kSubnormalF32), // Types<f32M, AFloatM>(AFloat(-kSubnormalF32), -kSubnormalF32), //
/* Types<f16V, AFloatM>(1.0_a), */ // /* Types<f16M, AFloatM>(0.0_a, 0.0), */ //
/* Types<f16M, AFloatM>(1.0_a, 1.0), */ //
/* Types<f16M, AFloatM>(-1.0_a, -1.0), */ //
/* Types<f16M, AFloatM>(AFloat(kHighestF16), kHighestF16), */ //
/* Types<f16M, AFloatM>(AFloat(kLowestF16), kLowestF16), */ //
/* Types<f16M, AFloatM>(AFloat(kPiF16), kPiF64), */ //
/* Types<f16M, AFloatM>(AFloat(kSubnormalF16), kSubnormalF16), */ //
/* Types<f16M, AFloatM>(AFloat(-kSubnormalF16), -kSubnormalF16), */ //
}))); })));
INSTANTIATE_TEST_SUITE_P(MaterializeSwitch, INSTANTIATE_TEST_SUITE_P(MaterializeSwitch,
@ -542,14 +565,14 @@ INSTANTIATE_TEST_SUITE_P(ScalarValueCannotBeRepresented,
testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented), testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
testing::ValuesIn(kScalarMethods), testing::ValuesIn(kScalarMethods),
testing::ValuesIn(std::vector<Data>{ testing::ValuesIn(std::vector<Data>{
Types<i32, AInt>(0_a, kHighestI32 + 1), // Types<i32, AInt>(0_a, kHighestI32 + 1), //
Types<i32, AInt>(0_a, kLowestI32 - 1), // Types<i32, AInt>(0_a, kLowestI32 - 1), //
Types<u32, AInt>(0_a, kHighestU32 + 1), // Types<u32, AInt>(0_a, kHighestU32 + 1), //
Types<u32, AInt>(0_a, kLowestU32 - 1), // Types<u32, AInt>(0_a, kLowestU32 - 1), //
Types<f32, AFloat>(0.0_a, kTooBigF32), // Types<f32, AFloat>(0.0_a, kTooBigF32), //
Types<f32, AFloat>(0.0_a, -kTooBigF32), // Types<f32, AFloat>(0.0_a, -kTooBigF32), //
/* Types<f16, AFloat>(), */ // /* Types<f16, AFloat>(0.0_a, kTooBigF16), */ //
/* Types<f16, AFloat>(), */ // /* Types<f16, AFloat>(0.0_a, -kTooBigF16), */ //
}))); })));
INSTANTIATE_TEST_SUITE_P(VectorValueCannotBeRepresented, INSTANTIATE_TEST_SUITE_P(VectorValueCannotBeRepresented,
@ -557,14 +580,14 @@ INSTANTIATE_TEST_SUITE_P(VectorValueCannotBeRepresented,
testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented), testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
testing::ValuesIn(kVectorMethods), testing::ValuesIn(kVectorMethods),
testing::ValuesIn(std::vector<Data>{ testing::ValuesIn(std::vector<Data>{
Types<i32V, AIntV>(0_a, kHighestI32 + 1), // Types<i32V, AIntV>(0_a, kHighestI32 + 1), //
Types<i32V, AIntV>(0_a, kLowestI32 - 1), // Types<i32V, AIntV>(0_a, kLowestI32 - 1), //
Types<u32V, AIntV>(0_a, kHighestU32 + 1), // Types<u32V, AIntV>(0_a, kHighestU32 + 1), //
Types<u32V, AIntV>(0_a, kLowestU32 - 1), // Types<u32V, AIntV>(0_a, kLowestU32 - 1), //
Types<f32V, AFloatV>(0.0_a, kTooBigF32), // Types<f32V, AFloatV>(0.0_a, kTooBigF32), //
Types<f32V, AFloatV>(0.0_a, -kTooBigF32), // Types<f32V, AFloatV>(0.0_a, -kTooBigF32), //
/* Types<f16V, AFloatV>(), */ // /* Types<f16V, AFloatV>(0.0_a, kTooBigF16), */ //
/* Types<f16V, AFloatV>(), */ // /* Types<f16V, AFloatV>(0.0_a, -kTooBigF16), */ //
}))); })));
INSTANTIATE_TEST_SUITE_P(MatrixValueCannotBeRepresented, INSTANTIATE_TEST_SUITE_P(MatrixValueCannotBeRepresented,
@ -572,10 +595,10 @@ INSTANTIATE_TEST_SUITE_P(MatrixValueCannotBeRepresented,
testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented), testing::Combine(testing::Values(Expectation::kValueCannotBeRepresented),
testing::ValuesIn(kMatrixMethods), testing::ValuesIn(kMatrixMethods),
testing::ValuesIn(std::vector<Data>{ testing::ValuesIn(std::vector<Data>{
Types<f32M, AFloatM>(0.0_a, kTooBigF32), // Types<f32M, AFloatM>(0.0_a, kTooBigF32), //
Types<f32M, AFloatM>(0.0_a, -kTooBigF32), // Types<f32M, AFloatM>(0.0_a, -kTooBigF32), //
/* Types<f16M, AFloatM>(), */ // /* Types<f16M, AFloatM>(0.0_a, kTooBigF16), */ //
/* Types<f16M, AFloatM>(), */ // /* Types<f16M, AFloatM>(0.0_a, -kTooBigF16), */ //
}))); })));
} // namespace materialize_abstract_numeric_to_concrete_type } // namespace materialize_abstract_numeric_to_concrete_type
@ -683,9 +706,6 @@ using MaterializeAbstractNumericToDefaultType =
resolver::ResolverTestWithParam<std::tuple<Expectation, Method, Data>>; resolver::ResolverTestWithParam<std::tuple<Expectation, Method, Data>>;
TEST_P(MaterializeAbstractNumericToDefaultType, Test) { TEST_P(MaterializeAbstractNumericToDefaultType, Test) {
// Once F16 is properly supported, we'll need to enable this:
// Enable(ast::Extension::kF16);
const auto& param = GetParam(); const auto& param = GetParam();
const auto& expectation = std::get<0>(param); const auto& expectation = std::get<0>(param);
const auto& method = std::get<1>(param); const auto& method = std::get<1>(param);

View File

@ -1506,6 +1506,7 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
}, },
[&](const sem::I32*) { return ct_ctor_or_conv(CtorConvIntrinsic::kI32, nullptr); }, [&](const sem::I32*) { return ct_ctor_or_conv(CtorConvIntrinsic::kI32, nullptr); },
[&](const sem::U32*) { return ct_ctor_or_conv(CtorConvIntrinsic::kU32, nullptr); }, [&](const sem::U32*) { return ct_ctor_or_conv(CtorConvIntrinsic::kU32, nullptr); },
[&](const sem::F16*) { return ct_ctor_or_conv(CtorConvIntrinsic::kF16, nullptr); },
[&](const sem::F32*) { return ct_ctor_or_conv(CtorConvIntrinsic::kF32, nullptr); }, [&](const sem::F32*) { return ct_ctor_or_conv(CtorConvIntrinsic::kF32, nullptr); },
[&](const sem::Bool*) { return ct_ctor_or_conv(CtorConvIntrinsic::kBool, nullptr); }, [&](const sem::Bool*) { return ct_ctor_or_conv(CtorConvIntrinsic::kBool, nullptr); },
[&](const sem::Array* arr) -> sem::Call* { [&](const sem::Array* arr) -> sem::Call* {

View File

@ -75,6 +75,23 @@ TEST_F(ResolverConstantsTest, Scalar_f32) {
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(0).value, 9.9f); EXPECT_EQ(sem->ConstantValue().Element<AFloat>(0).value, 9.9f);
} }
TEST_F(ResolverConstantsTest, Scalar_f16) {
Enable(ast::Extension::kF16);
auto* expr = Expr(9.9_h);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr);
EXPECT_TRUE(sem->Type()->Is<sem::F16>());
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_EQ(sem->ConstantValue().ElementType(), sem->Type());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 1u);
// 9.9 is not exactly representable by f16, and should be quantized to 9.8984375
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(0).value, 9.8984375f);
}
TEST_F(ResolverConstantsTest, Scalar_bool) { TEST_F(ResolverConstantsTest, Scalar_bool) {
auto* expr = Expr(true); auto* expr = Expr(true);
WrapInFunction(expr); WrapInFunction(expr);
@ -150,6 +167,27 @@ TEST_F(ResolverConstantsTest, Vec3_ZeroInit_f32) {
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 0.0); EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 0.0);
} }
TEST_F(ResolverConstantsTest, Vec3_ZeroInit_f16) {
Enable(ast::Extension::kF16);
auto* expr = vec3<f16>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F16>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(0).value, 0.0);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(1).value, 0.0);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 0.0);
}
TEST_F(ResolverConstantsTest, Vec3_ZeroInit_bool) { TEST_F(ResolverConstantsTest, Vec3_ZeroInit_bool) {
auto* expr = vec3<bool>(); auto* expr = vec3<bool>();
WrapInFunction(expr); WrapInFunction(expr);
@ -230,6 +268,28 @@ TEST_F(ResolverConstantsTest, Vec3_Splat_f32) {
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 9.9f); EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 9.9f);
} }
TEST_F(ResolverConstantsTest, Vec3_Splat_f16) {
Enable(ast::Extension::kF16);
auto* expr = vec3<f16>(9.9_h);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F16>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 3u);
// 9.9 is not exactly representable by f16, and should be quantized to 9.8984375
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(0).value, 9.8984375f);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(1).value, 9.8984375f);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 9.8984375f);
}
TEST_F(ResolverConstantsTest, Vec3_Splat_bool) { TEST_F(ResolverConstantsTest, Vec3_Splat_bool) {
auto* expr = vec3<bool>(true); auto* expr = vec3<bool>(true);
WrapInFunction(expr); WrapInFunction(expr);
@ -310,6 +370,27 @@ TEST_F(ResolverConstantsTest, Vec3_FullConstruct_f32) {
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 3.f); EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 3.f);
} }
TEST_F(ResolverConstantsTest, Vec3_FullConstruct_f16) {
Enable(ast::Extension::kF16);
auto* expr = vec3<f16>(1_h, 2_h, 3_h);
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F16>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(0).value, 1.f);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(1).value, 2.f);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 3.f);
}
TEST_F(ResolverConstantsTest, Vec3_FullConstruct_bool) { TEST_F(ResolverConstantsTest, Vec3_FullConstruct_bool) {
auto* expr = vec3<bool>(true, false, true); auto* expr = vec3<bool>(true, false, true);
WrapInFunction(expr); WrapInFunction(expr);
@ -390,6 +471,27 @@ TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f32) {
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 3.f); EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 3.f);
} }
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_f16) {
Enable(ast::Extension::kF16);
auto* expr = vec3<f16>(1_h, vec2<f16>(2_h, 3_h));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F16>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(0).value, 1.f);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(1).value, 2.f);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 3.f);
}
TEST_F(ResolverConstantsTest, Vec3_MixConstruct_bool) { TEST_F(ResolverConstantsTest, Vec3_MixConstruct_bool) {
auto* expr = vec3<bool>(vec2<bool>(true, false), true); auto* expr = vec3<bool>(vec2<bool>(true, false), true);
WrapInFunction(expr); WrapInFunction(expr);
@ -450,6 +552,48 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_u32_to_f32) {
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 30.f); EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 30.f);
} }
TEST_F(ResolverConstantsTest, Vec3_Convert_f16_to_i32) {
Enable(ast::Extension::kF16);
auto* expr = vec3<i32>(vec3<f16>(1.1_h, 2.2_h, 3.3_h));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::I32>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(sem->ConstantValue().Element<AInt>(0).value, 1);
EXPECT_EQ(sem->ConstantValue().Element<AInt>(1).value, 2);
EXPECT_EQ(sem->ConstantValue().Element<AInt>(2).value, 3);
}
TEST_F(ResolverConstantsTest, Vec3_Convert_u32_to_f16) {
Enable(ast::Extension::kF16);
auto* expr = vec3<f16>(vec3<u32>(10_u, 20_u, 30_u));
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr);
auto* vec = sem->Type()->As<sem::Vector>();
ASSERT_NE(vec, nullptr);
EXPECT_TRUE(vec->type()->Is<sem::F16>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F16>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 3u);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(0).value, 10.f);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(1).value, 20.f);
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, 30.f);
}
TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_i32) { TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_i32) {
auto* expr = vec3<i32>(vec3<f32>(1e10_f, -1e20_f, 1e30_f)); auto* expr = vec3<i32>(vec3<f32>(1e10_f, -1e20_f, 1e30_f));
WrapInFunction(expr); WrapInFunction(expr);
@ -490,11 +634,10 @@ TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_u32) {
EXPECT_EQ(sem->ConstantValue().Element<AInt>(2).value, u32::kHighest); EXPECT_EQ(sem->ConstantValue().Element<AInt>(2).value, u32::kHighest);
} }
// TODO(crbug.com/tint/1502): Enable when f16 overloads are implemented TEST_F(ResolverConstantsTest, Vec3_Convert_Large_f32_to_f16) {
TEST_F(ResolverConstantsTest, DISABLED_Vec3_Convert_Large_f32_to_f16) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
auto* expr = vec3<f16>(vec3<f32>(0.00001_f, -0.00002_f, 0.00003_f)); auto* expr = vec3<f16>(vec3<f32>(1e10_f, -1e20_f, 1e30_f));
WrapInFunction(expr); WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -515,11 +658,10 @@ TEST_F(ResolverConstantsTest, DISABLED_Vec3_Convert_Large_f32_to_f16) {
EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, kInf); EXPECT_EQ(sem->ConstantValue().Element<AFloat>(2).value, kInf);
} }
// TODO(crbug.com/tint/1502): Enable when f16 overloads are implemented TEST_F(ResolverConstantsTest, Vec3_Convert_Small_f32_to_f16) {
TEST_F(ResolverConstantsTest, DISABLED_Vec3_Convert_Small_f32_to_f16) {
Enable(ast::Extension::kF16); Enable(ast::Extension::kF16);
auto* expr = vec3<f16>(vec3<f32>(1e-10_f, -1e20_f, 1e30_f)); auto* expr = vec3<f16>(vec3<f32>(1e-20_f, -2e-30_f, 3e-40_f));
WrapInFunction(expr); WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -562,6 +704,32 @@ TEST_F(ResolverConstantsTest, Mat2x3_ZeroInit_f32) {
EXPECT_EQ(sem->ConstantValue().Element<f32>(5).value, 0._f); EXPECT_EQ(sem->ConstantValue().Element<f32>(5).value, 0._f);
} }
TEST_F(ResolverConstantsTest, Mat2x3_ZeroInit_f16) {
Enable(ast::Extension::kF16);
auto* expr = mat2x3<f16>();
WrapInFunction(expr);
EXPECT_TRUE(r()->Resolve()) << r()->error();
auto* sem = Sem().Get(expr);
EXPECT_NE(sem, nullptr);
auto* mat = sem->Type()->As<sem::Matrix>();
ASSERT_NE(mat, nullptr);
EXPECT_TRUE(mat->type()->Is<sem::F16>());
EXPECT_EQ(mat->columns(), 2u);
EXPECT_EQ(mat->rows(), 3u);
EXPECT_EQ(sem->ConstantValue().Type(), sem->Type());
EXPECT_TRUE(sem->ConstantValue().ElementType()->Is<sem::F16>());
ASSERT_EQ(sem->ConstantValue().ElementCount(), 6u);
EXPECT_EQ(sem->ConstantValue().Element<f16>(0).value, 0._h);
EXPECT_EQ(sem->ConstantValue().Element<f16>(1).value, 0._h);
EXPECT_EQ(sem->ConstantValue().Element<f16>(2).value, 0._h);
EXPECT_EQ(sem->ConstantValue().Element<f16>(3).value, 0._h);
EXPECT_EQ(sem->ConstantValue().Element<f16>(4).value, 0._h);
EXPECT_EQ(sem->ConstantValue().Element<f16>(5).value, 0._h);
}
TEST_F(ResolverConstantsTest, Mat3x2_Construct_Scalars_af) { TEST_F(ResolverConstantsTest, Mat3x2_Construct_Scalars_af) {
auto* expr = Construct(ty.mat(nullptr, 3, 2), 1.0_a, 2.0_a, 3.0_a, 4.0_a, 5.0_a, 6.0_a); auto* expr = Construct(ty.mat(nullptr, 3, 2), 1.0_a, 2.0_a, 3.0_a, 4.0_a, 5.0_a, 6.0_a);
WrapInFunction(expr); WrapInFunction(expr);

View File

@ -54,6 +54,57 @@ TEST_F(ResolverStructLayoutTest, Scalars) {
} }
} }
TEST_F(ResolverStructLayoutTest, ScalarsWithF16) {
Enable(ast::Extension::kF16);
auto* s = Structure("S", {
Member("a", ty.f32()),
Member("b", ty.f16()),
Member("c", ty.u32()),
Member("d", ty.f16()),
Member("e", ty.f16()),
Member("f", ty.i32()),
Member("g", ty.f16()),
});
ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->Size(), 24u);
EXPECT_EQ(sem->SizeNoPadding(), 22u);
EXPECT_EQ(sem->Align(), 4u);
ASSERT_EQ(sem->Members().size(), 7u);
// f32
EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
EXPECT_EQ(sem->Members()[0]->Align(), 4u);
EXPECT_EQ(sem->Members()[0]->Size(), 4u);
// f16
EXPECT_EQ(sem->Members()[1]->Offset(), 4u);
EXPECT_EQ(sem->Members()[1]->Align(), 2u);
EXPECT_EQ(sem->Members()[1]->Size(), 2u);
// u32
EXPECT_EQ(sem->Members()[2]->Offset(), 8u);
EXPECT_EQ(sem->Members()[2]->Align(), 4u);
EXPECT_EQ(sem->Members()[2]->Size(), 4u);
// f16
EXPECT_EQ(sem->Members()[3]->Offset(), 12u);
EXPECT_EQ(sem->Members()[3]->Align(), 2u);
EXPECT_EQ(sem->Members()[3]->Size(), 2u);
// f16
EXPECT_EQ(sem->Members()[4]->Offset(), 14u);
EXPECT_EQ(sem->Members()[4]->Align(), 2u);
EXPECT_EQ(sem->Members()[4]->Size(), 2u);
// i32
EXPECT_EQ(sem->Members()[5]->Offset(), 16u);
EXPECT_EQ(sem->Members()[5]->Align(), 4u);
EXPECT_EQ(sem->Members()[5]->Size(), 4u);
// f16
EXPECT_EQ(sem->Members()[6]->Offset(), 20u);
EXPECT_EQ(sem->Members()[6]->Align(), 2u);
EXPECT_EQ(sem->Members()[6]->Size(), 2u);
}
TEST_F(ResolverStructLayoutTest, Alias) { TEST_F(ResolverStructLayoutTest, Alias) {
auto* alias_a = Alias("a", ty.f32()); auto* alias_a = Alias("a", ty.f32());
auto* alias_b = Alias("b", ty.f32()); auto* alias_b = Alias("b", ty.f32());
@ -83,58 +134,80 @@ TEST_F(ResolverStructLayoutTest, Alias) {
} }
TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayStaticSize) { TEST_F(ResolverStructLayoutTest, ImplicitStrideArrayStaticSize) {
Enable(ast::Extension::kF16);
auto* s = Structure("S", { auto* s = Structure("S", {
Member("a", ty.array<i32, 3>()), Member("a", ty.array<i32, 3>()),
Member("b", ty.array<f32, 5>()), Member("b", ty.array<f32, 5>()),
Member("c", ty.array<f32, 1>()), Member("c", ty.array<f16, 7>()),
Member("d", ty.array<f32, 1>()),
}); });
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->Size(), 36u); EXPECT_EQ(sem->Size(), 52u);
EXPECT_EQ(sem->SizeNoPadding(), 36u); EXPECT_EQ(sem->SizeNoPadding(), 52u);
EXPECT_EQ(sem->Align(), 4u); EXPECT_EQ(sem->Align(), 4u);
ASSERT_EQ(sem->Members().size(), 3u); ASSERT_EQ(sem->Members().size(), 4u);
// array<i32, 3>
EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Align(), 4u);
EXPECT_EQ(sem->Members()[0]->Size(), 12u); EXPECT_EQ(sem->Members()[0]->Size(), 12u);
// array<f32, 5>
EXPECT_EQ(sem->Members()[1]->Offset(), 12u); EXPECT_EQ(sem->Members()[1]->Offset(), 12u);
EXPECT_EQ(sem->Members()[1]->Align(), 4u); EXPECT_EQ(sem->Members()[1]->Align(), 4u);
EXPECT_EQ(sem->Members()[1]->Size(), 20u); EXPECT_EQ(sem->Members()[1]->Size(), 20u);
// array<f16, 7>
EXPECT_EQ(sem->Members()[2]->Offset(), 32u); EXPECT_EQ(sem->Members()[2]->Offset(), 32u);
EXPECT_EQ(sem->Members()[2]->Align(), 4u); EXPECT_EQ(sem->Members()[2]->Align(), 2u);
EXPECT_EQ(sem->Members()[2]->Size(), 4u); EXPECT_EQ(sem->Members()[2]->Size(), 14u);
// array<f32, 1>
EXPECT_EQ(sem->Members()[3]->Offset(), 48u);
EXPECT_EQ(sem->Members()[3]->Align(), 4u);
EXPECT_EQ(sem->Members()[3]->Size(), 4u);
for (auto& m : sem->Members()) { for (auto& m : sem->Members()) {
EXPECT_EQ(m->Struct()->Declaration(), s); EXPECT_EQ(m->Struct()->Declaration(), s);
} }
} }
TEST_F(ResolverStructLayoutTest, ExplicitStrideArrayStaticSize) { TEST_F(ResolverStructLayoutTest, ExplicitStrideArrayStaticSize) {
Enable(ast::Extension::kF16);
auto* s = Structure("S", { auto* s = Structure("S", {
Member("a", ty.array<i32, 3>(/*stride*/ 8)), Member("a", ty.array<i32, 3>(/*stride*/ 8)),
Member("b", ty.array<f32, 5>(/*stride*/ 16)), Member("b", ty.array<f32, 5>(/*stride*/ 16)),
Member("c", ty.array<f32, 1>(/*stride*/ 32)), Member("c", ty.array<f16, 7>(/*stride*/ 4)),
Member("d", ty.array<f32, 1>(/*stride*/ 32)),
}); });
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->Size(), 136u); EXPECT_EQ(sem->Size(), 164u);
EXPECT_EQ(sem->SizeNoPadding(), 136u); EXPECT_EQ(sem->SizeNoPadding(), 164u);
EXPECT_EQ(sem->Align(), 4u); EXPECT_EQ(sem->Align(), 4u);
ASSERT_EQ(sem->Members().size(), 3u); ASSERT_EQ(sem->Members().size(), 4u);
// array<i32, 3>, stride = 8
EXPECT_EQ(sem->Members()[0]->Offset(), 0u); EXPECT_EQ(sem->Members()[0]->Offset(), 0u);
EXPECT_EQ(sem->Members()[0]->Align(), 4u); EXPECT_EQ(sem->Members()[0]->Align(), 4u);
EXPECT_EQ(sem->Members()[0]->Size(), 24u); EXPECT_EQ(sem->Members()[0]->Size(), 24u);
// array<f32, 5>, stride = 16
EXPECT_EQ(sem->Members()[1]->Offset(), 24u); EXPECT_EQ(sem->Members()[1]->Offset(), 24u);
EXPECT_EQ(sem->Members()[1]->Align(), 4u); EXPECT_EQ(sem->Members()[1]->Align(), 4u);
EXPECT_EQ(sem->Members()[1]->Size(), 80u); EXPECT_EQ(sem->Members()[1]->Size(), 80u);
// array<f16, 7>, stride = 4
EXPECT_EQ(sem->Members()[2]->Offset(), 104u); EXPECT_EQ(sem->Members()[2]->Offset(), 104u);
EXPECT_EQ(sem->Members()[2]->Align(), 4u); EXPECT_EQ(sem->Members()[2]->Align(), 2u);
EXPECT_EQ(sem->Members()[2]->Size(), 32u); EXPECT_EQ(sem->Members()[2]->Size(), 28u);
// array<f32, 1>, stride = 32
EXPECT_EQ(sem->Members()[3]->Offset(), 132u);
EXPECT_EQ(sem->Members()[3]->Align(), 4u);
EXPECT_EQ(sem->Members()[3]->Size(), 32u);
for (auto& m : sem->Members()) { for (auto& m : sem->Members()) {
EXPECT_EQ(m->Struct()->Declaration(), s); EXPECT_EQ(m->Struct()->Declaration(), s);
} }
@ -262,53 +335,92 @@ TEST_F(ResolverStructLayoutTest, Vector) {
} }
TEST_F(ResolverStructLayoutTest, Matrix) { TEST_F(ResolverStructLayoutTest, Matrix) {
Enable(ast::Extension::kF16);
auto* s = Structure("S", { auto* s = Structure("S", {
Member("a", ty.mat2x2<f32>()), Member("a_1", ty.mat2x2<f32>()),
Member("b", ty.mat2x3<f32>()), Member("a_2", ty.mat2x2<f16>()),
Member("c", ty.mat2x4<f32>()), Member("b_1", ty.mat2x3<f32>()),
Member("d", ty.mat3x2<f32>()), Member("b_2", ty.mat2x3<f16>()),
Member("e", ty.mat3x3<f32>()), Member("c_1", ty.mat2x4<f32>()),
Member("f", ty.mat3x4<f32>()), Member("c_2", ty.mat2x4<f16>()),
Member("g", ty.mat4x2<f32>()), Member("d_1", ty.mat3x2<f32>()),
Member("h", ty.mat4x3<f32>()), Member("d_2", ty.mat3x2<f16>()),
Member("i", ty.mat4x4<f32>()), Member("e_1", ty.mat3x3<f32>()),
Member("e_2", ty.mat3x3<f16>()),
Member("f_1", ty.mat3x4<f32>()),
Member("f_2", ty.mat3x4<f16>()),
Member("g_1", ty.mat4x2<f32>()),
Member("g_2", ty.mat4x2<f16>()),
Member("h_1", ty.mat4x3<f32>()),
Member("h_2", ty.mat4x3<f16>()),
Member("i_1", ty.mat4x4<f32>()),
Member("i_2", ty.mat4x4<f16>()),
}); });
ASSERT_TRUE(r()->Resolve()) << r()->error(); ASSERT_TRUE(r()->Resolve()) << r()->error();
auto* sem = TypeOf(s)->As<sem::Struct>(); auto* sem = TypeOf(s)->As<sem::Struct>();
ASSERT_NE(sem, nullptr); ASSERT_NE(sem, nullptr);
EXPECT_EQ(sem->Size(), 368u); EXPECT_EQ(sem->Size(), 576u);
EXPECT_EQ(sem->SizeNoPadding(), 368u); EXPECT_EQ(sem->SizeNoPadding(), 576u);
EXPECT_EQ(sem->Align(), 16u); EXPECT_EQ(sem->Align(), 16u);
ASSERT_EQ(sem->Members().size(), 9u); ASSERT_EQ(sem->Members().size(), 18u);
EXPECT_EQ(sem->Members()[0]->Offset(), 0u); // mat2x2 EXPECT_EQ(sem->Members()[0]->Offset(), 0u); // mat2x2<f32>
EXPECT_EQ(sem->Members()[0]->Align(), 8u); EXPECT_EQ(sem->Members()[0]->Align(), 8u);
EXPECT_EQ(sem->Members()[0]->Size(), 16u); EXPECT_EQ(sem->Members()[0]->Size(), 16u);
EXPECT_EQ(sem->Members()[1]->Offset(), 16u); // mat2x3 EXPECT_EQ(sem->Members()[1]->Offset(), 16u); // mat2x2<f16>
EXPECT_EQ(sem->Members()[1]->Align(), 16u); EXPECT_EQ(sem->Members()[1]->Align(), 4u);
EXPECT_EQ(sem->Members()[1]->Size(), 32u); EXPECT_EQ(sem->Members()[1]->Size(), 8u);
EXPECT_EQ(sem->Members()[2]->Offset(), 48u); // mat2x4 EXPECT_EQ(sem->Members()[2]->Offset(), 32u); // mat2x3<f32>
EXPECT_EQ(sem->Members()[2]->Align(), 16u); EXPECT_EQ(sem->Members()[2]->Align(), 16u);
EXPECT_EQ(sem->Members()[2]->Size(), 32u); EXPECT_EQ(sem->Members()[2]->Size(), 32u);
EXPECT_EQ(sem->Members()[3]->Offset(), 80u); // mat3x2 EXPECT_EQ(sem->Members()[3]->Offset(), 64u); // mat2x3<f16>
EXPECT_EQ(sem->Members()[3]->Align(), 8u); EXPECT_EQ(sem->Members()[3]->Align(), 8u);
EXPECT_EQ(sem->Members()[3]->Size(), 24u); EXPECT_EQ(sem->Members()[3]->Size(), 16u);
EXPECT_EQ(sem->Members()[4]->Offset(), 112u); // mat3x3 EXPECT_EQ(sem->Members()[4]->Offset(), 80u); // mat2x4<f32>
EXPECT_EQ(sem->Members()[4]->Align(), 16u); EXPECT_EQ(sem->Members()[4]->Align(), 16u);
EXPECT_EQ(sem->Members()[4]->Size(), 48u); EXPECT_EQ(sem->Members()[4]->Size(), 32u);
EXPECT_EQ(sem->Members()[5]->Offset(), 160u); // mat3x4 EXPECT_EQ(sem->Members()[5]->Offset(), 112u); // mat2x4<f16>
EXPECT_EQ(sem->Members()[5]->Align(), 16u); EXPECT_EQ(sem->Members()[5]->Align(), 8u);
EXPECT_EQ(sem->Members()[5]->Size(), 48u); EXPECT_EQ(sem->Members()[5]->Size(), 16u);
EXPECT_EQ(sem->Members()[6]->Offset(), 208u); // mat4x2 EXPECT_EQ(sem->Members()[6]->Offset(), 128u); // mat3x2<f32>
EXPECT_EQ(sem->Members()[6]->Align(), 8u); EXPECT_EQ(sem->Members()[6]->Align(), 8u);
EXPECT_EQ(sem->Members()[6]->Size(), 32u); EXPECT_EQ(sem->Members()[6]->Size(), 24u);
EXPECT_EQ(sem->Members()[7]->Offset(), 240u); // mat4x3 EXPECT_EQ(sem->Members()[7]->Offset(), 152u); // mat3x2<f16>
EXPECT_EQ(sem->Members()[7]->Align(), 16u); EXPECT_EQ(sem->Members()[7]->Align(), 4u);
EXPECT_EQ(sem->Members()[7]->Size(), 64u); EXPECT_EQ(sem->Members()[7]->Size(), 12u);
EXPECT_EQ(sem->Members()[8]->Offset(), 304u); // mat4x4 EXPECT_EQ(sem->Members()[8]->Offset(), 176u); // mat3x3<f32>
EXPECT_EQ(sem->Members()[8]->Align(), 16u); EXPECT_EQ(sem->Members()[8]->Align(), 16u);
EXPECT_EQ(sem->Members()[8]->Size(), 64u); EXPECT_EQ(sem->Members()[8]->Size(), 48u);
EXPECT_EQ(sem->Members()[9]->Offset(), 224u); // mat3x3<f16>
EXPECT_EQ(sem->Members()[9]->Align(), 8u);
EXPECT_EQ(sem->Members()[9]->Size(), 24u);
EXPECT_EQ(sem->Members()[10]->Offset(), 256u); // mat3x4<f32>
EXPECT_EQ(sem->Members()[10]->Align(), 16u);
EXPECT_EQ(sem->Members()[10]->Size(), 48u);
EXPECT_EQ(sem->Members()[11]->Offset(), 304u); // mat3x4<f16>
EXPECT_EQ(sem->Members()[11]->Align(), 8u);
EXPECT_EQ(sem->Members()[11]->Size(), 24u);
EXPECT_EQ(sem->Members()[12]->Offset(), 328u); // mat4x2<f32>
EXPECT_EQ(sem->Members()[12]->Align(), 8u);
EXPECT_EQ(sem->Members()[12]->Size(), 32u);
EXPECT_EQ(sem->Members()[13]->Offset(), 360u); // mat4x2<f16>
EXPECT_EQ(sem->Members()[13]->Align(), 4u);
EXPECT_EQ(sem->Members()[13]->Size(), 16u);
EXPECT_EQ(sem->Members()[14]->Offset(), 384u); // mat4x3<f32>
EXPECT_EQ(sem->Members()[14]->Align(), 16u);
EXPECT_EQ(sem->Members()[14]->Size(), 64u);
EXPECT_EQ(sem->Members()[15]->Offset(), 448u); // mat4x3<f16>
EXPECT_EQ(sem->Members()[15]->Align(), 8u);
EXPECT_EQ(sem->Members()[15]->Size(), 32u);
EXPECT_EQ(sem->Members()[16]->Offset(), 480u); // mat4x4<f32>
EXPECT_EQ(sem->Members()[16]->Align(), 16u);
EXPECT_EQ(sem->Members()[16]->Size(), 64u);
EXPECT_EQ(sem->Members()[17]->Offset(), 544u); // mat4x4<f16>
EXPECT_EQ(sem->Members()[17]->Align(), 8u);
EXPECT_EQ(sem->Members()[17]->Size(), 32u);
for (auto& m : sem->Members()) { for (auto& m : sem->Members()) {
EXPECT_EQ(m->Struct()->Declaration(), s); EXPECT_EQ(m->Struct()->Declaration(), s);
} }

File diff suppressed because it is too large Load Diff

View File

@ -1120,6 +1120,9 @@ using ValidMatrixTypes = ResolverTestWithParam<Params>;
TEST_P(ValidMatrixTypes, Okay) { TEST_P(ValidMatrixTypes, Okay) {
// var a : matNxM<EL_TY>; // var a : matNxM<EL_TY>;
auto& params = GetParam(); auto& params = GetParam();
Enable(ast::Extension::kF16);
GlobalVar("a", ty.mat(params.elem_ty(*this), params.columns, params.rows), GlobalVar("a", ty.mat(params.elem_ty(*this), params.columns, params.rows),
ast::StorageClass::kPrivate); ast::StorageClass::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -1137,16 +1140,31 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
ParamsFor<f32>(4, 4), ParamsFor<f32>(4, 4),
ParamsFor<alias<f32>>(4, 2), ParamsFor<alias<f32>>(4, 2),
ParamsFor<alias<f32>>(4, 3), ParamsFor<alias<f32>>(4, 3),
ParamsFor<alias<f32>>(4, 4))); ParamsFor<alias<f32>>(4, 4),
ParamsFor<f16>(2, 2),
ParamsFor<f16>(2, 3),
ParamsFor<f16>(2, 4),
ParamsFor<f16>(3, 2),
ParamsFor<f16>(3, 3),
ParamsFor<f16>(3, 4),
ParamsFor<f16>(4, 2),
ParamsFor<f16>(4, 3),
ParamsFor<f16>(4, 4),
ParamsFor<alias<f16>>(4, 2),
ParamsFor<alias<f16>>(4, 3),
ParamsFor<alias<f16>>(4, 4)));
using InvalidMatrixElementTypes = ResolverTestWithParam<Params>; using InvalidMatrixElementTypes = ResolverTestWithParam<Params>;
TEST_P(InvalidMatrixElementTypes, InvalidElementType) { TEST_P(InvalidMatrixElementTypes, InvalidElementType) {
// var a : matNxM<EL_TY>; // var a : matNxM<EL_TY>;
auto& params = GetParam(); auto& params = GetParam();
Enable(ast::Extension::kF16);
GlobalVar("a", ty.mat(Source{{12, 34}}, params.elem_ty(*this), params.columns, params.rows), GlobalVar("a", ty.mat(Source{{12, 34}}, params.elem_ty(*this), params.columns, params.rows),
ast::StorageClass::kPrivate); ast::StorageClass::kPrivate);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: matrix element type must be 'f32'"); EXPECT_EQ(r()->error(), "12:34 error: matrix element type must be 'f32' or 'f16'");
} }
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest, INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
InvalidMatrixElementTypes, InvalidMatrixElementTypes,
@ -1154,12 +1172,17 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
ParamsFor<i32>(4, 3), ParamsFor<i32>(4, 3),
ParamsFor<u32>(4, 4), ParamsFor<u32>(4, 4),
ParamsFor<vec2<f32>>(2, 2), ParamsFor<vec2<f32>>(2, 2),
ParamsFor<vec2<f16>>(2, 2),
ParamsFor<vec3<i32>>(2, 3), ParamsFor<vec3<i32>>(2, 3),
ParamsFor<vec4<u32>>(2, 4), ParamsFor<vec4<u32>>(2, 4),
ParamsFor<mat2x2<f32>>(3, 2), ParamsFor<mat2x2<f32>>(3, 2),
ParamsFor<mat3x3<f32>>(3, 3), ParamsFor<mat3x3<f32>>(3, 3),
ParamsFor<mat4x4<f32>>(3, 4), ParamsFor<mat4x4<f32>>(3, 4),
ParamsFor<array<2, f32>>(4, 2))); ParamsFor<mat2x2<f16>>(3, 2),
ParamsFor<mat3x3<f16>>(3, 3),
ParamsFor<mat4x4<f16>>(3, 4),
ParamsFor<array<2, f32>>(4, 2),
ParamsFor<array<2, f16>>(4, 2)));
} // namespace MatrixTests } // namespace MatrixTests
namespace VectorTests { namespace VectorTests {
@ -1177,6 +1200,9 @@ using ValidVectorTypes = ResolverTestWithParam<Params>;
TEST_P(ValidVectorTypes, Okay) { TEST_P(ValidVectorTypes, Okay) {
// var a : vecN<EL_TY>; // var a : vecN<EL_TY>;
auto& params = GetParam(); auto& params = GetParam();
Enable(ast::Extension::kF16);
GlobalVar("a", ty.vec(params.elem_ty(*this), params.width), ast::StorageClass::kPrivate); GlobalVar("a", ty.vec(params.elem_ty(*this), params.width), ast::StorageClass::kPrivate);
EXPECT_TRUE(r()->Resolve()) << r()->error(); EXPECT_TRUE(r()->Resolve()) << r()->error();
} }
@ -1184,18 +1210,22 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
ValidVectorTypes, ValidVectorTypes,
testing::Values(ParamsFor<bool>(2), testing::Values(ParamsFor<bool>(2),
ParamsFor<f32>(2), ParamsFor<f32>(2),
ParamsFor<f16>(2),
ParamsFor<i32>(2), ParamsFor<i32>(2),
ParamsFor<u32>(2), ParamsFor<u32>(2),
ParamsFor<bool>(3), ParamsFor<bool>(3),
ParamsFor<f32>(3), ParamsFor<f32>(3),
ParamsFor<f16>(3),
ParamsFor<i32>(3), ParamsFor<i32>(3),
ParamsFor<u32>(3), ParamsFor<u32>(3),
ParamsFor<bool>(4), ParamsFor<bool>(4),
ParamsFor<f32>(4), ParamsFor<f32>(4),
ParamsFor<f16>(4),
ParamsFor<i32>(4), ParamsFor<i32>(4),
ParamsFor<u32>(4), ParamsFor<u32>(4),
ParamsFor<alias<bool>>(4), ParamsFor<alias<bool>>(4),
ParamsFor<alias<f32>>(4), ParamsFor<alias<f32>>(4),
ParamsFor<alias<f16>>(4),
ParamsFor<alias<i32>>(4), ParamsFor<alias<i32>>(4),
ParamsFor<alias<u32>>(4))); ParamsFor<alias<u32>>(4)));
@ -1203,11 +1233,15 @@ using InvalidVectorElementTypes = ResolverTestWithParam<Params>;
TEST_P(InvalidVectorElementTypes, InvalidElementType) { TEST_P(InvalidVectorElementTypes, InvalidElementType) {
// var a : vecN<EL_TY>; // var a : vecN<EL_TY>;
auto& params = GetParam(); auto& params = GetParam();
Enable(ast::Extension::kF16);
GlobalVar("a", ty.vec(Source{{12, 34}}, params.elem_ty(*this), params.width), GlobalVar("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(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: vector element type must be 'bool', 'f32', 'i32' or 'u32'"); "12:34 error: vector element type must be 'bool', 'f32', 'f16', 'i32' "
"or 'u32'");
} }
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest, INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
InvalidVectorElementTypes, InvalidVectorElementTypes,
@ -1215,7 +1249,7 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
ParamsFor<vec3<i32>>(2), ParamsFor<vec3<i32>>(2),
ParamsFor<vec4<u32>>(2), ParamsFor<vec4<u32>>(2),
ParamsFor<mat2x2<f32>>(2), ParamsFor<mat2x2<f32>>(2),
ParamsFor<mat3x3<f32>>(2), ParamsFor<mat3x3<f16>>(2),
ParamsFor<mat4x4<f32>>(2), ParamsFor<mat4x4<f32>>(2),
ParamsFor<array<2, f32>>(2))); ParamsFor<array<2, f32>>(2)));
} // namespace VectorTests } // namespace VectorTests

View File

@ -1865,7 +1865,7 @@ bool Validator::ArrayConstructor(const ast::CallExpression* ctor,
bool Validator::Vector(const sem::Vector* ty, const Source& source) const { bool Validator::Vector(const sem::Vector* ty, const Source& source) const {
if (!ty->type()->is_scalar()) { if (!ty->type()->is_scalar()) {
AddError("vector element type must be 'bool', 'f32', 'i32' or 'u32'", source); AddError("vector element type must be 'bool', 'f32', 'f16', 'i32' or 'u32'", source);
return false; return false;
} }
return true; return true;
@ -1873,7 +1873,7 @@ bool Validator::Vector(const sem::Vector* ty, const Source& source) const {
bool Validator::Matrix(const sem::Matrix* ty, const Source& source) const { bool Validator::Matrix(const sem::Matrix* ty, const Source& source) const {
if (!ty->is_float_matrix()) { if (!ty->is_float_matrix()) {
AddError("matrix element type must be 'f32'", source); AddError("matrix element type must be 'f32' or 'f16'", source);
return false; return false;
} }
return true; return true;

View File

@ -32,6 +32,7 @@ TEST_F(ValidatorIsStorableTest, Scalar) {
EXPECT_TRUE(v()->IsStorable(create<sem::I32>())); EXPECT_TRUE(v()->IsStorable(create<sem::I32>()));
EXPECT_TRUE(v()->IsStorable(create<sem::U32>())); EXPECT_TRUE(v()->IsStorable(create<sem::U32>()));
EXPECT_TRUE(v()->IsStorable(create<sem::F32>())); EXPECT_TRUE(v()->IsStorable(create<sem::F32>()));
EXPECT_TRUE(v()->IsStorable(create<sem::F16>()));
} }
TEST_F(ValidatorIsStorableTest, Vector) { TEST_F(ValidatorIsStorableTest, Vector) {
@ -44,21 +45,36 @@ TEST_F(ValidatorIsStorableTest, Vector) {
EXPECT_TRUE(v()->IsStorable(create<sem::Vector>(create<sem::F32>(), 2u))); EXPECT_TRUE(v()->IsStorable(create<sem::Vector>(create<sem::F32>(), 2u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Vector>(create<sem::F32>(), 3u))); EXPECT_TRUE(v()->IsStorable(create<sem::Vector>(create<sem::F32>(), 3u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Vector>(create<sem::F32>(), 4u))); EXPECT_TRUE(v()->IsStorable(create<sem::Vector>(create<sem::F32>(), 4u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Vector>(create<sem::F16>(), 2u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Vector>(create<sem::F16>(), 3u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Vector>(create<sem::F16>(), 4u)));
} }
TEST_F(ValidatorIsStorableTest, Matrix) { TEST_F(ValidatorIsStorableTest, Matrix) {
auto* vec2 = create<sem::Vector>(create<sem::F32>(), 2u); auto* vec2_f32 = create<sem::Vector>(create<sem::F32>(), 2u);
auto* vec3 = create<sem::Vector>(create<sem::F32>(), 3u); auto* vec3_f32 = create<sem::Vector>(create<sem::F32>(), 3u);
auto* vec4 = create<sem::Vector>(create<sem::F32>(), 4u); auto* vec4_f32 = create<sem::Vector>(create<sem::F32>(), 4u);
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec2, 2u))); auto* vec2_f16 = create<sem::Vector>(create<sem::F16>(), 2u);
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec2, 3u))); auto* vec3_f16 = create<sem::Vector>(create<sem::F16>(), 3u);
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec2, 4u))); auto* vec4_f16 = create<sem::Vector>(create<sem::F16>(), 4u);
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec3, 2u))); EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec2_f32, 2u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec3, 3u))); EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec2_f32, 3u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec3, 4u))); EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec2_f32, 4u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec4, 2u))); EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec3_f32, 2u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec4, 3u))); EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec3_f32, 3u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec4, 4u))); EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec3_f32, 4u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec4_f32, 2u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec4_f32, 3u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec4_f32, 4u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec2_f16, 2u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec2_f16, 3u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec2_f16, 4u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec3_f16, 2u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec3_f16, 3u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec3_f16, 4u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec4_f16, 2u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec4_f16, 3u)));
EXPECT_TRUE(v()->IsStorable(create<sem::Matrix>(vec4_f16, 4u)));
} }
TEST_F(ValidatorIsStorableTest, Pointer) { TEST_F(ValidatorIsStorableTest, Pointer) {

View File

@ -35,17 +35,21 @@ TEST_F(ResolverVariableTest, LocalVar_NoConstructor) {
// var i : i32; // var i : i32;
// var u : u32; // var u : u32;
// var f : f32; // var f : f32;
// var h : f16;
// var b : bool; // var b : bool;
// var s : S; // var s : S;
// var a : A; // var a : A;
// } // }
Enable(ast::Extension::kF16);
auto* S = Structure("S", {Member("i", ty.i32())}); auto* S = Structure("S", {Member("i", ty.i32())});
auto* A = Alias("A", ty.Of(S)); auto* A = Alias("A", ty.Of(S));
auto* i = Var("i", ty.i32(), ast::StorageClass::kNone); auto* i = Var("i", ty.i32(), ast::StorageClass::kNone);
auto* u = Var("u", ty.u32(), ast::StorageClass::kNone); auto* u = Var("u", ty.u32(), ast::StorageClass::kNone);
auto* f = Var("f", ty.f32(), ast::StorageClass::kNone); auto* f = Var("f", ty.f32(), ast::StorageClass::kNone);
auto* h = Var("h", ty.f16(), ast::StorageClass::kNone);
auto* b = Var("b", ty.bool_(), ast::StorageClass::kNone); auto* b = Var("b", ty.bool_(), ast::StorageClass::kNone);
auto* s = Var("s", ty.Of(S), ast::StorageClass::kNone); auto* s = Var("s", ty.Of(S), ast::StorageClass::kNone);
auto* a = Var("a", ty.Of(A), ast::StorageClass::kNone); auto* a = Var("a", ty.Of(A), ast::StorageClass::kNone);
@ -55,6 +59,7 @@ TEST_F(ResolverVariableTest, LocalVar_NoConstructor) {
Decl(i), Decl(i),
Decl(u), Decl(u),
Decl(f), Decl(f),
Decl(h),
Decl(b), Decl(b),
Decl(s), Decl(s),
Decl(a), Decl(a),
@ -66,6 +71,7 @@ TEST_F(ResolverVariableTest, LocalVar_NoConstructor) {
ASSERT_TRUE(TypeOf(i)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(i)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(u)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(u)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(f)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(f)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(h)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(b)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(b)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(s)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(s)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(a)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(a)->Is<sem::Reference>());
@ -73,6 +79,7 @@ TEST_F(ResolverVariableTest, LocalVar_NoConstructor) {
EXPECT_TRUE(TypeOf(i)->As<sem::Reference>()->StoreType()->Is<sem::I32>()); EXPECT_TRUE(TypeOf(i)->As<sem::Reference>()->StoreType()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(u)->As<sem::Reference>()->StoreType()->Is<sem::U32>()); EXPECT_TRUE(TypeOf(u)->As<sem::Reference>()->StoreType()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(f)->As<sem::Reference>()->StoreType()->Is<sem::F32>()); EXPECT_TRUE(TypeOf(f)->As<sem::Reference>()->StoreType()->Is<sem::F32>());
EXPECT_TRUE(TypeOf(h)->As<sem::Reference>()->StoreType()->Is<sem::F16>());
EXPECT_TRUE(TypeOf(b)->As<sem::Reference>()->StoreType()->Is<sem::Bool>()); EXPECT_TRUE(TypeOf(b)->As<sem::Reference>()->StoreType()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(s)->As<sem::Reference>()->StoreType()->Is<sem::Struct>()); EXPECT_TRUE(TypeOf(s)->As<sem::Reference>()->StoreType()->Is<sem::Struct>());
EXPECT_TRUE(TypeOf(a)->As<sem::Reference>()->StoreType()->Is<sem::Struct>()); EXPECT_TRUE(TypeOf(a)->As<sem::Reference>()->StoreType()->Is<sem::Struct>());
@ -80,6 +87,7 @@ TEST_F(ResolverVariableTest, LocalVar_NoConstructor) {
EXPECT_EQ(Sem().Get(i)->Constructor(), nullptr); EXPECT_EQ(Sem().Get(i)->Constructor(), nullptr);
EXPECT_EQ(Sem().Get(u)->Constructor(), nullptr); EXPECT_EQ(Sem().Get(u)->Constructor(), nullptr);
EXPECT_EQ(Sem().Get(f)->Constructor(), nullptr); EXPECT_EQ(Sem().Get(f)->Constructor(), nullptr);
EXPECT_EQ(Sem().Get(h)->Constructor(), nullptr);
EXPECT_EQ(Sem().Get(b)->Constructor(), nullptr); EXPECT_EQ(Sem().Get(b)->Constructor(), nullptr);
EXPECT_EQ(Sem().Get(s)->Constructor(), nullptr); EXPECT_EQ(Sem().Get(s)->Constructor(), nullptr);
EXPECT_EQ(Sem().Get(a)->Constructor(), nullptr); EXPECT_EQ(Sem().Get(a)->Constructor(), nullptr);
@ -92,17 +100,21 @@ TEST_F(ResolverVariableTest, LocalVar_WithConstructor) {
// var i : i32 = 1i; // var i : i32 = 1i;
// var u : u32 = 1u; // var u : u32 = 1u;
// var f : f32 = 1.f; // var f : f32 = 1.f;
// var h : f16 = 1.h;
// var b : bool = true; // var b : bool = true;
// var s : S = S(1); // var s : S = S(1);
// var a : A = A(1); // var a : A = A(1);
// } // }
Enable(ast::Extension::kF16);
auto* S = Structure("S", {Member("i", ty.i32())}); auto* S = Structure("S", {Member("i", ty.i32())});
auto* A = Alias("A", ty.Of(S)); auto* A = Alias("A", ty.Of(S));
auto* i_c = Expr(1_i); auto* i_c = Expr(1_i);
auto* u_c = Expr(1_u); auto* u_c = Expr(1_u);
auto* f_c = Expr(1_f); auto* f_c = Expr(1_f);
auto* h_c = Expr(1_h);
auto* b_c = Expr(true); auto* b_c = Expr(true);
auto* s_c = Construct(ty.Of(S), Expr(1_i)); auto* s_c = Construct(ty.Of(S), Expr(1_i));
auto* a_c = Construct(ty.Of(A), Expr(1_i)); auto* a_c = Construct(ty.Of(A), Expr(1_i));
@ -110,6 +122,7 @@ TEST_F(ResolverVariableTest, LocalVar_WithConstructor) {
auto* i = Var("i", ty.i32(), ast::StorageClass::kNone, i_c); auto* i = Var("i", ty.i32(), ast::StorageClass::kNone, i_c);
auto* u = Var("u", ty.u32(), ast::StorageClass::kNone, u_c); auto* u = Var("u", ty.u32(), ast::StorageClass::kNone, u_c);
auto* f = Var("f", ty.f32(), ast::StorageClass::kNone, f_c); auto* f = Var("f", ty.f32(), ast::StorageClass::kNone, f_c);
auto* h = Var("h", ty.f16(), ast::StorageClass::kNone, h_c);
auto* b = Var("b", ty.bool_(), ast::StorageClass::kNone, b_c); auto* b = Var("b", ty.bool_(), ast::StorageClass::kNone, b_c);
auto* s = Var("s", ty.Of(S), ast::StorageClass::kNone, s_c); auto* s = Var("s", ty.Of(S), ast::StorageClass::kNone, s_c);
auto* a = Var("a", ty.Of(A), ast::StorageClass::kNone, a_c); auto* a = Var("a", ty.Of(A), ast::StorageClass::kNone, a_c);
@ -119,6 +132,7 @@ TEST_F(ResolverVariableTest, LocalVar_WithConstructor) {
Decl(i), Decl(i),
Decl(u), Decl(u),
Decl(f), Decl(f),
Decl(h),
Decl(b), Decl(b),
Decl(s), Decl(s),
Decl(a), Decl(a),
@ -130,6 +144,7 @@ TEST_F(ResolverVariableTest, LocalVar_WithConstructor) {
ASSERT_TRUE(TypeOf(i)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(i)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(u)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(u)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(f)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(f)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(h)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(b)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(b)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(s)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(s)->Is<sem::Reference>());
ASSERT_TRUE(TypeOf(a)->Is<sem::Reference>()); ASSERT_TRUE(TypeOf(a)->Is<sem::Reference>());
@ -144,6 +159,7 @@ TEST_F(ResolverVariableTest, LocalVar_WithConstructor) {
EXPECT_TRUE(TypeOf(i)->As<sem::Reference>()->StoreType()->Is<sem::I32>()); EXPECT_TRUE(TypeOf(i)->As<sem::Reference>()->StoreType()->Is<sem::I32>());
EXPECT_TRUE(TypeOf(u)->As<sem::Reference>()->StoreType()->Is<sem::U32>()); EXPECT_TRUE(TypeOf(u)->As<sem::Reference>()->StoreType()->Is<sem::U32>());
EXPECT_TRUE(TypeOf(f)->As<sem::Reference>()->StoreType()->Is<sem::F32>()); EXPECT_TRUE(TypeOf(f)->As<sem::Reference>()->StoreType()->Is<sem::F32>());
EXPECT_TRUE(TypeOf(h)->As<sem::Reference>()->StoreType()->Is<sem::F16>());
EXPECT_TRUE(TypeOf(b)->As<sem::Reference>()->StoreType()->Is<sem::Bool>()); EXPECT_TRUE(TypeOf(b)->As<sem::Reference>()->StoreType()->Is<sem::Bool>());
EXPECT_TRUE(TypeOf(s)->As<sem::Reference>()->StoreType()->Is<sem::Struct>()); EXPECT_TRUE(TypeOf(s)->As<sem::Reference>()->StoreType()->Is<sem::Struct>());
EXPECT_TRUE(TypeOf(a)->As<sem::Reference>()->StoreType()->Is<sem::Struct>()); EXPECT_TRUE(TypeOf(a)->As<sem::Reference>()->StoreType()->Is<sem::Struct>());
@ -151,6 +167,7 @@ TEST_F(ResolverVariableTest, LocalVar_WithConstructor) {
EXPECT_EQ(Sem().Get(i)->Constructor()->Declaration(), i_c); EXPECT_EQ(Sem().Get(i)->Constructor()->Declaration(), i_c);
EXPECT_EQ(Sem().Get(u)->Constructor()->Declaration(), u_c); EXPECT_EQ(Sem().Get(u)->Constructor()->Declaration(), u_c);
EXPECT_EQ(Sem().Get(f)->Constructor()->Declaration(), f_c); EXPECT_EQ(Sem().Get(f)->Constructor()->Declaration(), f_c);
EXPECT_EQ(Sem().Get(h)->Constructor()->Declaration(), h_c);
EXPECT_EQ(Sem().Get(b)->Constructor()->Declaration(), b_c); EXPECT_EQ(Sem().Get(b)->Constructor()->Declaration(), b_c);
EXPECT_EQ(Sem().Get(s)->Constructor()->Declaration(), s_c); EXPECT_EQ(Sem().Get(s)->Constructor()->Declaration(), s_c);
EXPECT_EQ(Sem().Get(a)->Constructor()->Declaration(), a_c); EXPECT_EQ(Sem().Get(a)->Constructor()->Declaration(), a_c);
@ -396,13 +413,16 @@ TEST_F(ResolverVariableTest, LocalLet) {
// var v : i32; // var v : i32;
// let i : i32 = 1i; // let i : i32 = 1i;
// let u : u32 = 1u; // let u : u32 = 1u;
// let f : f32 = 1.; // let f : f32 = 1.f;
// let h : h32 = 1.h;
// let b : bool = true; // let b : bool = true;
// let s : S = S(1); // let s : S = S(1);
// let a : A = A(1); // let a : A = A(1);
// let p : pointer<function, i32> = &v; // let p : pointer<function, i32> = &v;
// } // }
Enable(ast::Extension::kF16);
auto* S = Structure("S", {Member("i", ty.i32())}); auto* S = Structure("S", {Member("i", ty.i32())});
auto* A = Alias("A", ty.Of(S)); auto* A = Alias("A", ty.Of(S));
auto* v = Var("v", ty.i32(), ast::StorageClass::kNone); auto* v = Var("v", ty.i32(), ast::StorageClass::kNone);
@ -410,6 +430,7 @@ TEST_F(ResolverVariableTest, LocalLet) {
auto* i_c = Expr(1_i); auto* i_c = Expr(1_i);
auto* u_c = Expr(1_u); auto* u_c = Expr(1_u);
auto* f_c = Expr(1_f); auto* f_c = Expr(1_f);
auto* h_c = Expr(1_h);
auto* b_c = Expr(true); auto* b_c = Expr(true);
auto* s_c = Construct(ty.Of(S), Expr(1_i)); auto* s_c = Construct(ty.Of(S), Expr(1_i));
auto* a_c = Construct(ty.Of(A), Expr(1_i)); auto* a_c = Construct(ty.Of(A), Expr(1_i));
@ -418,6 +439,7 @@ TEST_F(ResolverVariableTest, LocalLet) {
auto* i = Let("i", ty.i32(), i_c); auto* i = Let("i", ty.i32(), i_c);
auto* u = Let("u", ty.u32(), u_c); auto* u = Let("u", ty.u32(), u_c);
auto* f = Let("f", ty.f32(), f_c); auto* f = Let("f", ty.f32(), f_c);
auto* h = Let("h", ty.f16(), h_c);
auto* b = Let("b", ty.bool_(), b_c); auto* b = Let("b", ty.bool_(), b_c);
auto* s = Let("s", ty.Of(S), s_c); auto* s = Let("s", ty.Of(S), s_c);
auto* a = Let("a", ty.Of(A), a_c); auto* a = Let("a", ty.Of(A), a_c);
@ -429,6 +451,7 @@ TEST_F(ResolverVariableTest, LocalLet) {
Decl(i), Decl(i),
Decl(u), Decl(u),
Decl(f), Decl(f),
Decl(h),
Decl(b), Decl(b),
Decl(s), Decl(s),
Decl(a), Decl(a),
@ -441,6 +464,7 @@ TEST_F(ResolverVariableTest, LocalLet) {
ASSERT_TRUE(TypeOf(i)->Is<sem::I32>()); ASSERT_TRUE(TypeOf(i)->Is<sem::I32>());
ASSERT_TRUE(TypeOf(u)->Is<sem::U32>()); ASSERT_TRUE(TypeOf(u)->Is<sem::U32>());
ASSERT_TRUE(TypeOf(f)->Is<sem::F32>()); ASSERT_TRUE(TypeOf(f)->Is<sem::F32>());
ASSERT_TRUE(TypeOf(h)->Is<sem::F16>());
ASSERT_TRUE(TypeOf(b)->Is<sem::Bool>()); ASSERT_TRUE(TypeOf(b)->Is<sem::Bool>());
ASSERT_TRUE(TypeOf(s)->Is<sem::Struct>()); ASSERT_TRUE(TypeOf(s)->Is<sem::Struct>());
ASSERT_TRUE(TypeOf(a)->Is<sem::Struct>()); ASSERT_TRUE(TypeOf(a)->Is<sem::Struct>());
@ -450,6 +474,7 @@ TEST_F(ResolverVariableTest, LocalLet) {
EXPECT_EQ(Sem().Get(i)->Constructor()->Declaration(), i_c); EXPECT_EQ(Sem().Get(i)->Constructor()->Declaration(), i_c);
EXPECT_EQ(Sem().Get(u)->Constructor()->Declaration(), u_c); EXPECT_EQ(Sem().Get(u)->Constructor()->Declaration(), u_c);
EXPECT_EQ(Sem().Get(f)->Constructor()->Declaration(), f_c); EXPECT_EQ(Sem().Get(f)->Constructor()->Declaration(), f_c);
EXPECT_EQ(Sem().Get(h)->Constructor()->Declaration(), h_c);
EXPECT_EQ(Sem().Get(b)->Constructor()->Declaration(), b_c); EXPECT_EQ(Sem().Get(b)->Constructor()->Declaration(), b_c);
EXPECT_EQ(Sem().Get(s)->Constructor()->Declaration(), s_c); EXPECT_EQ(Sem().Get(s)->Constructor()->Declaration(), s_c);
EXPECT_EQ(Sem().Get(a)->Constructor()->Declaration(), a_c); EXPECT_EQ(Sem().Get(a)->Constructor()->Declaration(), a_c);

View File

@ -0,0 +1,49 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen
// using the template:
// test/tint/builtins/gen/gen.wgsl.tmpl
// and the intrinsic defintion file:
// src/tint/intrinsics.def
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
struct SB_RO {
arg_0: array<f16>,
};
@group(0) @binding(1) var<storage, read> sb_ro : SB_RO;
// fn arrayLength(ptr<storage, array<f16>, read>) -> u32
fn arrayLength_8421b9() {
var res: u32 = arrayLength(&sb_ro.arg_0);
}
@vertex
fn vertex_main() -> @builtin(position) vec4<f32> {
arrayLength_8421b9();
return vec4<f32>();
}
@fragment
fn fragment_main() {
arrayLength_8421b9();
}
@compute @workgroup_size(1)
fn compute_main() {
arrayLength_8421b9();
}

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1,49 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen
// using the template:
// test/tint/builtins/gen/gen.wgsl.tmpl
// and the intrinsic defintion file:
// src/tint/intrinsics.def
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
struct SB_RW {
arg_0: array<f16>,
};
@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW;
// fn arrayLength(ptr<storage, array<f16>, read_write>) -> u32
fn arrayLength_cbd6b5() {
var res: u32 = arrayLength(&sb_rw.arg_0);
}
@vertex
fn vertex_main() -> @builtin(position) vec4<f32> {
arrayLength_cbd6b5();
return vec4<f32>();
}
@fragment
fn fragment_main() {
arrayLength_cbd6b5();
}
@compute @workgroup_size(1)
fn compute_main() {
arrayLength_cbd6b5();
}

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1,49 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen
// using the template:
// test/tint/builtins/gen/gen.wgsl.tmpl
// and the intrinsic defintion file:
// src/tint/intrinsics.def
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
struct SB_RO {
arg_0: array<f16>,
};
@group(0) @binding(1) var<storage, read> sb_ro : SB_RO;
// fn arrayLength(ptr<storage, array<f16>, read>) -> u32
fn arrayLength_8421b9() {
var res: u32 = arrayLength(&sb_ro.arg_0);
}
@vertex
fn vertex_main() -> @builtin(position) vec4<f32> {
arrayLength_8421b9();
return vec4<f32>();
}
@fragment
fn fragment_main() {
arrayLength_8421b9();
}
@compute @workgroup_size(1)
fn compute_main() {
arrayLength_8421b9();
}

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1,49 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen
// using the template:
// test/tint/builtins/gen/gen.wgsl.tmpl
// and the intrinsic defintion file:
// src/tint/intrinsics.def
//
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
struct SB_RW {
arg_0: array<f16>,
};
@group(0) @binding(0) var<storage, read_write> sb_rw : SB_RW;
// fn arrayLength(ptr<storage, array<f16>, read_write>) -> u32
fn arrayLength_cbd6b5() {
var res: u32 = arrayLength(&sb_rw.arg_0);
}
@vertex
fn vertex_main() -> @builtin(position) vec4<f32> {
arrayLength_cbd6b5();
return vec4<f32>();
}
@fragment
fn fragment_main() {
arrayLength_cbd6b5();
}
@compute @workgroup_size(1)
fn compute_main() {
arrayLength_cbd6b5();
}

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1 @@
SKIP

View File

@ -0,0 +1 @@
SKIP