From a49d440bf6b48ade64ae218436e9da0eaec91b9d Mon Sep 17 00:00:00 2001 From: Fr0zka Date: Mon, 27 Jul 2026 14:34:50 +0200 Subject: [PATCH] =?UTF-8?q?build:=20put=20FPSemantics=3DPrecise=20on=20the?= =?UTF-8?q?=20VoxelForge=20module=20=E2=80=94=20the=20experiment=20never?= =?UTF-8?q?=20ran?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FPSemantics is a per-module ModuleRules property. It had been set on the VoxelM GAME module, while every line of density code lives in VoxelForge, which kept compiling /fp:fast. So the run that supposedly "reproduced the residue under precise semantics" ran under fast semantics and proves nothing. Retracting the previous commit's conclusion: /fp:fast is NOT eliminated as the cause, and the notes claiming AUDIT C9 and OPSTACK-PLAN 2.6 are falsified are withdrawn with it. Those documents were fine. My error, and the third of its kind today: I reasoned a confident conclusion from an unverified premise, one paragraph after writing that the lesson was to instrument rather than assume. Checking took one grep and I only ran it after Jahni suggested it. The line is marked TEMPORARY with removal instructions and a guide to reading the result. Combined with the WORST-POINT DUMP already committed, one build now separates the two possibilities cleanly: 454 -> 0 : FP model was the cause; keeping precise then needs a profile, because it costs the vectorisation T2.a's SIMD work was buying. 454 -> 454 : real logic difference; read the dump. Either way the line comes back out afterwards. Co-Authored-By: Claude Opus 5 --- OPSTACK-PROGRESS.md | 40 +++++++++++++++++++++++++++ Source/VoxelForge/VoxelForge.Build.cs | 27 ++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/OPSTACK-PROGRESS.md b/OPSTACK-PROGRESS.md index 2c4d400..4c0fd46 100644 --- a/OPSTACK-PROGRESS.md +++ b/OPSTACK-PROGRESS.md @@ -451,3 +451,43 @@ in the SDF (lattice edges or `VoxelSDF::Capsule`) or in `SmoothStep01`. small unexplained numeric difference, and those do not get smaller when you build on them. --- + +## 2026-07-27 — CORRECTION: hypothesis 3 was never tested. My error, not Jahni's. + +**`FPSemantics = FPSemanticsMode.Precise` was set in `Source/VoxelM/VoxelM.Build.cs` — the GAME +module.** `FPSemantics` is a `ModuleRules` property, i.e. **per module**. Every line of density code +lives in the `VoxelForge` module, which was still compiling `/fp:fast`. The float model never +changed for the code under test. + +**So the previous entry is wrong and is retracted:** `/fp:fast` is NOT eliminated. The run that +"reproduced the residue under precise semantics" reproduced it under *fast* semantics, which is +exactly what it should have done and proves nothing. + +**The failure mode, stated plainly because it is the third time in one day:** I accepted "it's with +fpsemantics precise" as fact and reasoned a confident conclusion from it — one paragraph after +writing that the lesson was to instrument rather than assume. The check took one `grep` and I did it +only after Jahni suggested it. **Verify the premise before reasoning from it, especially when the +premise is what makes the conclusion interesting.** + +**Consequently:** the notes in the previous entry saying `AUDIT §C9` and `OPSTACK-PLAN §2.6` are +falsified are themselves withdrawn. Those documents' `/fp:fast` explanation is back to *plausible +and now genuinely about to be tested*. Nothing in them needs changing yet. + +**What changed:** `FPSemantics = FPSemanticsMode.Precise` added to **`VoxelForge.Build.cs`**, clearly +marked as a temporary experiment with removal instructions and a read-the-result guide. + +`VoxelM.Build.cs` can keep or drop its copy — it is harmless either way and irrelevant to this test. + +**One build now answers everything**, because the WORST-POINT DUMP instrumentation is already in: + +| Result | Meaning | Next | +|---|---|---| +| 454 → **0** | the FP model WAS the cause | remove the line; decide separately whether precise is worth its cost on the hot path (needs a profile) | +| 454 → **454** | real logic difference | remove the line; read the dump — identical recovered carve ⇒ fault after the conversion, differing carve ⇒ fault in the SDF or `SmoothStep01` | + +**UNVERIFIED:** everything about this experiment. + +**Next single action:** rebuild, re-run `MazeEquivalence`, read the two numbers. Phase 1 step 3 stays +paused. + +--- diff --git a/Source/VoxelForge/VoxelForge.Build.cs b/Source/VoxelForge/VoxelForge.Build.cs index 0352c41..cd58d59 100644 --- a/Source/VoxelForge/VoxelForge.Build.cs +++ b/Source/VoxelForge/VoxelForge.Build.cs @@ -11,6 +11,33 @@ public class VoxelForge : ModuleRules // UseExplicitOrSharedPCHs is the modern recommended setting PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; + // ============================================================================ + // ⚠️ TEMPORARY EXPERIMENT — 2026-07-27. REMOVE THIS LINE WHEN THE ANSWER IS IN. + // ============================================================================ + // Testing whether the ~1 ULP residue between GetMazeDensity and its operator-stack + // port (VoxelForge.OpStack.MazeEquivalence: 454 of 20000 samples, 0 crossing the + // isosurface) is caused by the compiler being allowed to reassociate identical + // source differently per translation unit. + // + // FPSemantics is a PER-MODULE property. Setting it on the VoxelM game module does + // NOT affect this one — every line of density code lives in VoxelForge, so the + // switch has to be here to mean anything. (That mistake already cost one build and + // one wrong conclusion.) + // + // UnrealBuildTool's Windows default is /fp:fast ("Default is imprecise FP + // semantics", VCToolChain.cs); every Clang target defaults to precise instead. + // + // READ THE RESULT LIKE THIS: + // 454 -> 0 : the FP model WAS the cause. Then decide separately whether to keep + // precise (it costs vectorisation on the density hot path — the thing + // T2.a's SIMD noise work was buying — for an unmeasured amount). + // 454 -> 454 : the FP model is NOT the cause and the difference is real logic. + // Read the WORST-POINT DUMP the test now prints. + // + // EITHER WAY THIS LINE COMES BACK OUT once measured. Keeping /fp:precise on the hot + // path is a decision that needs a profile, not a leftover from a diagnostic. + FPSemantics = FPSemanticsMode.Precise; + // Modules we depend on: // - Core: Basic types (TArray, FString, etc.) // - CoreUObject: UObject system (UCLASS, UPROPERTY, etc.)