docs: AUDIT C9 — the FP default differs BY TOOLCHAIN, not just "fast is allowed to drift"
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 <noreply@anthropic.com>
This commit is contained in:
+37
-4
@@ -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.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user