wip(assembler): round L3 -- Core forces FP contraction off and refuses to generate if it can't
CoreNamespacePreamble.h applies per-compiler contraction-off pragmas (Clang, MSVC, GCC; unknown compiler = #error) and a fused-multiply-add self-test that World::compile runs before building. Clang -ffp-contract=on and GCC's default (fast) now reproduce the L1/Windows hashes (they diverged in L2); Clang -ffp-contract=fast ignores the pragma and is refused at startup (negative control). Seed sweep with every cube on real terrain: 48 seeds x 2 recipes x 3 builds x W1/W12, 576 runs, 0 mismatches, 0 empty meshes. Cost +0.5% (2.326 -> 2.337 s, interleaved). World unchanged. MSVC/UBT not compiled here: Windows to-do list in Linux3/REPORT.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
303b7b9f24
commit
046f2af495
10 files changed
+1051
-2
No files matched your search
@@ -54,3 +54,40 @@
|
||||
// value tree shared lets the viewer resolve its reference world and Core snapshot from one parse.
|
||||
#include "Json.h"
|
||||
#include "VoxelForgeCore/VoxelForgeCore.h"
|
||||
|
||||
// Keep Core's expression-level FMA behavior fixed regardless of the toolchain setting.
|
||||
// Clang's "fast" mode ignores the pragma, so Core's runtime self-test rejects that build.
|
||||
#if defined(__clang__)
|
||||
#pragma clang fp contract(off)
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma fp_contract(off)
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC optimize ("fp-contract=off")
|
||||
#else
|
||||
#error "VoxelForge Core requires a compiler-specific FP contraction control"
|
||||
#endif
|
||||
|
||||
namespace vfcore::fp_contract
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
#define VFCORE_FP_PROBE_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
#define VFCORE_FP_PROBE_NOINLINE __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
[[maybe_unused]] static VFCORE_FP_PROBE_NOINLINE double multiplyAddProbe(
|
||||
double a, double b, double c) noexcept
|
||||
{
|
||||
return a * b + c;
|
||||
}
|
||||
|
||||
[[maybe_unused]] static bool selfTest() noexcept
|
||||
{
|
||||
volatile double a = 1.0 + 0x1p-27;
|
||||
volatile double b = 1.0 - 0x1p-27;
|
||||
volatile double c = -1.0;
|
||||
return multiplyAddProbe(a, b, c) == 0.0;
|
||||
}
|
||||
|
||||
#undef VFCORE_FP_PROBE_NOINLINE
|
||||
}
|
||||
@@ -969,6 +969,11 @@ namespace VoxelForgeCore
|
||||
bool World::compile(const ShapeBuildRequest& request,const JobScheduler& scheduler,std::string& error)
|
||||
{
|
||||
if(!impl_->owner){error="resolved world snapshot is empty";return false;}
|
||||
if(!::vfcore::fp_contract::selfTest())
|
||||
{
|
||||
error="Core startup refused: floating-point contraction self-test detected a fused multiply-add; this compiler/flag combination is unsupported for world generation";
|
||||
return false;
|
||||
}
|
||||
auto shape=std::make_unique<FStandaloneShapeWorld>();
|
||||
const bool ok=shape->Build(*impl_->owner,ToNative(request.minVoxel),ToNative(request.maxVoxel),
|
||||
ToNative(request.clipMinVoxel),ToNative(request.clipMaxVoxel),
|
||||
|
||||
Reference in new issue
Block a user