tint/writer/glsl: Support for F16 type, constructor, and convertor
This patch make GLSL writer support emitting f16 types, f16 literals, f16 constructor and convertor. Unittests are also implemented, and end-to-end testcases are updated for GLSL extension requirement. The GLSL writer will require `GL_AMD_gpu_shader_half_float` extension if f16 WGSL extension is enabled, emit f16 literal as `1.23hf`, and map f16 types as follow: WGSL type -> GLSL type f16 -> float16_t vec2<f16> -> f16vec2 vec3<f16> -> f16vec3 vec4<f16> -> f16vec4 mat2x2<f16> -> f16mat2 mat2x3<f16> -> f16mat2x3 mat2x4<f16> -> f16mat2x4 mat3x2<f16> -> f16mat3x2 mat3x3<f16> -> f16mat3 mat3x4<f16> -> f16mat3x4 mat4x2<f16> -> f16mat4x2 mat4x3<f16> -> f16mat4x3 mat4x4<f16> -> f16mat4 Bug: tint:1473, tint:1502 Change-Id: I7e788f82be2873911961c891a644200c1cbb74db Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/95684 Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Zhaoming Jiang <zhaoming.jiang@intel.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
f580be6960
commit
0d3d3210d4
|
@ -159,6 +159,17 @@ void PrintF32(std::ostream& out, float value) {
|
|||
}
|
||||
}
|
||||
|
||||
bool PrintF16(std::ostream& out, float value) {
|
||||
// Note: Currently inf and nan should not be constructable, and there is no solid way to
|
||||
// generate constant/literal f16 Inf or NaN.
|
||||
if (std::isinf(value) || std::isnan(value)) {
|
||||
return false;
|
||||
} else {
|
||||
out << FloatToString(value) << "hf";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SanitizedResult::SanitizedResult() = default;
|
||||
|
@ -313,6 +324,10 @@ bool GeneratorImpl::Generate() {
|
|||
extensions.Append("#extension GL_OES_sample_variables : require");
|
||||
}
|
||||
|
||||
if (requires_f16_extension_) {
|
||||
extensions.Append("#extension GL_AMD_gpu_shader_half_float : require");
|
||||
}
|
||||
|
||||
auto indent = current_buffer_->current_indent;
|
||||
|
||||
if (!extensions.lines.empty()) {
|
||||
|
@ -333,17 +348,12 @@ bool GeneratorImpl::Generate() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::RecordExtension(const ast::Enable*) {
|
||||
/*
|
||||
Deal with extension node here, recording it within the generator for
|
||||
later emition.
|
||||
For example:
|
||||
```
|
||||
if (ext->kind == ast::Enable::ExtensionKind::kF16) {
|
||||
require_fp16_ = true;
|
||||
}
|
||||
```
|
||||
*/
|
||||
bool GeneratorImpl::RecordExtension(const ast::Enable* ext) {
|
||||
// Deal with extension node here, recording it within the generator for later emition.
|
||||
|
||||
if (ext->extension == ast::Extension::kF16) {
|
||||
requires_f16_extension_ = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2225,6 +2235,7 @@ bool GeneratorImpl::EmitConstant(std::ostream& out, const sem::Constant* constan
|
|||
PrintF32(out, constant->As<float>());
|
||||
return true;
|
||||
},
|
||||
[&](const sem::F16*) { return PrintF16(out, constant->As<float>()); },
|
||||
[&](const sem::I32*) {
|
||||
out << constant->As<AInt>();
|
||||
return true;
|
||||
|
@ -2305,6 +2316,9 @@ bool GeneratorImpl::EmitLiteral(std::ostream& out, const ast::LiteralExpression*
|
|||
return true;
|
||||
},
|
||||
[&](const ast::FloatLiteralExpression* l) {
|
||||
if (l->suffix == ast::FloatLiteralExpression::Suffix::kH) {
|
||||
return PrintF16(out, static_cast<float>(l->value));
|
||||
}
|
||||
PrintF32(out, static_cast<float>(l->value));
|
||||
return true;
|
||||
},
|
||||
|
@ -2326,6 +2340,8 @@ bool GeneratorImpl::EmitZeroValue(std::ostream& out, const sem::Type* type) {
|
|||
out << "false";
|
||||
} else if (type->Is<sem::F32>()) {
|
||||
out << "0.0f";
|
||||
} else if (type->Is<sem::F16>()) {
|
||||
out << "0.0hf";
|
||||
} else if (type->Is<sem::I32>()) {
|
||||
out << "0";
|
||||
} else if (type->Is<sem::U32>()) {
|
||||
|
@ -2751,12 +2767,14 @@ bool GeneratorImpl::EmitType(std::ostream& out,
|
|||
} else if (type->Is<sem::F32>()) {
|
||||
out << "float";
|
||||
} else if (type->Is<sem::F16>()) {
|
||||
diagnostics_.add_error(diag::System::Writer, "Type f16 is not completely implemented yet.");
|
||||
return false;
|
||||
out << "float16_t";
|
||||
} else if (type->Is<sem::I32>()) {
|
||||
out << "int";
|
||||
} else if (auto* mat = type->As<sem::Matrix>()) {
|
||||
TINT_ASSERT(Writer, mat->type()->Is<sem::F32>());
|
||||
TINT_ASSERT(Writer, (mat->type()->IsAnyOf<sem::F32, sem::F16>()));
|
||||
if (mat->type()->Is<sem::F16>()) {
|
||||
out << "f16";
|
||||
}
|
||||
out << "mat" << mat->columns();
|
||||
if (mat->rows() != mat->columns()) {
|
||||
out << "x" << mat->rows();
|
||||
|
@ -2835,6 +2853,8 @@ bool GeneratorImpl::EmitType(std::ostream& out,
|
|||
auto width = vec->Width();
|
||||
if (vec->type()->Is<sem::F32>() && width >= 1 && width <= 4) {
|
||||
out << "vec" << width;
|
||||
} else if (vec->type()->Is<sem::F16>() && width >= 1 && width <= 4) {
|
||||
out << "f16vec" << width;
|
||||
} else if (vec->type()->Is<sem::I32>() && width >= 1 && width <= 4) {
|
||||
out << "ivec" << width;
|
||||
} else if (vec->type()->Is<sem::U32>() && width >= 1 && width <= 4) {
|
||||
|
|
|
@ -527,6 +527,7 @@ class GeneratorImpl : public TextGenerator {
|
|||
std::unordered_set<const sem::Struct*> emitted_structs_;
|
||||
bool requires_oes_sample_variables_ = false;
|
||||
bool requires_default_precision_qualifier_ = false;
|
||||
bool requires_f16_extension_ = false;
|
||||
Version version_;
|
||||
};
|
||||
|
||||
|
|
|
@ -61,6 +61,18 @@ TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Float) {
|
|||
EXPECT_THAT(gen.result(), HasSubstr("1073741824.0f"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_F16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
// Use a number close to 1<<16 but whose decimal representation ends in 0.
|
||||
WrapInFunction(Expr(f16((1 << 15) - 8)));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_THAT(gen.result(), HasSubstr("32752.0hf"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Float) {
|
||||
WrapInFunction(Construct<f32>(-1.2e-5_f));
|
||||
|
||||
|
@ -70,6 +82,17 @@ TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Float) {
|
|||
EXPECT_THAT(gen.result(), HasSubstr("-0.000012f"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_F16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
WrapInFunction(Construct<f16>(-1.2e-3_h));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_THAT(gen.result(), HasSubstr("-0.00119972229hf"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Bool) {
|
||||
WrapInFunction(Construct<bool>(true));
|
||||
|
||||
|
@ -97,7 +120,7 @@ TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Uint) {
|
|||
EXPECT_THAT(gen.result(), HasSubstr("12345u"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec) {
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_F32) {
|
||||
WrapInFunction(vec3<f32>(1_f, 2_f, 3_f));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
@ -106,7 +129,18 @@ TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec) {
|
|||
EXPECT_THAT(gen.result(), HasSubstr("vec3(1.0f, 2.0f, 3.0f)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_Empty) {
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_F16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
WrapInFunction(vec3<f16>(1_h, 2_h, 3_h));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_THAT(gen.result(), HasSubstr("f16vec3(1.0hf, 2.0hf, 3.0hf)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_Empty_F32) {
|
||||
WrapInFunction(vec3<f32>());
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
@ -115,7 +149,18 @@ TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_Empty) {
|
|||
EXPECT_THAT(gen.result(), HasSubstr("vec3(0.0f)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_Float) {
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_Empty_F16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
WrapInFunction(vec3<f16>());
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_THAT(gen.result(), HasSubstr("f16vec3(0.0hf)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_F32_Literal) {
|
||||
WrapInFunction(vec3<f32>(2_f));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
@ -124,6 +169,43 @@ TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_
|
|||
EXPECT_THAT(gen.result(), HasSubstr("vec3(2.0f)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_F16_Literal) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
WrapInFunction(vec3<f16>(2_h));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_THAT(gen.result(), HasSubstr("f16vec3(2.0hf)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_F32_Var) {
|
||||
auto* var = Var("v", nullptr, Expr(2_f));
|
||||
auto* cast = vec3<f32>(var);
|
||||
WrapInFunction(var, cast);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_THAT(gen.result(), HasSubstr(R"(float v = 2.0f;
|
||||
vec3 tint_symbol = vec3(v);)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_F16_Var) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* var = Var("v", nullptr, Expr(2_h));
|
||||
auto* cast = vec3<f16>(var);
|
||||
WrapInFunction(var, cast);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_THAT(gen.result(), HasSubstr(R"(float16_t v = 2.0hf;
|
||||
f16vec3 tint_symbol = f16vec3(v);)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_Bool) {
|
||||
WrapInFunction(vec3<bool>(true));
|
||||
|
||||
|
@ -151,7 +233,7 @@ TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Vec_SingleScalar_
|
|||
EXPECT_THAT(gen.result(), HasSubstr("uvec3(2u)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat) {
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_F32) {
|
||||
WrapInFunction(mat2x3<f32>(vec3<f32>(1_f, 2_f, 3_f), vec3<f32>(3_f, 4_f, 5_f)));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
@ -161,14 +243,135 @@ TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat) {
|
|||
EXPECT_THAT(gen.result(), HasSubstr("mat2x3(vec3(1.0f, 2.0f, 3.0f), vec3(3.0f, 4.0f, 5.0f))"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_Empty) {
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_F16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
WrapInFunction(mat2x3<f16>(vec3<f16>(1_h, 2_h, 3_h), vec3<f16>(3_h, 4_h, 5_h)));
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_THAT(gen.result(),
|
||||
HasSubstr("f16mat2x3(f16vec3(1.0hf, 2.0hf, 3.0hf), f16vec3(3.0hf, 4.0hf, 5.0hf))"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_Complex_F32) {
|
||||
// mat4x4<f32>(
|
||||
// vec4<f32>(2.0f, 3.0f, 4.0f, 8.0f),
|
||||
// vec4<f32>(),
|
||||
// vec4<f32>(7.0f),
|
||||
// vec4<f32>(vec4<f32>(42.0f, 21.0f, 6.0f, -5.0f)),
|
||||
// );
|
||||
auto* vector_literal =
|
||||
vec4<f32>(Expr(f32(2.0)), Expr(f32(3.0)), Expr(f32(4.0)), Expr(f32(8.0)));
|
||||
auto* vector_zero_ctor = vec4<f32>();
|
||||
auto* vector_single_scalar_ctor = vec4<f32>(Expr(f32(7.0)));
|
||||
auto* vector_identical_ctor =
|
||||
vec4<f32>(vec4<f32>(Expr(f32(42.0)), Expr(f32(21.0)), Expr(f32(6.0)), Expr(f32(-5.0))));
|
||||
|
||||
auto* constructor = mat4x4<f32>(vector_literal, vector_zero_ctor, vector_single_scalar_ctor,
|
||||
vector_identical_ctor);
|
||||
|
||||
WrapInFunction(constructor);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_THAT(gen.result(), HasSubstr("mat4(vec4(2.0f, 3.0f, 4.0f, 8.0f), vec4(0.0f), "
|
||||
"vec4(7.0f), vec4(42.0f, 21.0f, 6.0f, -5.0f))"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_Complex_F16) {
|
||||
// mat4x4<f16>(
|
||||
// vec4<f16>(2.0h, 3.0h, 4.0h, 8.0h),
|
||||
// vec4<f16>(),
|
||||
// vec4<f16>(7.0h),
|
||||
// vec4<f16>(vec4<f16>(42.0h, 21.0h, 6.0h, -5.0h)),
|
||||
// );
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* vector_literal =
|
||||
vec4<f16>(Expr(f16(2.0)), Expr(f16(3.0)), Expr(f16(4.0)), Expr(f16(8.0)));
|
||||
auto* vector_zero_ctor = vec4<f16>();
|
||||
auto* vector_single_scalar_ctor = vec4<f16>(Expr(f16(7.0)));
|
||||
auto* vector_identical_ctor =
|
||||
vec4<f16>(vec4<f16>(Expr(f16(42.0)), Expr(f16(21.0)), Expr(f16(6.0)), Expr(f16(-5.0))));
|
||||
|
||||
auto* constructor = mat4x4<f16>(vector_literal, vector_zero_ctor, vector_single_scalar_ctor,
|
||||
vector_identical_ctor);
|
||||
|
||||
WrapInFunction(constructor);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_THAT(gen.result(),
|
||||
HasSubstr("f16mat4(f16vec4(2.0hf, 3.0hf, 4.0hf, 8.0hf), f16vec4(0.0hf), "
|
||||
"f16vec4(7.0hf), f16vec4(42.0hf, 21.0hf, 6.0hf, -5.0hf))"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_Empty_F32) {
|
||||
WrapInFunction(mat2x3<f32>());
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_THAT(gen.result(), HasSubstr("mat2x3(vec3(0.0f), vec3(0.0f)"));
|
||||
EXPECT_THAT(gen.result(), HasSubstr("mat2x3 tint_symbol = mat2x3(vec3(0.0f), vec3(0.0f))"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_Empty_F16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
WrapInFunction(mat2x3<f16>());
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_THAT(gen.result(),
|
||||
HasSubstr("f16mat2x3 tint_symbol = f16mat2x3(f16vec3(0.0hf), f16vec3(0.0hf))"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_Identity_F32) {
|
||||
// fn f() {
|
||||
// var m_1: mat4x4<f32> = mat4x4<f32>();
|
||||
// var m_2: mat4x4<f32> = mat4x4<f32>(m_1);
|
||||
// }
|
||||
|
||||
auto* m_1 = Var("m_1", ty.mat4x4(ty.f32()), mat4x4<f32>());
|
||||
auto* m_2 = Var("m_2", ty.mat4x4(ty.f32()), mat4x4<f32>(m_1));
|
||||
|
||||
WrapInFunction(m_1, m_2);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_THAT(gen.result(), HasSubstr("mat4 m_2 = mat4(m_1);"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Mat_Identity_F16) {
|
||||
// fn f() {
|
||||
// var m_1: mat4x4<f16> = mat4x4<f16>();
|
||||
// var m_2: mat4x4<f16> = mat4x4<f16>(m_1);
|
||||
// }
|
||||
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* m_1 = Var("m_1", ty.mat4x4(ty.f16()), mat4x4<f16>());
|
||||
auto* m_2 = Var("m_2", ty.mat4x4(ty.f16()), mat4x4<f16>(m_1));
|
||||
|
||||
WrapInFunction(m_1, m_2);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_THAT(gen.result(), HasSubstr("f16mat4 m_2 = f16mat4(m_1);"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Constructor, EmitConstructor_Type_Array) {
|
||||
|
|
|
@ -117,6 +117,26 @@ void f() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* var = GlobalConst("G", nullptr, Expr(1_h));
|
||||
Func("f", {}, ty.void_(), {Decl(Let("l", nullptr, Expr(var)))});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_EQ(gen.result(), R"(#version 310 es
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
|
||||
void f() {
|
||||
float16_t l = 1.0hf;
|
||||
}
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_AInt) {
|
||||
auto* var = GlobalConst("G", nullptr, Construct(ty.vec3(nullptr), 1_a, 2_a, 3_a));
|
||||
Func("f", {}, ty.void_(), {Decl(Let("l", nullptr, Expr(var)))});
|
||||
|
@ -168,6 +188,26 @@ void f() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_vec3_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* var = GlobalConst("G", nullptr, vec3<f16>(1_h, 2_h, 3_h));
|
||||
Func("f", {}, ty.void_(), {Decl(Let("l", nullptr, Expr(var)))});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_EQ(gen.result(), R"(#version 310 es
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
|
||||
void f() {
|
||||
f16vec3 l = f16vec3(1.0hf, 2.0hf, 3.0hf);
|
||||
}
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_mat2x3_AFloat) {
|
||||
auto* var = GlobalConst("G", nullptr,
|
||||
Construct(ty.mat(nullptr, 2, 3), 1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
|
||||
|
@ -203,6 +243,26 @@ void f() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_mat2x3_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* var = GlobalConst("G", nullptr, mat2x3<f16>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
|
||||
Func("f", {}, ty.void_(), {Decl(Let("l", nullptr, Expr(var)))});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_EQ(gen.result(), R"(#version 310 es
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
|
||||
void f() {
|
||||
f16mat2x3 l = f16mat2x3(f16vec3(1.0hf, 2.0hf, 3.0hf), f16vec3(4.0hf, 5.0hf, 6.0hf));
|
||||
}
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_ModuleConstant, Emit_GlobalConst_arr_f32) {
|
||||
auto* var = GlobalConst("G", nullptr, Construct(ty.array<f32, 3>(), 1_f, 2_f, 3_f));
|
||||
Func("f", {}, ty.void_(), {Decl(Let("l", nullptr, Expr(var)))});
|
||||
|
|
|
@ -105,6 +105,19 @@ TEST_F(GlslGeneratorImplTest_Type, EmitType_F32) {
|
|||
EXPECT_EQ(out.str(), "float");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_F16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* f16 = create<sem::F16>();
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
std::stringstream out;
|
||||
ASSERT_TRUE(gen.EmitType(out, f16, ast::StorageClass::kNone, ast::Access::kReadWrite, ""))
|
||||
<< gen.error();
|
||||
EXPECT_EQ(out.str(), "float16_t");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_I32) {
|
||||
auto* i32 = create<sem::I32>();
|
||||
|
||||
|
@ -116,7 +129,7 @@ TEST_F(GlslGeneratorImplTest_Type, EmitType_I32) {
|
|||
EXPECT_EQ(out.str(), "int");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_Matrix) {
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_Matrix_F32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec3 = create<sem::Vector>(f32, 3u);
|
||||
auto* mat2x3 = create<sem::Matrix>(vec3, 2u);
|
||||
|
@ -129,6 +142,21 @@ TEST_F(GlslGeneratorImplTest_Type, EmitType_Matrix) {
|
|||
EXPECT_EQ(out.str(), "mat2x3");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_Matrix_F16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* f16 = create<sem::F16>();
|
||||
auto* vec3 = create<sem::Vector>(f16, 3u);
|
||||
auto* mat2x3 = create<sem::Matrix>(vec3, 2u);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
std::stringstream out;
|
||||
ASSERT_TRUE(gen.EmitType(out, mat2x3, ast::StorageClass::kNone, ast::Access::kReadWrite, ""))
|
||||
<< gen.error();
|
||||
EXPECT_EQ(out.str(), "f16mat2x3");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_StructDecl) {
|
||||
auto* s = Structure("S", {
|
||||
Member("a", ty.i32()),
|
||||
|
@ -213,7 +241,7 @@ TEST_F(GlslGeneratorImplTest_Type, EmitType_U32) {
|
|||
EXPECT_EQ(out.str(), "uint");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_Vector) {
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_Vector_F32) {
|
||||
auto* f32 = create<sem::F32>();
|
||||
auto* vec3 = create<sem::Vector>(f32, 3u);
|
||||
|
||||
|
@ -225,6 +253,20 @@ TEST_F(GlslGeneratorImplTest_Type, EmitType_Vector) {
|
|||
EXPECT_EQ(out.str(), "vec3");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_Vector_F16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* f16 = create<sem::F16>();
|
||||
auto* vec3 = create<sem::Vector>(f16, 3u);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
std::stringstream out;
|
||||
ASSERT_TRUE(gen.EmitType(out, vec3, ast::StorageClass::kNone, ast::Access::kReadWrite, ""))
|
||||
<< gen.error();
|
||||
EXPECT_EQ(out.str(), "f16vec3");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Type, EmitType_Void) {
|
||||
auto* void_ = create<sem::Void>();
|
||||
|
||||
|
|
|
@ -149,6 +149,26 @@ void f() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* C = Const("C", nullptr, Expr(1_h));
|
||||
Func("f", {}, ty.void_(), {Decl(C), Decl(Let("l", nullptr, Expr(C)))});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_EQ(gen.result(), R"(#version 310 es
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
|
||||
void f() {
|
||||
float16_t l = 1.0hf;
|
||||
}
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_AInt) {
|
||||
auto* C = Const("C", nullptr, Construct(ty.vec3(nullptr), 1_a, 2_a, 3_a));
|
||||
Func("f", {}, ty.void_(), {Decl(C), Decl(Let("l", nullptr, Expr(C)))});
|
||||
|
@ -200,6 +220,26 @@ void f() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_vec3_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* C = Const("C", nullptr, vec3<f16>(1_h, 2_h, 3_h));
|
||||
Func("f", {}, ty.void_(), {Decl(C), Decl(Let("l", nullptr, Expr(C)))});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_EQ(gen.result(), R"(#version 310 es
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
|
||||
void f() {
|
||||
f16vec3 l = f16vec3(1.0hf, 2.0hf, 3.0hf);
|
||||
}
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_mat2x3_AFloat) {
|
||||
auto* C =
|
||||
Const("C", nullptr, Construct(ty.mat(nullptr, 2, 3), 1._a, 2._a, 3._a, 4._a, 5._a, 6._a));
|
||||
|
@ -235,6 +275,26 @@ void f() {
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_mat2x3_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* C = Const("C", nullptr, mat2x3<f16>(1_h, 2_h, 3_h, 4_h, 5_h, 6_h));
|
||||
Func("f", {}, ty.void_(), {Decl(C), Decl(Let("l", nullptr, Expr(C)))});
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
|
||||
EXPECT_EQ(gen.result(), R"(#version 310 es
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
|
||||
void f() {
|
||||
f16mat2x3 l = f16mat2x3(f16vec3(1.0hf, 2.0hf, 3.0hf), f16vec3(4.0hf, 5.0hf, 6.0hf));
|
||||
}
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const_arr_f32) {
|
||||
auto* C = Const("C", nullptr, Construct(ty.array<f32, 3>(), 1_f, 2_f, 3_f));
|
||||
Func("f", {}, ty.void_(), {Decl(C), Decl(Let("l", nullptr, Expr(C)))});
|
||||
|
@ -300,7 +360,7 @@ TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Private) {
|
|||
EXPECT_THAT(gen.result(), HasSubstr(" float a = 0.0f;\n"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroVec) {
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroVec_f32) {
|
||||
auto* var = Var("a", ty.vec3<f32>(), ast::StorageClass::kNone, vec3<f32>());
|
||||
|
||||
auto* stmt = Decl(var);
|
||||
|
@ -313,7 +373,22 @@ TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initialize
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroMat) {
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroVec_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* var = Var("a", ty.vec3<f16>(), ast::StorageClass::kNone, vec3<f16>());
|
||||
|
||||
auto* stmt = Decl(var);
|
||||
WrapInFunction(stmt);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error();
|
||||
EXPECT_EQ(gen.result(), R"(f16vec3 a = f16vec3(0.0hf);
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroMat_f32) {
|
||||
auto* var = Var("a", ty.mat2x3<f32>(), ast::StorageClass::kNone, mat2x3<f32>());
|
||||
|
||||
auto* stmt = Decl(var);
|
||||
|
@ -327,5 +402,21 @@ TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initialize
|
|||
)");
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Initializer_ZeroMat_f16) {
|
||||
Enable(ast::Extension::kF16);
|
||||
|
||||
auto* var = Var("a", ty.mat2x3<f16>(), ast::StorageClass::kNone, mat2x3<f16>());
|
||||
|
||||
auto* stmt = Decl(var);
|
||||
WrapInFunction(stmt);
|
||||
|
||||
GeneratorImpl& gen = Build();
|
||||
|
||||
ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error();
|
||||
EXPECT_EQ(gen.result(),
|
||||
R"(f16mat2x3 a = f16mat2x3(f16vec3(0.0hf), f16vec3(0.0hf));
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace tint::writer::glsl
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#version 310 es
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
precision mediump float;
|
||||
|
||||
layout(location = 0) out vec4 value;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#version 310 es
|
||||
#extension GL_AMD_gpu_shader_half_float : require
|
||||
precision mediump float;
|
||||
|
||||
layout(location = 0) out vec4 value;
|
||||
|
|
Loading…
Reference in New Issue