writer/hlsl: Implement isNormal

Change-Id: I5e5aa81db686b0205ffbf157542c0e85f28b5d5d
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/54323
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
Ben Clayton 2021-06-16 09:19:36 +00:00 committed by Ben Clayton
parent 9ef52ffd8c
commit 35ce0d1993
7 changed files with 127 additions and 66 deletions

View File

@ -535,8 +535,7 @@ bool GeneratorImpl::EmitCall(std::ostream& pre,
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;
return EmitIsNormalCall(pre, out, expr, intrinsic);
} else if (intrinsic->Type() == sem::IntrinsicType::kIgnore) {
return EmitExpression(pre, out, expr->params()[0]);
} else if (intrinsic->IsDataPacking()) {
@ -670,6 +669,44 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& pre,
return true;
}
bool GeneratorImpl::EmitIsNormalCall(std::ostream& pre,
std::ostream& out,
ast::CallExpression* expr,
const sem::Intrinsic* intrinsic) {
// HLSL doesn't have a isNormal intrinsic, we need to emulate
auto input = intrinsic->Parameters()[0];
std::string width;
if (auto* vec = input.type->As<sem::Vector>()) {
width = std::to_string(vec->size());
}
constexpr auto* kExponentMask = "0x7f80000";
constexpr auto* kMinNormalExponent = "0x0080000";
constexpr auto* kMaxNormalExponent = "0x7f00000";
auto exponent = generate_name("tint_isnormal_exponent");
auto clamped = generate_name("tint_isnormal_clamped");
std::stringstream ss;
ss << "uint" << width << " " << exponent << " = asuint(";
if (!EmitExpression(pre, ss, expr->params()[0])) {
return false;
}
ss << ") & " << kExponentMask << ";";
make_indent(ss << std::endl);
ss << "uint" << width << " " << clamped << " = "
<< "clamp(" << exponent << ", " << kMinNormalExponent << ", "
<< kMaxNormalExponent << ");";
make_indent(ss << std::endl);
pre << ss.str();
out << "(" << clamped << " == " << exponent << ")";
return true;
}
bool GeneratorImpl::EmitDataPackingCall(std::ostream& pre,
std::ostream& out,
ast::CallExpression* expr,

View File

@ -152,6 +152,16 @@ class GeneratorImpl : public TextGenerator {
std::ostream& out,
ast::CallExpression* expr,
const sem::Intrinsic* intrinsic);
/// Handles generating a call to the `isNormal()` 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 EmitIsNormalCall(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

View File

@ -347,6 +347,36 @@ TEST_F(HlslGeneratorImplTest_Intrinsic, Frexp_Vector_i32) {
)"));
}
TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Scalar) {
auto* val = Var("val", ty.f32());
auto* call = Call("isNormal", val);
WrapInFunction(val, call);
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate(out)) << gen.error();
EXPECT_THAT(result(), HasSubstr(R"(
uint tint_isnormal_exponent = asuint(val) & 0x7f80000;
uint tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
(tint_isnormal_clamped == tint_isnormal_exponent);
)"));
}
TEST_F(HlslGeneratorImplTest_Intrinsic, IsNormal_Vector) {
auto* val = Var("val", ty.vec3<f32>());
auto* call = Call("isNormal", val);
WrapInFunction(val, call);
GeneratorImpl& gen = SanitizeAndBuild();
ASSERT_TRUE(gen.Generate(out)) << gen.error();
EXPECT_THAT(result(), HasSubstr(R"(
uint3 tint_isnormal_exponent = asuint(val) & 0x7f80000;
uint3 tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
(tint_isnormal_clamped == tint_isnormal_exponent);
)"));
}
TEST_F(HlslGeneratorImplTest_Intrinsic, Pack4x8Snorm) {
auto* call = Call("pack4x8snorm", "p1");
Global("p1", ty.vec4<f32>(), ast::StorageClass::kPrivate);

View File

@ -1,30 +1,26 @@
SKIP: FAILED
fn isNormal_863dcd() {
var res : vec4<bool> = isNormal(vec4<f32>());
void isNormal_863dcd() {
uint4 tint_isnormal_exponent = asuint(float4(0.0f, 0.0f, 0.0f, 0.0f)) & 0x7f80000;
uint4 tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
bool4 res = (tint_isnormal_clamped == tint_isnormal_exponent);
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
float4 value : SV_Position;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
tint_symbol vertex_main() {
isNormal_863dcd();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
const tint_symbol tint_symbol_1 = {float4(0.0f, 0.0f, 0.0f, 0.0f)};
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
void fragment_main() {
isNormal_863dcd();
return;
}
[[stage(compute)]]
fn compute_main() {
[numthreads(1, 1, 1)]
void compute_main() {
isNormal_863dcd();
return;
}
Failed to generate: error: is_normal not supported in HLSL backend yet

View File

@ -1,30 +1,26 @@
SKIP: FAILED
fn isNormal_b00ab1() {
var res : vec2<bool> = isNormal(vec2<f32>());
void isNormal_b00ab1() {
uint2 tint_isnormal_exponent = asuint(float2(0.0f, 0.0f)) & 0x7f80000;
uint2 tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
bool2 res = (tint_isnormal_clamped == tint_isnormal_exponent);
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
float4 value : SV_Position;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
tint_symbol vertex_main() {
isNormal_b00ab1();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
const tint_symbol tint_symbol_1 = {float4(0.0f, 0.0f, 0.0f, 0.0f)};
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
void fragment_main() {
isNormal_b00ab1();
return;
}
[[stage(compute)]]
fn compute_main() {
[numthreads(1, 1, 1)]
void compute_main() {
isNormal_b00ab1();
return;
}
Failed to generate: error: is_normal not supported in HLSL backend yet

View File

@ -1,30 +1,26 @@
SKIP: FAILED
fn isNormal_c286b7() {
var res : vec3<bool> = isNormal(vec3<f32>());
void isNormal_c286b7() {
uint3 tint_isnormal_exponent = asuint(float3(0.0f, 0.0f, 0.0f)) & 0x7f80000;
uint3 tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
bool3 res = (tint_isnormal_clamped == tint_isnormal_exponent);
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
float4 value : SV_Position;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
tint_symbol vertex_main() {
isNormal_c286b7();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
const tint_symbol tint_symbol_1 = {float4(0.0f, 0.0f, 0.0f, 0.0f)};
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
void fragment_main() {
isNormal_c286b7();
return;
}
[[stage(compute)]]
fn compute_main() {
[numthreads(1, 1, 1)]
void compute_main() {
isNormal_c286b7();
return;
}
Failed to generate: error: is_normal not supported in HLSL backend yet

View File

@ -1,30 +1,26 @@
SKIP: FAILED
fn isNormal_c6e880() {
var res : bool = isNormal(1.0);
void isNormal_c6e880() {
uint tint_isnormal_exponent = asuint(1.0f) & 0x7f80000;
uint tint_isnormal_clamped = clamp(tint_isnormal_exponent, 0x0080000, 0x7f00000);
bool res = (tint_isnormal_clamped == tint_isnormal_exponent);
}
struct tint_symbol {
[[builtin(position)]]
value : vec4<f32>;
float4 value : SV_Position;
};
[[stage(vertex)]]
fn vertex_main() -> tint_symbol {
tint_symbol vertex_main() {
isNormal_c6e880();
let tint_symbol_1 : tint_symbol = tint_symbol(vec4<f32>());
const tint_symbol tint_symbol_1 = {float4(0.0f, 0.0f, 0.0f, 0.0f)};
return tint_symbol_1;
}
[[stage(fragment)]]
fn fragment_main() {
void fragment_main() {
isNormal_c6e880();
return;
}
[[stage(compute)]]
fn compute_main() {
[numthreads(1, 1, 1)]
void compute_main() {
isNormal_c6e880();
return;
}
Failed to generate: error: is_normal not supported in HLSL backend yet