Files
VoxelForge/Source/VoxelForge/Private/Tests/VoxelForgeIsFiniteTest.cpp
T
Fr0zkaandClaude Opus 5 5489b5e311 perf(generation): inline exact IsFinite -- LOD0 ~11-12% faster, field-exact
The sampler's last "unknown" LOD0 bucket (~13.8%) was ucrtbase.dll!_finite: FMath::IsFinite is an
out-of-line CRT call on the MSVC game path, hit from the innermost tunnel, passage, density,
spatial-index and meshing loops.

- VoxelMath::IsFiniteFast(float/double) in VoxelTypes.h: memcpy to uint32/uint64,
  (Bits & ExpMask) != ExpMask. It is the same predicate for every bit pattern, with no FP
  comparison for fast-math to fold. The disassembly shows it inlined (movd/movq, mask, compare).
- VoxelMath::IsFinite routes through a plain global, voxel.FastIsFinite (default 1), for the A/B.
  The CRT call remains only on the switch-off branch. Hot generation-path uses are replaced; no
  _finite / std::isfinite remains in Source/VoxelForge. Tool/editor/test code keeps FMath.
- A test that can fail: VoxelForge.Math.IsFiniteExact compares against FMath::IsFinite over 22
  explicit float/double patterns (+-0, denormals, min/max normal, +-Inf, quiet and signalling NaN
  payloads) plus 2,000,000 hashed patterns each: 0 mismatches. The explicit NaNs make a NaN-wrong
  helper fail.

Field exact: 841/841 keyed tiles identical to NextHeadStaticTrace_20260913 (verdict/empty/
triangles), export OBJ unchanged (b3e5f4c3..9b377), capability 20,830 / 10,909.

Within-round A/B, game path, two interleaved runs each, sampler off (off -> on):
  static  LOD0 request p50  95.5 -> 84.8 ms   generation p50/p95  70.3/114.1 -> 62.3/100.6 ms
          worker            35.4 -> 31.6 s (-10.5%)
  moving  LOD0 request p50/p95  70.8/144.2 -> 62.0/126.1 ms
          generation p50/p95    62.6/113.4 -> 55.1/101.0 ms
          worker            102.6 -> 91.3 s (-11.0%)
Sampler-on moving: the _finite/CRT cluster is gone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TaFdXhTdYMkW1xrV6ApT6Y
2026-09-13 23:50:30 +02:00

182 lines
7.1 KiB
C++

// Bit-exact equivalence coverage for the generation-path finite predicate.
#if WITH_DEV_AUTOMATION_TESTS
#include "Misc/AutomationTest.h"
#include "VoxelTypes.h"
IMPLEMENT_SIMPLE_AUTOMATION_TEST(
FVoxelForgeIsFiniteTest,
"VoxelForge.Math.IsFiniteExact",
EAutomationTestFlags_ApplicationContextMask | EAutomationTestFlags::EngineFilter)
namespace
{
template <typename TValue, typename TBits>
TValue ValueFromBits(TBits Bits)
{
TValue Value;
FMemory::Memcpy(&Value, &Bits, sizeof(Value));
return Value;
}
FORCEINLINE uint64 NextHashedBits(uint64& State)
{
State += 0x9E3779B97F4A7C15ull;
uint64 Z = State;
Z = (Z ^ (Z >> 30)) * 0xBF58476D1CE4E5B9ull;
Z = (Z ^ (Z >> 27)) * 0x94D049BB133111EBull;
return Z ^ (Z >> 31);
}
struct FFloatPattern
{
const TCHAR* Name;
uint32 Bits;
};
struct FDoublePattern
{
const TCHAR* Name;
uint64 Bits;
};
}
bool FVoxelForgeIsFiniteTest::RunTest(const FString& Parameters)
{
int32 FloatMismatches = 0;
int32 DoubleMismatches = 0;
auto CheckFloat = [&](const TCHAR* Name, uint32 Bits)
{
const float Value = ValueFromBits<float>(Bits);
const bool Fast = VoxelMath::IsFiniteFast(Value);
const bool Reference = FMath::IsFinite(Value);
if (Fast != Reference)
{
++FloatMismatches;
if (FloatMismatches <= 8)
{
AddError(FString::Printf(
TEXT("%s: float bits 0x%08X produced fast=%s, FMath=%s"),
Name, Bits,
Fast ? TEXT("true") : TEXT("false"),
Reference ? TEXT("true") : TEXT("false")));
}
}
};
auto CheckDouble = [&](const TCHAR* Name, uint64 Bits)
{
const double Value = ValueFromBits<double>(Bits);
const bool Fast = VoxelMath::IsFiniteFast(Value);
const bool Reference = FMath::IsFinite(Value);
if (Fast != Reference)
{
++DoubleMismatches;
if (DoubleMismatches <= 8)
{
AddError(FString::Printf(
TEXT("%s: double bits 0x%08X%08X produced fast=%s, FMath=%s"),
Name,
static_cast<uint32>(Bits >> 32), static_cast<uint32>(Bits),
Fast ? TEXT("true") : TEXT("false"),
Reference ? TEXT("true") : TEXT("false")));
}
}
};
// Explicit classes make a NaN regression fail even if the random stream happens not to hit a
// NaN. In particular, a helper that only checks the sign/exponent incorrectly must fail here.
const FFloatPattern FloatPatterns[] =
{
{ TEXT("+0"), 0x00000000u },
{ TEXT("-0"), 0x80000000u },
{ TEXT("+min subnormal"), 0x00000001u },
{ TEXT("-min subnormal"), 0x80000001u },
{ TEXT("+max subnormal"), 0x007FFFFFu },
{ TEXT("-max subnormal"), 0x807FFFFFu },
{ TEXT("+min normal"), 0x00800000u },
{ TEXT("-min normal"), 0x80800000u },
{ TEXT("+max normal"), 0x7F7FFFFFu },
{ TEXT("-max normal"), 0xFF7FFFFFu },
{ TEXT("+infinity"), 0x7F800000u },
{ TEXT("-infinity"), 0xFF800000u },
{ TEXT("+quiet NaN payload 1"), 0x7FC00001u },
{ TEXT("-quiet NaN payload 1"), 0xFFC00001u },
{ TEXT("+quiet NaN payload mixed"), 0x7FC12345u },
{ TEXT("-quiet NaN payload mixed"), 0xFFC12345u },
{ TEXT("+signalling NaN payload 1"), 0x7F800001u },
{ TEXT("-signalling NaN payload 1"), 0xFF800001u },
{ TEXT("+signalling NaN payload mixed"), 0x7FA00001u },
{ TEXT("-signalling NaN payload mixed"), 0xFFA00001u },
{ TEXT("+signalling NaN max payload"), 0x7FBFFFFFu },
{ TEXT("-signalling NaN max payload"), 0xFFBFFFFFu },
};
for (const FFloatPattern& Pattern : FloatPatterns)
{
CheckFloat(Pattern.Name, Pattern.Bits);
}
const FDoublePattern DoublePatterns[] =
{
{ TEXT("+0"), 0x0000000000000000ull },
{ TEXT("-0"), 0x8000000000000000ull },
{ TEXT("+min subnormal"), 0x0000000000000001ull },
{ TEXT("-min subnormal"), 0x8000000000000001ull },
{ TEXT("+max subnormal"), 0x000FFFFFFFFFFFFFull },
{ TEXT("-max subnormal"), 0x800FFFFFFFFFFFFFull },
{ TEXT("+min normal"), 0x0010000000000000ull },
{ TEXT("-min normal"), 0x8010000000000000ull },
{ TEXT("+max normal"), 0x7FEFFFFFFFFFFFFFull },
{ TEXT("-max normal"), 0xFFEFFFFFFFFFFFFFull },
{ TEXT("+infinity"), 0x7FF0000000000000ull },
{ TEXT("-infinity"), 0xFFF0000000000000ull },
{ TEXT("+quiet NaN payload 1"), 0x7FF8000000000001ull },
{ TEXT("-quiet NaN payload 1"), 0xFFF8000000000001ull },
{ TEXT("+quiet NaN payload mixed"), 0x7FF8123456789ABCull },
{ TEXT("-quiet NaN payload mixed"), 0xFFF8123456789ABCull },
{ TEXT("+signalling NaN payload 1"), 0x7FF0000000000001ull },
{ TEXT("-signalling NaN payload 1"), 0xFFF0000000000001ull },
{ TEXT("+signalling NaN payload mixed"), 0x7FF4000000000001ull },
{ TEXT("-signalling NaN payload mixed"), 0xFFF4000000000001ull },
{ TEXT("+signalling NaN max payload"), 0x7FF7FFFFFFFFFFFFull },
{ TEXT("-signalling NaN max payload"), 0xFFF7FFFFFFFFFFFFull },
};
for (const FDoublePattern& Pattern : DoublePatterns)
{
CheckDouble(Pattern.Name, Pattern.Bits);
}
// Deterministic hash-generated raw bit patterns exercise ordinary values and special values
// without converting through floating point. The loop counts are intentionally large enough
// to make this a broad bit-pattern check rather than a handful of representative numbers.
constexpr uint32 NumRandomFloatPatterns = 2000000u;
constexpr uint32 NumRandomDoublePatterns = 2000000u;
uint64 FloatState = 0x123456789ABCDEF0ull;
for (uint32 Index = 0; Index < NumRandomFloatPatterns; ++Index)
{
CheckFloat(TEXT("hashed random"), static_cast<uint32>(NextHashedBits(FloatState)));
}
uint64 DoubleState = 0x0FEDCBA987654321ull;
for (uint32 Index = 0; Index < NumRandomDoublePatterns; ++Index)
{
CheckDouble(TEXT("hashed random"), NextHashedBits(DoubleState));
}
AddInfo(FString::Printf(
TEXT("Compared %d explicit + %u hashed float patterns and %d explicit + %u hashed double "
"patterns; float mismatches=%d, double mismatches=%d."),
UE_ARRAY_COUNT(FloatPatterns), NumRandomFloatPatterns,
UE_ARRAY_COUNT(DoublePatterns), NumRandomDoublePatterns,
FloatMismatches, DoubleMismatches));
TestEqual(TEXT("float finite predicate has no mismatches"), FloatMismatches, 0);
TestEqual(TEXT("double finite predicate has no mismatches"), DoubleMismatches, 0);
return FloatMismatches == 0 && DoubleMismatches == 0;
}
#endif // WITH_DEV_AUTOMATION_TESTS