mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-14 15:46:28 +00:00
hlsl: Implement modf and frexp
Change-Id: I40b3ad7e2d4811b0a52e75402c7d5ccda090a97c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/53809 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
@@ -586,6 +586,9 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kSelect) {
|
||||
return EmitSelectCall(pre, out, expr);
|
||||
}
|
||||
if (intrinsic->Type() == sem::IntrinsicType::kFrexp) {
|
||||
return EmitFrexpCall(pre, out, expr, intrinsic);
|
||||
} else if (intrinsic->Type() == sem::IntrinsicType::kIsNormal) {
|
||||
diagnostics_.add_error("is_normal not supported in HLSL backend yet");
|
||||
return false;
|
||||
@@ -701,6 +704,52 @@ bool GeneratorImpl::EmitSelectCall(std::ostream& pre,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitFrexpCall(std::ostream& pre,
|
||||
std::ostream& out,
|
||||
ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
// Exponent is an integer in WGSL, but HLSL wants a float.
|
||||
// We need to make the call with a temporary float, and then cast.
|
||||
|
||||
auto signficand = intrinsic->Parameters()[0];
|
||||
auto exponent = intrinsic->Parameters()[1];
|
||||
|
||||
std::string width;
|
||||
if (auto* vec = signficand.type->As<sem::Vector>()) {
|
||||
width = std::to_string(vec->size());
|
||||
}
|
||||
|
||||
// Exponent is an integer, which HLSL does not have an overload for.
|
||||
// We need to cast from a float.
|
||||
std::stringstream ss;
|
||||
auto float_exp = generate_name(kTempNamePrefix);
|
||||
ss << "float" << width << " " << float_exp << ";";
|
||||
|
||||
make_indent(ss << std::endl);
|
||||
auto significand = generate_name(kTempNamePrefix);
|
||||
ss << "float" << width << " " << significand << " = frexp(";
|
||||
if (!EmitExpression(pre, ss, expr->params()[0])) {
|
||||
return false;
|
||||
}
|
||||
ss << ", " << float_exp << ");";
|
||||
|
||||
make_indent(ss << std::endl);
|
||||
if (!EmitExpression(pre, ss, expr->params()[1])) {
|
||||
return false;
|
||||
}
|
||||
ss << " = ";
|
||||
if (!EmitType(ss, exponent.type->UnwrapPtr(), ast::StorageClass::kNone,
|
||||
ast::Access::kUndefined, "")) {
|
||||
return false;
|
||||
}
|
||||
ss << "(" << float_exp << ");";
|
||||
|
||||
make_indent(ss << std::endl);
|
||||
pre << ss.str();
|
||||
out << significand;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitDataPackingCall(std::ostream& pre,
|
||||
std::ostream& out,
|
||||
ast::CallExpression* expr,
|
||||
@@ -1150,13 +1199,15 @@ std::string GeneratorImpl::generate_builtin_name(
|
||||
const sem::Intrinsic* intrinsic) {
|
||||
std::string out;
|
||||
switch (intrinsic->Type()) {
|
||||
case sem::IntrinsicType::kAbs:
|
||||
case sem::IntrinsicType::kAcos:
|
||||
case sem::IntrinsicType::kAny:
|
||||
case sem::IntrinsicType::kAll:
|
||||
case sem::IntrinsicType::kAny:
|
||||
case sem::IntrinsicType::kAsin:
|
||||
case sem::IntrinsicType::kAtan:
|
||||
case sem::IntrinsicType::kAtan2:
|
||||
case sem::IntrinsicType::kCeil:
|
||||
case sem::IntrinsicType::kClamp:
|
||||
case sem::IntrinsicType::kCos:
|
||||
case sem::IntrinsicType::kCosh:
|
||||
case sem::IntrinsicType::kCross:
|
||||
@@ -1167,14 +1218,19 @@ std::string GeneratorImpl::generate_builtin_name(
|
||||
case sem::IntrinsicType::kExp2:
|
||||
case sem::IntrinsicType::kFloor:
|
||||
case sem::IntrinsicType::kFma:
|
||||
case sem::IntrinsicType::kFrexp:
|
||||
case sem::IntrinsicType::kLdexp:
|
||||
case sem::IntrinsicType::kLength:
|
||||
case sem::IntrinsicType::kLog:
|
||||
case sem::IntrinsicType::kLog2:
|
||||
case sem::IntrinsicType::kMax:
|
||||
case sem::IntrinsicType::kMin:
|
||||
case sem::IntrinsicType::kModf:
|
||||
case sem::IntrinsicType::kNormalize:
|
||||
case sem::IntrinsicType::kPow:
|
||||
case sem::IntrinsicType::kReflect:
|
||||
case sem::IntrinsicType::kRound:
|
||||
case sem::IntrinsicType::kSign:
|
||||
case sem::IntrinsicType::kSin:
|
||||
case sem::IntrinsicType::kSinh:
|
||||
case sem::IntrinsicType::kSqrt:
|
||||
@@ -1183,11 +1239,6 @@ std::string GeneratorImpl::generate_builtin_name(
|
||||
case sem::IntrinsicType::kTanh:
|
||||
case sem::IntrinsicType::kTranspose:
|
||||
case sem::IntrinsicType::kTrunc:
|
||||
case sem::IntrinsicType::kSign:
|
||||
case sem::IntrinsicType::kAbs:
|
||||
case sem::IntrinsicType::kMax:
|
||||
case sem::IntrinsicType::kMin:
|
||||
case sem::IntrinsicType::kClamp:
|
||||
out = intrinsic->str();
|
||||
break;
|
||||
case sem::IntrinsicType::kCountOneBits:
|
||||
|
||||
@@ -139,7 +139,6 @@ class GeneratorImpl : public TextGenerator {
|
||||
std::ostream& out,
|
||||
ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
|
||||
/// Handles generating a call to the `select()` intrinsic
|
||||
/// @param pre the preamble of the expression stream
|
||||
/// @param out the output of the expression stream
|
||||
@@ -148,7 +147,16 @@ class GeneratorImpl : public TextGenerator {
|
||||
bool EmitSelectCall(std::ostream& pre,
|
||||
std::ostream& out,
|
||||
ast::CallExpression* expr);
|
||||
|
||||
/// Handles generating a call to the `frexp()` intrinsic
|
||||
/// @param pre the preamble of the expression stream
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param intrinsic the semantic information for the intrinsic
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitFrexpCall(std::ostream& pre,
|
||||
std::ostream& out,
|
||||
ast::CallExpression* expr,
|
||||
const sem::Intrinsic* intrinsic);
|
||||
/// Handles generating a call to data packing intrinsic
|
||||
/// @param pre the preamble of the expression stream
|
||||
/// @param out the output of the expression stream
|
||||
|
||||
@@ -257,10 +257,6 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_IsNormal) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, DISABLED_Intrinsic_Select) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Call) {
|
||||
auto* call = Call("dot", "param1", "param2");
|
||||
|
||||
@@ -297,6 +293,60 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Select_Vector) {
|
||||
EXPECT_EQ(result(), "(bool2(true, false) ? int2(1, 2) : int2(3, 4))");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Scalar) {
|
||||
auto* res = Var("res", ty.f32());
|
||||
auto* call = Call("modf", 1.0f, AddressOf(res));
|
||||
WrapInFunction(res, call);
|
||||
|
||||
GeneratorImpl& gen = SanitizeAndBuild();
|
||||
|
||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
||||
EXPECT_THAT(result(), HasSubstr("modf(1.0f, res)"));
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Modf_Vector) {
|
||||
auto* res = Var("res", ty.vec3<f32>());
|
||||
auto* call = Call("modf", vec3<f32>(), AddressOf(res));
|
||||
WrapInFunction(res, call);
|
||||
|
||||
GeneratorImpl& gen = SanitizeAndBuild();
|
||||
|
||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
||||
EXPECT_THAT(result(), HasSubstr("modf(float3(0.0f, 0.0f, 0.0f), res)"));
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Scalar_i32) {
|
||||
auto* exp = Var("exp", ty.i32());
|
||||
auto* call = Call("frexp", 1.0f, AddressOf(exp));
|
||||
WrapInFunction(exp, call);
|
||||
|
||||
GeneratorImpl& gen = SanitizeAndBuild();
|
||||
|
||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
||||
EXPECT_THAT(result(), HasSubstr(R"(
|
||||
float tint_tmp;
|
||||
float tint_tmp_1 = frexp(1.0f, tint_tmp);
|
||||
exp = int(tint_tmp);
|
||||
(void) tint_tmp_1;
|
||||
)"));
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) {
|
||||
auto* res = Var("res", ty.vec3<i32>());
|
||||
auto* call = Call("frexp", vec3<f32>(), AddressOf(res));
|
||||
WrapInFunction(res, call);
|
||||
|
||||
GeneratorImpl& gen = SanitizeAndBuild();
|
||||
|
||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
||||
EXPECT_THAT(result(), HasSubstr(R"(
|
||||
float3 tint_tmp;
|
||||
float3 tint_tmp_1 = frexp(float3(0.0f, 0.0f, 0.0f), tint_tmp);
|
||||
res = int3(tint_tmp);
|
||||
(void) tint_tmp_1;
|
||||
)"));
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) {
|
||||
auto* call = Call("pack4x8snorm", "p1");
|
||||
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);
|
||||
|
||||
Reference in New Issue
Block a user