mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-11 14:41:50 +00:00
Remove isNan, isInf, isFinite, and isNormal
These were deprecated in M98. Fixed: tint:1312 Change-Id: Ieec17bfcc729f90d0a9aa8904a162167b9de54ed Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/82800 Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: James Price <jrprice@google.com>
This commit is contained in:
committed by
Tint LUCI CQ
parent
e228319549
commit
bcd9ad2ebb
File diff suppressed because it is too large
Load Diff
@@ -340,14 +340,6 @@ fn insertBits<T: iu32>(T, T, u32, u32) -> T
|
||||
fn insertBits<N: num, T: iu32>(vec<N, T>, vec<N, T>, u32, u32) -> vec<N, T>
|
||||
fn inverseSqrt(f32) -> f32
|
||||
fn inverseSqrt<N: num>(vec<N, f32>) -> vec<N, f32>
|
||||
[[deprecated]] fn isFinite(f32) -> bool
|
||||
[[deprecated]] fn isFinite<N: num>(vec<N, f32>) -> vec<N, bool>
|
||||
[[deprecated]] fn isInf(f32) -> bool
|
||||
[[deprecated]] fn isInf<N: num>(vec<N, f32>) -> vec<N, bool>
|
||||
[[deprecated]] fn isNan(f32) -> bool
|
||||
[[deprecated]] fn isNan<N: num>(vec<N, f32>) -> vec<N, bool>
|
||||
[[deprecated]] fn isNormal(f32) -> bool
|
||||
[[deprecated]] fn isNormal<N: num>(vec<N, f32>) -> vec<N, bool>
|
||||
fn ldexp(f32, i32) -> f32
|
||||
fn ldexp<N: num>(vec<N, f32>, vec<N, i32>) -> vec<N, f32>
|
||||
fn length(f32) -> f32
|
||||
|
||||
@@ -138,75 +138,6 @@ INSTANTIATE_TEST_SUITE_P(ResolverTest,
|
||||
ResolverBuiltinTest_BoolMethod,
|
||||
testing::Values("any", "all"));
|
||||
|
||||
using ResolverBuiltinTest_FloatMethod = ResolverTestWithParam<std::string>;
|
||||
TEST_P(ResolverBuiltinTest_FloatMethod, Vector) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
|
||||
auto* expr = Call(name, "my_var");
|
||||
WrapInFunction(expr);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(expr), nullptr);
|
||||
ASSERT_TRUE(TypeOf(expr)->Is<sem::Vector>());
|
||||
EXPECT_TRUE(TypeOf(expr)->As<sem::Vector>()->type()->Is<sem::Bool>());
|
||||
EXPECT_EQ(TypeOf(expr)->As<sem::Vector>()->Width(), 3u);
|
||||
}
|
||||
|
||||
TEST_P(ResolverBuiltinTest_FloatMethod, Scalar) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("my_var", ty.f32(), ast::StorageClass::kPrivate);
|
||||
|
||||
auto* expr = Call(name, "my_var");
|
||||
WrapInFunction(expr);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
ASSERT_NE(TypeOf(expr), nullptr);
|
||||
EXPECT_TRUE(TypeOf(expr)->Is<sem::Bool>());
|
||||
}
|
||||
|
||||
TEST_P(ResolverBuiltinTest_FloatMethod, MissingParam) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("my_var", ty.f32(), ast::StorageClass::kPrivate);
|
||||
|
||||
auto* expr = Call(name);
|
||||
WrapInFunction(expr);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
EXPECT_EQ(r()->error(), "error: no matching call to " + name +
|
||||
"()\n\n"
|
||||
"2 candidate functions:\n " +
|
||||
name + "(f32) -> bool\n " + name +
|
||||
"(vecN<f32>) -> vecN<bool>\n");
|
||||
}
|
||||
|
||||
TEST_P(ResolverBuiltinTest_FloatMethod, TooManyParams) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("my_var", ty.f32(), ast::StorageClass::kPrivate);
|
||||
|
||||
auto* expr = Call(name, "my_var", 1.23f);
|
||||
WrapInFunction(expr);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
EXPECT_EQ(r()->error(), "error: no matching call to " + name +
|
||||
"(f32, f32)\n\n"
|
||||
"2 candidate functions:\n " +
|
||||
name + "(f32) -> bool\n " + name +
|
||||
"(vecN<f32>) -> vecN<bool>\n");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
ResolverTest,
|
||||
ResolverBuiltinTest_FloatMethod,
|
||||
testing::Values("isInf", "isNan", "isFinite", "isNormal"));
|
||||
|
||||
enum class Texture { kF32, kI32, kU32 };
|
||||
inline std::ostream& operator<<(std::ostream& out, Texture data) {
|
||||
if (data == Texture::kF32) {
|
||||
|
||||
@@ -46,11 +46,6 @@ bool IsDerivativeBuiltin(BuiltinType i) {
|
||||
IsFineDerivativeBuiltin(i);
|
||||
}
|
||||
|
||||
bool IsFloatClassificationBuiltin(BuiltinType i) {
|
||||
return i == BuiltinType::kIsFinite || i == BuiltinType::kIsInf ||
|
||||
i == BuiltinType::kIsNan || i == BuiltinType::kIsNormal;
|
||||
}
|
||||
|
||||
bool IsTextureBuiltin(BuiltinType i) {
|
||||
return IsImageQueryBuiltin(i) || i == BuiltinType::kTextureLoad ||
|
||||
i == BuiltinType::kTextureGather ||
|
||||
@@ -132,10 +127,6 @@ bool Builtin::IsDerivative() const {
|
||||
return IsDerivativeBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsFloatClassification() const {
|
||||
return IsFloatClassificationBuiltin(type_);
|
||||
}
|
||||
|
||||
bool Builtin::IsTexture() const {
|
||||
return IsTextureBuiltin(type_);
|
||||
}
|
||||
|
||||
@@ -41,11 +41,6 @@ bool IsFineDerivativeBuiltin(BuiltinType i);
|
||||
/// @returns true if the given `i` is a derivative builtin
|
||||
bool IsDerivativeBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a float classification builtin
|
||||
/// @param i the builtin type
|
||||
/// @returns true if the given `i` is a float builtin
|
||||
bool IsFloatClassificationBuiltin(BuiltinType i);
|
||||
|
||||
/// Determines if the given `i` is a texture operation builtin
|
||||
/// @param i the builtin type
|
||||
/// @returns true if the given `i` is a texture operation builtin
|
||||
@@ -118,9 +113,6 @@ class Builtin : public Castable<Builtin, CallTarget> {
|
||||
/// @returns true if builtin is a derivative builtin
|
||||
bool IsDerivative() const;
|
||||
|
||||
/// @returns true if builtin is a float builtin
|
||||
bool IsFloatClassification() const;
|
||||
|
||||
/// @returns true if builtin is a texture operation builtin
|
||||
bool IsTexture() const;
|
||||
|
||||
|
||||
@@ -75,10 +75,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
BuiltinData{"fwidthCoarse", BuiltinType::kFwidthCoarse},
|
||||
BuiltinData{"fwidthFine", BuiltinType::kFwidthFine},
|
||||
BuiltinData{"inverseSqrt", BuiltinType::kInverseSqrt},
|
||||
BuiltinData{"isFinite", BuiltinType::kIsFinite},
|
||||
BuiltinData{"isInf", BuiltinType::kIsInf},
|
||||
BuiltinData{"isNan", BuiltinType::kIsNan},
|
||||
BuiltinData{"isNormal", BuiltinType::kIsNormal},
|
||||
BuiltinData{"ldexp", BuiltinType::kLdexp},
|
||||
BuiltinData{"length", BuiltinType::kLength},
|
||||
BuiltinData{"log", BuiltinType::kLog},
|
||||
|
||||
@@ -153,18 +153,6 @@ BuiltinType ParseBuiltinType(const std::string& name) {
|
||||
if (name == "inverseSqrt") {
|
||||
return BuiltinType::kInverseSqrt;
|
||||
}
|
||||
if (name == "isFinite") {
|
||||
return BuiltinType::kIsFinite;
|
||||
}
|
||||
if (name == "isInf") {
|
||||
return BuiltinType::kIsInf;
|
||||
}
|
||||
if (name == "isNan") {
|
||||
return BuiltinType::kIsNan;
|
||||
}
|
||||
if (name == "isNormal") {
|
||||
return BuiltinType::kIsNormal;
|
||||
}
|
||||
if (name == "ldexp") {
|
||||
return BuiltinType::kLdexp;
|
||||
}
|
||||
@@ -443,14 +431,6 @@ const char* str(BuiltinType i) {
|
||||
return "insertBits";
|
||||
case BuiltinType::kInverseSqrt:
|
||||
return "inverseSqrt";
|
||||
case BuiltinType::kIsFinite:
|
||||
return "isFinite";
|
||||
case BuiltinType::kIsInf:
|
||||
return "isInf";
|
||||
case BuiltinType::kIsNan:
|
||||
return "isNan";
|
||||
case BuiltinType::kIsNormal:
|
||||
return "isNormal";
|
||||
case BuiltinType::kLdexp:
|
||||
return "ldexp";
|
||||
case BuiltinType::kLength:
|
||||
|
||||
@@ -75,10 +75,6 @@ enum class BuiltinType {
|
||||
kFwidthFine,
|
||||
kInsertBits,
|
||||
kInverseSqrt,
|
||||
kIsFinite,
|
||||
kIsInf,
|
||||
kIsNan,
|
||||
kIsNormal,
|
||||
kLdexp,
|
||||
kLength,
|
||||
kLog,
|
||||
|
||||
@@ -663,9 +663,6 @@ bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
|
||||
if (builtin->Type() == sem::BuiltinType::kFrexp) {
|
||||
return EmitFrexpCall(out, expr, builtin);
|
||||
}
|
||||
if (builtin->Type() == sem::BuiltinType::kIsNormal) {
|
||||
return EmitIsNormalCall(out, expr, builtin);
|
||||
}
|
||||
if (builtin->Type() == sem::BuiltinType::kDegrees) {
|
||||
return EmitDegreesCall(out, expr, builtin);
|
||||
}
|
||||
@@ -1191,40 +1188,6 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
||||
});
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Builtin* builtin) {
|
||||
// GLSL doesn't have a isNormal builtin, we need to emulate
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* input_ty = builtin->Parameters()[0]->Type();
|
||||
|
||||
std::string vec_type;
|
||||
if (auto* vec = input_ty->As<sem::Vector>()) {
|
||||
vec_type = "uvec" + std::to_string(vec->Width());
|
||||
} else {
|
||||
vec_type = "uint";
|
||||
}
|
||||
|
||||
constexpr auto* kExponentMask = "0x7f80000u";
|
||||
constexpr auto* kMinNormalExponent = "0x0080000u";
|
||||
constexpr auto* kMaxNormalExponent = "0x7f00000u";
|
||||
|
||||
line(b) << vec_type << " exponent = floatBitsToUint(" << params[0]
|
||||
<< ") & " << kExponentMask << ";";
|
||||
line(b) << vec_type << " clamped = "
|
||||
<< "clamp(exponent, " << kMinNormalExponent << ", "
|
||||
<< kMaxNormalExponent << ");";
|
||||
if (input_ty->Is<sem::Vector>()) {
|
||||
line(b) << "return equal(clamped, exponent);";
|
||||
} else {
|
||||
line(b) << "return clamped == exponent;";
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Builtin* builtin) {
|
||||
@@ -1625,12 +1588,6 @@ std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
|
||||
return "fwidth";
|
||||
case sem::BuiltinType::kInverseSqrt:
|
||||
return "inversesqrt";
|
||||
case sem::BuiltinType::kIsFinite:
|
||||
return "isfinite";
|
||||
case sem::BuiltinType::kIsInf:
|
||||
return "isinf";
|
||||
case sem::BuiltinType::kIsNan:
|
||||
return "isnan";
|
||||
case sem::BuiltinType::kMix:
|
||||
return "mix";
|
||||
case sem::BuiltinType::kPack2x16float:
|
||||
|
||||
@@ -239,14 +239,6 @@ class GeneratorImpl : public TextGenerator {
|
||||
bool EmitFrexpCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `isNormal()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitIsNormalCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `degrees()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
|
||||
@@ -84,10 +84,6 @@ const ast::CallExpression* GenerateCall(BuiltinType builtin,
|
||||
case BuiltinType::kFwidthCoarse:
|
||||
case BuiltinType::kFwidthFine:
|
||||
case BuiltinType::kInverseSqrt:
|
||||
case BuiltinType::kIsFinite:
|
||||
case BuiltinType::kIsInf:
|
||||
case BuiltinType::kIsNan:
|
||||
case BuiltinType::kIsNormal:
|
||||
case BuiltinType::kLength:
|
||||
case BuiltinType::kLog:
|
||||
case BuiltinType::kLog2:
|
||||
@@ -219,9 +215,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
BuiltinData{BuiltinType::kFwidthCoarse, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kFwidthFine, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kInverseSqrt, ParamType::kF32, "inversesqrt"},
|
||||
BuiltinData{BuiltinType::kIsFinite, ParamType::kF32, "isfinite"},
|
||||
BuiltinData{BuiltinType::kIsInf, ParamType::kF32, "isinf"},
|
||||
BuiltinData{BuiltinType::kIsNan, ParamType::kF32, "isnan"},
|
||||
BuiltinData{BuiltinType::kLdexp, ParamType::kF32, "ldexp"},
|
||||
BuiltinData{BuiltinType::kLength, ParamType::kF32, "length"},
|
||||
BuiltinData{BuiltinType::kLog, ParamType::kF32, "log"},
|
||||
@@ -248,10 +241,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
BuiltinData{BuiltinType::kTranspose, ParamType::kF32, "transpose"},
|
||||
BuiltinData{BuiltinType::kTrunc, ParamType::kF32, "trunc"}));
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, DISABLED_Builtin_IsNormal) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Builtin_Call) {
|
||||
auto* call = Call("dot", "param1", "param2");
|
||||
|
||||
@@ -416,62 +405,6 @@ void main() {
|
||||
)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, IsNormal_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("isNormal", val);
|
||||
WrapInFunction(val, call);
|
||||
|
||||
GeneratorImpl& gen = SanitizeAndBuild();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_THAT(gen.result(), HasSubstr(R"(ion 310 es
|
||||
|
||||
bool tint_isNormal(float param_0) {
|
||||
uint exponent = floatBitsToUint(param_0) & 0x7f80000u;
|
||||
uint clamped = clamp(exponent, 0x0080000u, 0x7f00000u);
|
||||
return clamped == exponent;
|
||||
}
|
||||
|
||||
|
||||
void test_function() {
|
||||
float val = 0.0f;
|
||||
bool tint_symbol = tint_isNormal(val);
|
||||
}
|
||||
|
||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
void main() {
|
||||
test_function();
|
||||
)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, IsNormal_Vector) {
|
||||
auto* val = Var("val", ty.vec3<f32>());
|
||||
auto* call = Call("isNormal", val);
|
||||
WrapInFunction(val, call);
|
||||
|
||||
GeneratorImpl& gen = SanitizeAndBuild();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_THAT(gen.result(), HasSubstr(R"( 310 es
|
||||
|
||||
bvec3 tint_isNormal(vec3 param_0) {
|
||||
uvec3 exponent = floatBitsToUint(param_0) & 0x7f80000u;
|
||||
uvec3 clamped = clamp(exponent, 0x0080000u, 0x7f00000u);
|
||||
return equal(clamped, exponent);
|
||||
}
|
||||
|
||||
|
||||
void test_function() {
|
||||
vec3 val = vec3(0.0f, 0.0f, 0.0f);
|
||||
bvec3 tint_symbol = tint_isNormal(val);
|
||||
}
|
||||
|
||||
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
|
||||
void main() {
|
||||
test_function();
|
||||
)"));
|
||||
}
|
||||
|
||||
TEST_F(GlslGeneratorImplTest_Builtin, Degrees_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("degrees", val);
|
||||
|
||||
@@ -1034,9 +1034,6 @@ bool GeneratorImpl::EmitBuiltinCall(std::ostream& out,
|
||||
if (builtin->Type() == sem::BuiltinType::kFrexp) {
|
||||
return EmitFrexpCall(out, expr, builtin);
|
||||
}
|
||||
if (builtin->Type() == sem::BuiltinType::kIsNormal) {
|
||||
return EmitIsNormalCall(out, expr, builtin);
|
||||
}
|
||||
if (builtin->Type() == sem::BuiltinType::kDegrees) {
|
||||
return EmitDegreesCall(out, expr, builtin);
|
||||
}
|
||||
@@ -1922,34 +1919,6 @@ bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
|
||||
});
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitIsNormalCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Builtin* builtin) {
|
||||
// HLSL doesn't have a isNormal builtin, we need to emulate
|
||||
return CallBuiltinHelper(
|
||||
out, expr, builtin,
|
||||
[&](TextBuffer* b, const std::vector<std::string>& params) {
|
||||
auto* input_ty = builtin->Parameters()[0]->Type();
|
||||
|
||||
std::string width;
|
||||
if (auto* vec = input_ty->As<sem::Vector>()) {
|
||||
width = std::to_string(vec->Width());
|
||||
}
|
||||
|
||||
constexpr auto* kExponentMask = "0x7f80000";
|
||||
constexpr auto* kMinNormalExponent = "0x0080000";
|
||||
constexpr auto* kMaxNormalExponent = "0x7f00000";
|
||||
|
||||
line(b) << "uint" << width << " exponent = asuint(" << params[0]
|
||||
<< ") & " << kExponentMask << ";";
|
||||
line(b) << "uint" << width << " clamped = "
|
||||
<< "clamp(exponent, " << kMinNormalExponent << ", "
|
||||
<< kMaxNormalExponent << ");";
|
||||
line(b) << "return clamped == exponent;";
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitDegreesCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Builtin* builtin) {
|
||||
@@ -2571,12 +2540,6 @@ std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
|
||||
return "fwidth";
|
||||
case sem::BuiltinType::kInverseSqrt:
|
||||
return "rsqrt";
|
||||
case sem::BuiltinType::kIsFinite:
|
||||
return "isfinite";
|
||||
case sem::BuiltinType::kIsInf:
|
||||
return "isinf";
|
||||
case sem::BuiltinType::kIsNan:
|
||||
return "isnan";
|
||||
case sem::BuiltinType::kMix:
|
||||
return "lerp";
|
||||
case sem::BuiltinType::kReverseBits:
|
||||
|
||||
@@ -241,14 +241,6 @@ class GeneratorImpl : public TextGenerator {
|
||||
bool EmitFrexpCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `isNormal()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
/// @param builtin the semantic information for the builtin
|
||||
/// @returns true if the call expression is emitted
|
||||
bool EmitIsNormalCall(std::ostream& out,
|
||||
const ast::CallExpression* expr,
|
||||
const sem::Builtin* builtin);
|
||||
/// Handles generating a call to the `degrees()` builtin
|
||||
/// @param out the output of the expression stream
|
||||
/// @param expr the call expression
|
||||
|
||||
@@ -84,10 +84,6 @@ const ast::CallExpression* GenerateCall(BuiltinType builtin,
|
||||
case BuiltinType::kFwidthCoarse:
|
||||
case BuiltinType::kFwidthFine:
|
||||
case BuiltinType::kInverseSqrt:
|
||||
case BuiltinType::kIsFinite:
|
||||
case BuiltinType::kIsInf:
|
||||
case BuiltinType::kIsNan:
|
||||
case BuiltinType::kIsNormal:
|
||||
case BuiltinType::kLength:
|
||||
case BuiltinType::kLog:
|
||||
case BuiltinType::kLog2:
|
||||
@@ -219,9 +215,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
BuiltinData{BuiltinType::kFwidthCoarse, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kFwidthFine, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kInverseSqrt, ParamType::kF32, "rsqrt"},
|
||||
BuiltinData{BuiltinType::kIsFinite, ParamType::kF32, "isfinite"},
|
||||
BuiltinData{BuiltinType::kIsInf, ParamType::kF32, "isinf"},
|
||||
BuiltinData{BuiltinType::kIsNan, ParamType::kF32, "isnan"},
|
||||
BuiltinData{BuiltinType::kLdexp, ParamType::kF32, "ldexp"},
|
||||
BuiltinData{BuiltinType::kLength, ParamType::kF32, "length"},
|
||||
BuiltinData{BuiltinType::kLog, ParamType::kF32, "log"},
|
||||
@@ -247,10 +240,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
BuiltinData{BuiltinType::kTranspose, ParamType::kF32, "transpose"},
|
||||
BuiltinData{BuiltinType::kTrunc, ParamType::kF32, "trunc"}));
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, DISABLED_Builtin_IsNormal) {
|
||||
FAIL();
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Builtin_Call) {
|
||||
auto* call = Call("dot", "param1", "param2");
|
||||
|
||||
@@ -394,52 +383,6 @@ void test_function() {
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, IsNormal_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("isNormal", val);
|
||||
WrapInFunction(val, call);
|
||||
|
||||
GeneratorImpl& gen = SanitizeAndBuild();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_EQ(gen.result(), R"(bool tint_isNormal(float param_0) {
|
||||
uint exponent = asuint(param_0) & 0x7f80000;
|
||||
uint clamped = clamp(exponent, 0x0080000, 0x7f00000);
|
||||
return clamped == exponent;
|
||||
}
|
||||
|
||||
[numthreads(1, 1, 1)]
|
||||
void test_function() {
|
||||
float val = 0.0f;
|
||||
const bool tint_symbol = tint_isNormal(val);
|
||||
return;
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, IsNormal_Vector) {
|
||||
auto* val = Var("val", ty.vec3<f32>());
|
||||
auto* call = Call("isNormal", val);
|
||||
WrapInFunction(val, call);
|
||||
|
||||
GeneratorImpl& gen = SanitizeAndBuild();
|
||||
|
||||
ASSERT_TRUE(gen.Generate()) << gen.error();
|
||||
EXPECT_EQ(gen.result(), R"(bool3 tint_isNormal(float3 param_0) {
|
||||
uint3 exponent = asuint(param_0) & 0x7f80000;
|
||||
uint3 clamped = clamp(exponent, 0x0080000, 0x7f00000);
|
||||
return clamped == exponent;
|
||||
}
|
||||
|
||||
[numthreads(1, 1, 1)]
|
||||
void test_function() {
|
||||
float3 val = float3(0.0f, 0.0f, 0.0f);
|
||||
const bool3 tint_symbol = tint_isNormal(val);
|
||||
return;
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(HlslGeneratorImplTest_Builtin, Degrees_Scalar) {
|
||||
auto* val = Var("val", ty.f32());
|
||||
auto* call = Call("degrees", val);
|
||||
|
||||
@@ -1385,18 +1385,6 @@ std::string GeneratorImpl::generate_builtin_name(const sem::Builtin* builtin) {
|
||||
case sem::BuiltinType::kFwidthFine:
|
||||
out += "fwidth";
|
||||
break;
|
||||
case sem::BuiltinType::kIsFinite:
|
||||
out += "isfinite";
|
||||
break;
|
||||
case sem::BuiltinType::kIsInf:
|
||||
out += "isinf";
|
||||
break;
|
||||
case sem::BuiltinType::kIsNan:
|
||||
out += "isnan";
|
||||
break;
|
||||
case sem::BuiltinType::kIsNormal:
|
||||
out += "isnormal";
|
||||
break;
|
||||
case sem::BuiltinType::kMax:
|
||||
if (builtin->ReturnType()->is_float_scalar_or_vector()) {
|
||||
out += "fmax";
|
||||
|
||||
@@ -80,10 +80,6 @@ const ast::CallExpression* GenerateCall(BuiltinType builtin,
|
||||
case BuiltinType::kFwidthCoarse:
|
||||
case BuiltinType::kFwidthFine:
|
||||
case BuiltinType::kInverseSqrt:
|
||||
case BuiltinType::kIsFinite:
|
||||
case BuiltinType::kIsInf:
|
||||
case BuiltinType::kIsNan:
|
||||
case BuiltinType::kIsNormal:
|
||||
case BuiltinType::kLength:
|
||||
case BuiltinType::kLog:
|
||||
case BuiltinType::kLog2:
|
||||
@@ -243,10 +239,6 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
BuiltinData{BuiltinType::kFwidthFine, ParamType::kF32, "fwidth"},
|
||||
BuiltinData{BuiltinType::kInsertBits, ParamType::kU32, "insert_bits"},
|
||||
BuiltinData{BuiltinType::kInverseSqrt, ParamType::kF32, "rsqrt"},
|
||||
BuiltinData{BuiltinType::kIsFinite, ParamType::kF32, "isfinite"},
|
||||
BuiltinData{BuiltinType::kIsInf, ParamType::kF32, "isinf"},
|
||||
BuiltinData{BuiltinType::kIsNan, ParamType::kF32, "isnan"},
|
||||
BuiltinData{BuiltinType::kIsNormal, ParamType::kF32, "isnormal"},
|
||||
BuiltinData{BuiltinType::kLdexp, ParamType::kF32, "ldexp"},
|
||||
BuiltinData{BuiltinType::kLength, ParamType::kF32, "length"},
|
||||
BuiltinData{BuiltinType::kLog, ParamType::kF32, "log"},
|
||||
|
||||
@@ -2527,116 +2527,6 @@ uint32_t Builder::GenerateBuiltinCall(const sem::Call* call,
|
||||
case BuiltinType::kInsertBits:
|
||||
op = spv::Op::OpBitFieldInsert;
|
||||
break;
|
||||
case BuiltinType::kIsInf:
|
||||
op = spv::Op::OpIsInf;
|
||||
break;
|
||||
case BuiltinType::kIsNan:
|
||||
op = spv::Op::OpIsNan;
|
||||
break;
|
||||
case BuiltinType::kIsFinite: {
|
||||
// Implemented as: not(IsInf or IsNan)
|
||||
auto val_id = get_arg_as_value_id(0);
|
||||
if (!val_id) {
|
||||
return 0;
|
||||
}
|
||||
auto inf_result = result_op();
|
||||
auto nan_result = result_op();
|
||||
auto or_result = result_op();
|
||||
if (push_function_inst(spv::Op::OpIsInf,
|
||||
{Operand::Int(result_type_id), inf_result,
|
||||
Operand::Int(val_id)}) &&
|
||||
push_function_inst(spv::Op::OpIsNan,
|
||||
{Operand::Int(result_type_id), nan_result,
|
||||
Operand::Int(val_id)}) &&
|
||||
push_function_inst(spv::Op::OpLogicalOr,
|
||||
{Operand::Int(result_type_id), or_result,
|
||||
Operand::Int(inf_result.to_i()),
|
||||
Operand::Int(nan_result.to_i())}) &&
|
||||
push_function_inst(spv::Op::OpLogicalNot,
|
||||
{Operand::Int(result_type_id), result,
|
||||
Operand::Int(or_result.to_i())})) {
|
||||
return result_id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case BuiltinType::kIsNormal: {
|
||||
// A normal number is finite, non-zero, and not subnormal.
|
||||
// Its exponent is neither of the extreme possible values.
|
||||
// Implemented as:
|
||||
// exponent_bits = bitcast<u32>(f);
|
||||
// clamped = uclamp(1,254,exponent_bits);
|
||||
// result = (clamped == exponent_bits);
|
||||
//
|
||||
auto val_id = get_arg_as_value_id(0);
|
||||
if (!val_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// These parameters are valid for IEEE 754 binary32
|
||||
const uint32_t kExponentMask = 0x7f80000;
|
||||
const uint32_t kMinNormalExponent = 0x0080000;
|
||||
const uint32_t kMaxNormalExponent = 0x7f00000;
|
||||
|
||||
auto set_id = GetGLSLstd450Import();
|
||||
auto* u32 = builder_.create<sem::U32>();
|
||||
|
||||
auto unsigned_id = GenerateTypeIfNeeded(u32);
|
||||
auto exponent_mask_id =
|
||||
GenerateConstantIfNeeded(ScalarConstant::U32(kExponentMask));
|
||||
auto min_exponent_id =
|
||||
GenerateConstantIfNeeded(ScalarConstant::U32(kMinNormalExponent));
|
||||
auto max_exponent_id =
|
||||
GenerateConstantIfNeeded(ScalarConstant::U32(kMaxNormalExponent));
|
||||
if (auto* fvec_ty = builtin->ReturnType()->As<sem::Vector>()) {
|
||||
// In the vector case, update the unsigned type to a vector type of the
|
||||
// same size, and create vector constants by replicating the scalars.
|
||||
// I expect backend compilers to fold these into unique constants, so
|
||||
// there is no loss of efficiency.
|
||||
auto* uvec_ty = builder_.create<sem::Vector>(u32, fvec_ty->Width());
|
||||
unsigned_id = GenerateTypeIfNeeded(uvec_ty);
|
||||
auto splat = [&](uint32_t scalar_id) -> uint32_t {
|
||||
auto splat_result = result_op();
|
||||
OperandList splat_params{Operand::Int(unsigned_id), splat_result};
|
||||
for (size_t i = 0; i < fvec_ty->Width(); i++) {
|
||||
splat_params.emplace_back(Operand::Int(scalar_id));
|
||||
}
|
||||
if (!push_function_inst(spv::Op::OpCompositeConstruct,
|
||||
std::move(splat_params))) {
|
||||
return 0;
|
||||
}
|
||||
return splat_result.to_i();
|
||||
};
|
||||
exponent_mask_id = splat(exponent_mask_id);
|
||||
min_exponent_id = splat(min_exponent_id);
|
||||
max_exponent_id = splat(max_exponent_id);
|
||||
}
|
||||
auto cast_result = result_op();
|
||||
auto exponent_bits_result = result_op();
|
||||
auto clamp_result = result_op();
|
||||
|
||||
if (set_id && unsigned_id && exponent_mask_id && min_exponent_id &&
|
||||
max_exponent_id &&
|
||||
push_function_inst(
|
||||
spv::Op::OpBitcast,
|
||||
{Operand::Int(unsigned_id), cast_result, Operand::Int(val_id)}) &&
|
||||
push_function_inst(spv::Op::OpBitwiseAnd,
|
||||
{Operand::Int(unsigned_id), exponent_bits_result,
|
||||
Operand::Int(cast_result.to_i()),
|
||||
Operand::Int(exponent_mask_id)}) &&
|
||||
push_function_inst(
|
||||
spv::Op::OpExtInst,
|
||||
{Operand::Int(unsigned_id), clamp_result, Operand::Int(set_id),
|
||||
Operand::Int(GLSLstd450UClamp),
|
||||
Operand::Int(exponent_bits_result.to_i()),
|
||||
Operand::Int(min_exponent_id), Operand::Int(max_exponent_id)}) &&
|
||||
push_function_inst(spv::Op::OpIEqual,
|
||||
{Operand::Int(result_type_id), result,
|
||||
Operand::Int(exponent_bits_result.to_i()),
|
||||
Operand::Int(clamp_result.to_i())})) {
|
||||
return result_id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case BuiltinType::kMix: {
|
||||
auto std450 = Operand::Int(GetGLSLstd450Import());
|
||||
|
||||
|
||||
@@ -102,225 +102,6 @@ INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
testing::Values(BuiltinData{"any", "OpAny"},
|
||||
BuiltinData{"all", "OpAll"}));
|
||||
|
||||
using BuiltinFloatTest = BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(BuiltinFloatTest, Call_Float_Scalar) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
Assign(Phony(), expr),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
|
||||
ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
|
||||
%2 = OpTypePointer Private %3
|
||||
%4 = OpConstantNull %3
|
||||
%1 = OpVariable %2 Private %4
|
||||
%6 = OpTypeVoid
|
||||
%5 = OpTypeFunction %6
|
||||
%10 = OpTypeBool
|
||||
)");
|
||||
|
||||
auto expected = utils::ReplaceAll(R"(%11 = OpLoad %3 %1
|
||||
%9 = ${op} %10 %11
|
||||
OpReturn
|
||||
)",
|
||||
"${op}", param.op);
|
||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
|
||||
TEST_P(BuiltinFloatTest, Call_Float_Vector) {
|
||||
auto param = GetParam();
|
||||
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call(param.name, "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
Assign(Phony(), expr),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
|
||||
ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
|
||||
%3 = OpTypeVector %4 3
|
||||
%2 = OpTypePointer Private %3
|
||||
%5 = OpConstantNull %3
|
||||
%1 = OpVariable %2 Private %5
|
||||
%7 = OpTypeVoid
|
||||
%6 = OpTypeFunction %7
|
||||
%12 = OpTypeBool
|
||||
%11 = OpTypeVector %12 3
|
||||
)");
|
||||
|
||||
auto expected = utils::ReplaceAll(R"(%13 = OpLoad %3 %1
|
||||
%10 = ${op} %11 %13
|
||||
OpReturn
|
||||
)",
|
||||
"${op}", param.op);
|
||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), expected);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(BuiltinBuilderTest,
|
||||
BuiltinFloatTest,
|
||||
testing::Values(BuiltinData{"isNan", "OpIsNan"},
|
||||
BuiltinData{"isInf", "OpIsInf"}));
|
||||
|
||||
TEST_F(BuiltinBuilderTest, IsFinite_Scalar) {
|
||||
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("isFinite", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
Assign(Phony(), expr),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
|
||||
ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
|
||||
%2 = OpTypePointer Private %3
|
||||
%4 = OpConstantNull %3
|
||||
%1 = OpVariable %2 Private %4
|
||||
%6 = OpTypeVoid
|
||||
%5 = OpTypeFunction %6
|
||||
%10 = OpTypeBool
|
||||
)");
|
||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
||||
R"(%11 = OpLoad %3 %1
|
||||
%12 = OpIsInf %10 %11
|
||||
%13 = OpIsNan %10 %11
|
||||
%14 = OpLogicalOr %10 %12 %13
|
||||
%9 = OpLogicalNot %10 %14
|
||||
OpReturn
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(BuiltinBuilderTest, IsFinite_Vector) {
|
||||
auto* var = Global("v", ty.vec3<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("isFinite", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
Assign(Phony(), expr),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
|
||||
ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
|
||||
|
||||
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
|
||||
%3 = OpTypeVector %4 3
|
||||
%2 = OpTypePointer Private %3
|
||||
%5 = OpConstantNull %3
|
||||
%1 = OpVariable %2 Private %5
|
||||
%7 = OpTypeVoid
|
||||
%6 = OpTypeFunction %7
|
||||
%12 = OpTypeBool
|
||||
%11 = OpTypeVector %12 3
|
||||
)");
|
||||
EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()),
|
||||
R"(%13 = OpLoad %3 %1
|
||||
%14 = OpIsInf %11 %13
|
||||
%15 = OpIsNan %11 %13
|
||||
%16 = OpLogicalOr %11 %14 %15
|
||||
%10 = OpLogicalNot %11 %16
|
||||
OpReturn
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(BuiltinBuilderTest, IsNormal_Scalar) {
|
||||
auto* var = Global("v", ty.f32(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("isNormal", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
Assign(Phony(), expr),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
|
||||
ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
|
||||
|
||||
auto got = DumpBuilder(b);
|
||||
EXPECT_EQ(got, R"(%12 = OpExtInstImport "GLSL.std.450"
|
||||
OpName %1 "v"
|
||||
OpName %7 "a_func"
|
||||
%3 = OpTypeFloat 32
|
||||
%2 = OpTypePointer Private %3
|
||||
%4 = OpConstantNull %3
|
||||
%1 = OpVariable %2 Private %4
|
||||
%6 = OpTypeVoid
|
||||
%5 = OpTypeFunction %6
|
||||
%10 = OpTypeBool
|
||||
%13 = OpTypeInt 32 0
|
||||
%14 = OpConstant %13 133693440
|
||||
%15 = OpConstant %13 524288
|
||||
%16 = OpConstant %13 133169152
|
||||
%7 = OpFunction %6 None %5
|
||||
%8 = OpLabel
|
||||
%11 = OpLoad %3 %1
|
||||
%17 = OpBitcast %13 %11
|
||||
%18 = OpBitwiseAnd %13 %17 %14
|
||||
%19 = OpExtInst %13 %12 UClamp %18 %15 %16
|
||||
%9 = OpIEqual %10 %18 %19
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(BuiltinBuilderTest, IsNormal_Vector) {
|
||||
auto* var = Global("v", ty.vec2<f32>(), ast::StorageClass::kPrivate);
|
||||
auto* expr = Call("isNormal", "v");
|
||||
auto* func = Func("a_func", {}, ty.void_(),
|
||||
{
|
||||
Assign(Phony(), expr),
|
||||
});
|
||||
|
||||
spirv::Builder& b = Build();
|
||||
|
||||
ASSERT_TRUE(b.GenerateGlobalVariable(var)) << b.error();
|
||||
ASSERT_TRUE(b.GenerateFunction(func)) << b.error();
|
||||
|
||||
auto got = DumpBuilder(b);
|
||||
EXPECT_EQ(got, R"(%14 = OpExtInstImport "GLSL.std.450"
|
||||
OpName %1 "v"
|
||||
OpName %8 "a_func"
|
||||
%4 = OpTypeFloat 32
|
||||
%3 = OpTypeVector %4 2
|
||||
%2 = OpTypePointer Private %3
|
||||
%5 = OpConstantNull %3
|
||||
%1 = OpVariable %2 Private %5
|
||||
%7 = OpTypeVoid
|
||||
%6 = OpTypeFunction %7
|
||||
%12 = OpTypeBool
|
||||
%11 = OpTypeVector %12 2
|
||||
%15 = OpTypeInt 32 0
|
||||
%16 = OpConstant %15 133693440
|
||||
%17 = OpConstant %15 524288
|
||||
%18 = OpConstant %15 133169152
|
||||
%19 = OpTypeVector %15 2
|
||||
%8 = OpFunction %7 None %6
|
||||
%9 = OpLabel
|
||||
%13 = OpLoad %3 %1
|
||||
%20 = OpCompositeConstruct %19 %16 %16
|
||||
%21 = OpCompositeConstruct %19 %17 %17
|
||||
%22 = OpCompositeConstruct %19 %18 %18
|
||||
%23 = OpBitcast %19 %13
|
||||
%24 = OpBitwiseAnd %19 %23 %20
|
||||
%25 = OpExtInst %19 %14 UClamp %24 %21 %22
|
||||
%10 = OpIEqual %11 %24 %25
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)");
|
||||
}
|
||||
|
||||
using BuiltinIntTest = BuiltinBuilderTestWithParam<BuiltinData>;
|
||||
TEST_P(BuiltinIntTest, Call_SInt_Scalar) {
|
||||
auto param = GetParam();
|
||||
|
||||
Reference in New Issue
Block a user