# WorldAssemblerM3 Linux3 — FP contraction ## Unreal flags: documented and inferred UE 5.7's Target Reference documents `FPSemantics`; Epic's Module Properties page documents the matching module-level property and says it overrides FP semantics. Epic Support says module and target overrides have existed since UE 5.4. This repo's `VoxelForgeCore.Build.cs` already sets `FPSemantics = FPSemanticsMode.Precise` and `PCHUsage = PCHUsageMode.NoPCHs` (existing lines 44–45). [UE 5.7 Target Reference](https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-build-tool-target-reference?application_version=5.7), [Module Properties](https://dev.epicgames.com/documentation/unreal-engine/module-properties-in-unreal-engine), [Epic Support answer](https://forums.unrealengine.com/t/debug-game-development/2668723) Public UBT documentation does **not** publish one exact compiler argv for every plugin, platform, and configuration. Epic Support reports Windows DebugGame uses `/fp:precise` and Development uses `/fp:fast` by default. MSVC 2022 17+ defaults `/fp:precise` to contraction off; explicit `/fp:contract` can enable it under `/fp:precise`, and `/fp:fast` permits it by default. Earlier MSVC versions defaulted precise contraction on. Explicit `#pragma fp_contract(off)` overrides `/fp:fast`. Clang's `precise` model allows same-expression `-ffp-contract=on`; `-ffp-contract=fast` can fuse across statements and ignores `#pragma clang fp contract(off)`. GCC defaults to `-ffp-contract=fast`; its standard `FP_CONTRACT` pragma is not implemented, so this patch uses GCC's function-option pragma instead. [MSVC `/fp`](https://learn.microsoft.com/en-us/cpp/build/reference/fp-specify-floating-point-behavior?view=msvc-170), [MSVC pragma](https://learn.microsoft.com/en-us/cpp/preprocessor/fp-contract?view=msvc-170), [Clang FP pragmas and model](https://clang.llvm.org/docs/LanguageExtensions.html#extensions-to-specify-floating-point-flags), [GCC FP options](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html), [GCC function-specific pragmas](https://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html), [GCC FP implementation](https://gcc.gnu.org/onlinedocs/gcc/Floating-point-implementation.html) **Inference for this repo:** The standalone BuildHost is safe-by-configuration on current VS 2022: `Build.ps1` explicitly uses `/fp:precise`, whose 17.0+ default is contraction off. The owner's UBT Windows build is likely safe for the same reason because the module sets `Precise`, but it was not captured here; an older MSVC or an explicit `/fp:contract` could put it at risk. On Linux, `Precise` alone does not mean contraction off for Clang, so the UBT build was at risk before this change. UE 5.7's supported Linux compiler is Clang 20.1.8; this host tested Clang 19.1.7. Epic's UE 5.7 PS5 notes also show Clang flags vary by platform: PS5 removed `-ffp-contract=off` because its `-ffast-math` setting conflicted with it. This does not establish that Linux UBT passes `-ffast-math`; capture that module's actual command line on the owner PC. [UE Linux requirements](https://dev.epicgames.com/documentation/unreal-engine/linux-development-requirements-for-unreal-engine?lang=en-US), [UE 5.7 PS5 notes](https://dev.epicgames.com/documentation/en-us/unreal-engine/playstation-5-release-notes-for-unreal-engine-5-7) ## Mechanism and Core lines touched Each Core translation unit loads `CoreNamespacePreamble.h` before its implementation. The preamble applies Clang `contract(off)`, MSVC `fp_contract(off)`, or GCC `optimize("fp-contract=off")`; unknown compilers fail at compile time. Its noinline probe evaluates `(1 + 2^-27) * (1 - 2^-27) - 1` using volatile inputs. Separate multiply/add rounds to `0`; a fused operation returns `-2^-54`. `World::compile` runs that probe before building the shape and returns an error before density generation if it fuses. The check and density implementation receive the same preamble/FP pragma in Core. Clang `fast` is deliberately refused because Clang documents that mode as ignoring the source pragma. GCC's default and the explicit Clang `on` mode are instead compiled with the source-level off control. Only these Core lines changed: - `Standalone/Core/src/CoreNamespacePreamble.h:58–93` — per-compiler pragma and shared self-test. - `Standalone/Core/src/VoxelForgeCore.cpp:972–976` — refusal before shape build. For this sweep, the standalone headless runner also gained `--auto-surface-camera` and `--mesh-coverage` in `Standalone/Source/StreamBenchmarkHeadless.cpp` and `Standalone/Source/StreamBenchmarkPipeline.h`. The probe guards FP contraction. It does not establish immunity to unrelated `-ffast-math` transformations such as reassociation; those flags must be captured and handled separately if present. ## Hash immunity All successful rows cover the L1 whole view (2,553 tiles); each cell below lists density / mesh / payload / topology hashes. Runs used `Standalone/data/owner_world.json` and `--world-assembler-prototype --stream-benchmark --stream-pipeline --stream-hash --force-generate --clip-radius=3 --max-clip-level=8 --camera=0,-35,-487.94,0,-22 --far-horizon-lod8-step=0`. `Clang fast` was built with `-ffp-contract=fast` and `-fno-fast-math`. | Compiler and setting | W1 | W12 | |---|---|---| | Clang 19 `-ffp-contract=off` | `c10697a8f48380c7 / e75c9119a1498cd5 / 49a9a8d1835a6c8c / edcb23288b5e8724` | same | | Clang 19 `-ffp-contract=on` | same | same | | Clang 19 `-ffp-contract=fast` | refused before generation | refused before generation | | GCC 14 default (effective contract=fast) | `c10697a8f48380c7 / e75c9119a1498cd5 / 49a9a8d1835a6c8c / edcb23288b5e8724` | same | All three supported configurations (Clang off/on, GCC default) match the L1 reference. Both Clang `fast` runs returned exit code 2 in about 0.066 s with the explicit diagnostic, before generating a density hash. Logs: [W1 refusal](../../../../Saved/Linux/linux3-final-hash-clang-fast-w1.log), [W12 refusal](../../../../Saved/Linux/linux3-final-hash-clang-fast-w12.log); successful per-run logs are `linux3-final-hash-*.log` under `Saved/Linux`. ## Self-test negative control The test is in the shared Core preamble, not a separate differently compiled test file. In the deliberate Clang `fast` build it detected the fused result and the Core API rejected world generation at W1 and W12. A compiler-only probe also returned `0` for Clang off/on and GCC with its off pragma, and `-0x1p-54` for Clang fast ([probe log](../../../../Saved/Linux/linux3-pragma-probe.log)). The production-build refusal is the negative control. ## Corrected seed sweep The sweep used 48 unique seeds, both recipes, Clang off/on and GCC default, and W1/W12: 576 runs in 432.977 s. Each SurfaceWorld 96³-voxel cube was centered at the original XY and moved to that seed's nearest heightfield surface; each FloatingIslands cube was centered on that seed's largest planned island. Every run covered 27 LOD0 tiles and contained triangles. | Recipe | Per-seed coverage across the sweep | |---|---| | SurfaceWorld | 9–18 nonempty mesh tiles; 26,182–52,468 indexed triangles | | FloatingIslands | 7–15 nonempty mesh tiles; 15,728–46,224 indexed triangles | All seeds had distinct density hashes within each recipe. Cross-build comparisons: 192, mismatches 0. W1/W12 comparisons: 288, mismatches 0. Empty-mesh rows: 0. Peak run RSS: 306,580 KiB. The full compiler/worker results are in [seed_mesh_coverage.csv](seed_mesh_coverage.csv); one row per seed and recipe, including the nonempty tile and triangle counts and placed camera, is in [seed_mesh_coverage_per_seed.csv](seed_mesh_coverage_per_seed.csv). Summary: [seed_mesh_coverage_summary.txt](seed_mesh_coverage_summary.txt). ## Cost Three interleaved W12 runs per binary used the same 2,553-tile view, without mesh-coverage counting. “Before” is the S14 executable; “after” is the Clang-off L3 executable. | Build | Whole-view ready times (s) | Median | |---|---|---:| | S14 before | 2.260, 2.326, 2.339 | 2.326 s | | L3 after | 2.329, 2.384, 2.337 | 2.337 s | The interleaved median change is +0.011 s (+0.5%). The agreed owner-provided before baseline was 2.42 s; L3's 2.337 s median is 0.083 s below it. All six runs retained the L1 hashes. Maximum run RSS was about 550 MiB. Governor remained `powersave`; EPP remained `balance_performance`. ## Windows work still needed MSVC was not available here. On the Windows BuildHost: 1. Build the standalone Core and viewer from the updated tree: `powershell -ExecutionPolicy Bypass -File Standalone\Build.ps1 -Target All -CompileWorkers 12`. This uses `/fp:precise`; inspect `Standalone\Build\VoxelForgeCore\core-compile.rsp` to confirm. 2. Run the resulting viewer on the L1 view twice, once with `--workers=1` and once with `--workers=12`, using `--world-assembler-prototype --stream-benchmark --stream-pipeline --stream-hash --force-generate --clip-radius=3 --max-clip-level=8 --camera=0,-35,-487.94,0,-22 --far-horizon-lod8-step=0`. Require the four L1 hashes both times and no self-test error. 3. To validate the MSVC pragma under an explicitly contracted setting, make a temporary copy of `Build.ps1`, change its single `/fp:precise` entry to `/fp:fast`, and build it with `-OutputName VoxelForgeCoreStandalone-msvc-fast.exe`. Run the same W1/W12 L1 checks and require unchanged hashes and a passing self-test. 4. Build the owner project's UE 5.7 Win64 Development Editor target (and its Server target if configured) with this plugin enabled. Save the actual UBT `cl.exe` commands for `VoxelForgeCore` and record `/fp:*`, `/fp:contract`, and any `/fp:fast` or `/fp:precise` options. Run the owner's existing seed-0 Core world/hash path at W1 and W12 and confirm the L1 result and passing self-test. MSVC-specific risks: the pragma has not been compiled here; `/fp:precise` contraction defaults changed at VS 2022 17.0; target configuration may add `/fp:fast` or `/fp:contract`; and UBT's module override must reach every Core source. Microsoft documents that the explicit pragma overrides `/fp:fast`, but the Windows build must confirm that the actual toolset honors it. `VoxelForgeCore.Build.cs` already disables PCH and unity builds, and each Core wrapper includes the pragma preamble. ## Runs and limits No build, hash, sweep, or timing run failed or needed a retry. The two Clang `fast` exits were the expected negative control. Build variants were Clang 19.1.7 and GCC 14.2; builds and runs used CPUs 0–11, at most 12 jobs, normal priority, and a 6 GiB per-process address-space limit. Build peak RSS: 895,640 KiB (GCC); L1 hash-run peak: 551,004 KiB; seed-sweep peak: 306,580 KiB. The 8 MiB process stack was unchanged; Linux workers retain their existing 32 MiB stacks. Build artifacts are under `Standalone/Build/linux-l3-*` and `Standalone/bin/linux/`; logs are under `Saved/Linux/`. ## Note for the owner Core now disables expression contraction for Clang, GCC, and MSVC, and rejects Clang fast when that compiler ignores the off pragma; all supported Linux settings retained the L1 hashes. Please validate the source pragma on native MSVC and capture UE 5.7 UBT's actual Windows and Linux compiler arguments, since those builds were not available here. ## Orchestrator review (Claude) - Re-run by me on Luna's binaries, W12, L1 view: Clang `off` 2.299 s and Clang `on` 2.302 s, both density `c10697a8f48380c7`; GCC default 2.469 s, also `c10697a8f48380c7`; Clang `fast` exits 2 with the self-test refusal. Clang `on` and GCC default gave *different* worlds in L2, so the pragma is demonstrably effective. - Known gap (small): the pragma sits after the standard headers, `Json.h` and the public API header in the preamble, so inline/template code defined there is not covered. All Core world math (Compat, `*Internal.h`, legacy sources) comes after it. - The probe guards contraction only; `-ffast-math` reassociation is a separate risk (as Luna says). The Windows to-do list above is the gate before claiming this on MSVC/UBT.