From 0379d59c1c53494ff44212ae27f4fdac6da6b003 Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Mon, 27 Jul 2026 14:19:42 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20AUDIT=20C9=20=E2=80=94=20the=20FP=20def?= =?UTF-8?q?ault=20differs=20BY=20TOOLCHAIN,=20not=20just=20"fast=20is=20al?= =?UTF-8?q?lowed=20to=20drift"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Jahni asked the right question: does the same seed produce identical results across OS builds today? Checking the other toolchain made the answer sharper and worse than what C9 originally said. ClangToolChain.cs (Linux, Mac, Windows-with-Clang): case FPSemanticsMode.Default: // Default to precise FP semantics. case FPSemanticsMode.Precise: Arguments.Add("-ffp-contract=off"); and VCToolChain forces Precise when Windows uses Clang. So the same FPSemanticsMode.Default resolves to OPPOSITE float models per toolchain, and Windows/MSVC is the only imprecise configuration in the engine's defaults. Two builds of identical source are not merely permitted to diverge -- they are compiled under different rules. Also added, so the entry does not over-fear itself: - Calibration: 0 of 20000 samples crossed the isosurface under a 1-ULP perturbation, so divergence means occasional single-voxel surface differences, not different terrain. The case that bites is topological (a cave pinch-point connecting on one build and not the other), which is rare and unreproducible -- the expensive kind. - Precise everywhere still would not guarantee cross-platform bit-identity: FMath::Sin/Cos route to platform libm, which is not bit-standardised. It closes the large gap, not every gap. - The knob would ALIGN Windows with every other platform rather than being a one-sided cost -- but still must not be turned speculatively. - The claim is inferred, not measured. The cheap decisive test is one Windows build with FPSemantics = Precise: if MazeEquivalence's 454-sample residue vanishes, the FP model is confirmed as the sole cause. Co-Authored-By: Claude Opus 5 --- AUDIT-2026-07.md | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/AUDIT-2026-07.md b/AUDIT-2026-07.md index e09259f..ba156ac 100644 --- a/AUDIT-2026-07.md +++ b/AUDIT-2026-07.md @@ -263,6 +263,20 @@ and UBT's own doc for that mode: *"FP math isn't IEEE-754 compliant: the compile transform math expressions in ways that might result in differently rounded results from what IEEE-754 requires."* The plugin sets no `FPSemantics` override, so it gets the default. +**⚠️ And the default is not the same default everywhere.** `ClangToolChain.cs` — used by Linux, Mac, +and Windows-with-Clang: + +```csharp +case FPSemanticsMode.Default: // Default to precise FP semantics. +case FPSemanticsMode.Precise: + Arguments.Add("-ffp-contract=off"); +``` + +`VCToolChain` additionally forces `Precise` when the Windows compiler is Clang. So **the same +`FPSemanticsMode.Default` resolves to opposite float models per toolchain**, and Windows/MSVC is the +only imprecise configuration in the engine's defaults. Two builds of identical source are therefore +not merely *permitted* to diverge — they are compiled under different rules. + **Two consequences, one benign and one not:** **Benign — refactors cannot be bit-identical.** The same expression compiled into two translation @@ -292,11 +306,30 @@ stated. is a real desync source, and it will present as rare, unreproducible, geometry-only divergence: approximately the worst bug class to diagnose. +**Calibration, so this isn't over-feared.** In 20,000 Maze samples, **zero** crossed the isosurface +under a 1-ULP perturbation. Divergence would therefore be occasional *single-voxel* surface +differences, not visibly different terrain — sub-voxel, near-certainly imperceptible for +collision-vs-visual mismatch. The case that would genuinely bite is **topological**: a cave +pinch-point that connects on one build and not the other. Rare — but "rare and unreproducible" is +the expensive kind of rare. + +**Even `Precise` everywhere would not buy guaranteed cross-platform bit-identity.** `FMath::Sqrt` is +IEEE-exact and `VoxelNoise`'s hash-gradient core is integer + basic arithmetic, so those are safe. +But `FMath::Sin`/`Cos` (disturbance bridge/ridge angles) route to platform libm, which is not +bit-standardised across OSes. Aligning the FP model closes the large gap, not every gap. + **The knob, if it turns out to matter:** `ModuleRules.FPSemantics = FPSemanticsMode.Precise` in -`VoxelForge.Build.cs` restores IEEE semantics for this module only. **Do not do this speculatively** — -the density path is the plugin's hot loop, `/fp:precise` blocks exactly the vectorisation and -contraction that T2.a's SIMD noise work was chasing, and the cost is unmeasured. It is a decision to -take with a profile in hand and a confirmed cross-platform requirement, not a tidy-up. +`VoxelForge.Build.cs`, module-scoped. Note it would *align Windows with every other platform's +default* rather than being a one-sided cost. **Still do not do this speculatively** — the density +path is the plugin's hot loop, precise semantics block exactly the vectorisation and contraction +T2.a's SIMD noise work was chasing, and the cost is unmeasured. Decision needs a profile in hand and +a confirmed cross-platform requirement. + +**Verification, when it becomes relevant:** the cross-build claim above is *inferred*, not measured — +no Linux build has been made. The cheap decisive test is to compile the plugin once with +`FPSemantics = Precise` on Windows and re-run `VoxelForge.OpStack.MazeEquivalence`: if the residual +454-sample difference vanishes, the FP model is confirmed as the sole cause and the cross-toolchain +risk is real. That is one build, and it settles it. ---