OverviewFilesCommitsIssuesDocsReleasesPeers

dc-terrain commits / b2bbb4a

gate: prove a tile can arrive at runtime WITHOUT recompiling the shader
The assertion the world-sized table exists for, and it is a string compare: emitted constants are IDENTICAL with and without B 556 bytes, 11 vs 12 tiles Pack the set minus tile B -- what the world looks like before B is fetched from a peer -- and pack it again with B. If those two constant blocks differ, adding a tile means recompiling the density shader, and a world that recompiles on every fetched tile is not a mutable tileset. They are identical. Measured on an RTX 2070 over the real cache: B reads the stub before it arrives -99999.0 B reads real terrain after it arrives 2002.00 m A is untouched by the addition That last one is not decoration: removing B shifts every later tile's index in the packed buffer, so it asserts the TABLE absorbed the reshuffle rather than A quietly following a stale index. CONTROL: a tile outside the world window is dropped, not wrapped 11 packed, 1 refused World now 119x119 from (-59,-59) = 14,161 cells, table 55 KiB. TWO THINGS THE BIGGER WORLD CHANGED, both predicted and both re-measured: The precision residual doubled, 0.001953 -> 0.004150 m, because the world texel extent went 11,776 -> 30,464 and the bound is ULP(u) x slope. Predicted before running it; the bound moved with it (0.148 m) and this is now the FULL-WORLD number rather than a footprint-sized one. The known gap is now MASKED rather than live, and the file says so instead of repeating a claim that stopped being true. hblk_sample_level still clamps world->texel BEFORE the fetch; with a footprint-sized table the clamped edge cell was loaded and returned -3871 m of somebody else's terrain, but with 12 tiles in 14,161 cells the clamp lands on an absent cell and the stub comes back anyway. Live again once tiles reach the world edge. Not asserted, because this cache cannot demonstrate it -- no tile sits at 59. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
b2bbb4a24ebf0b4decdd9b86970b97b0eaa593b6
by plankatron <fleeky@gmail.com> · 2026-09-03T18:31:42.000Z

Changed files (1) +75 -12

tests/test_tile_grid_gpu.cpp +75 -12
……@@ -506,11 +506,24 @@ int main(int argc, char** argv) {
506506 pts.push_back(0.0f); pts.push_back(0.0f);
507507 }
508508
509 HeightGridPack g = erosion_heightmap_pack_tiles(tiles, STUB);
509 // Tile B, on the far side of the hole -- the tile the mutability probe adds.
510 const HeightTileSrc* B = by_coord[(long long)hole_tx * 100000 + (hole_ty + 1)];
511 const int I_B = I_EXACT + N_EXACT;
512 pts.push_back(tile_centre_x(*B));
513 pts.push_back(tile_centre_z(*B));
514 pts.push_back(0.0f); pts.push_back(0.0f);
515
516 // THE WORLD, from map_dc_diffusion.gd: root span = 28 * 2^(OCTREE_DEPTH-1)
517 // * VOXEL_SIZE with OCTREE_DEPTH 16, and a tile is 256 px * 30 m.
518 const HeightWorld world = erosion_heightmap_world(28.0 * (1 << 15) * 1.0,
519 (double)payload * mpp);
520 HeightGridPack g = erosion_heightmap_pack_tiles(tiles, STUB, world);
510521 ok("pack accepted the tile set", g.ok);
511522 if (!g.ok) { printf("\nFAIL cannot continue\n"); return 1; }
512 printf(" grid %dx%d cells from (%d,%d), %d tiles, %.1f MiB\n\n",
513 g.nx, g.ny, g.tx0, g.ty0, g.tiles, g.data.size() * 4.0 / 1048576.0);
523 printf(" world %dx%d cells from (%d,%d) = %d, table %.0f KiB\n",
524 g.nx, g.ny, g.tx0, g.ty0, g.nx * g.ny, g.nx * g.ny * 4.0 / 1024.0);
525 printf(" %d tiles packed, %d refused, %.1f MiB total\n\n",
526 g.tiles, g.rejected, g.data.size() * 4.0 / 1048576.0);
514527
515528 std::vector<float> ref = run_sampler(c, single_tile_consts(*A), false, A->h, pts, "reference");
516529 std::vector<float> got = run_sampler(c, grid_consts(g), true, g.data, pts, "paged");
……@@ -584,7 +597,7 @@ int main(int argc, char** argv) {
584597
585598 printf("\n CONTROL C: swap tx/ty when packing -> probe 1 must FAIL\n");
586599 {
587 HeightGridPack sw = erosion_heightmap_pack_tiles(tiles, STUB, true);
600 HeightGridPack sw = erosion_heightmap_pack_tiles(tiles, STUB, world, true);
588601 if (!sw.ok) { ok("swapped pack built", false); }
589602 else {
590603 std::vector<float> sg = run_sampler(c, grid_consts(sw), true, sw.data, pts, "swapped");
……@@ -595,11 +608,60 @@ int main(int argc, char** argv) {
595608 }
596609 }
597610
598 // REPORTED, NOT ASSERTED. hblk_sample_level clamps world->texel to
599 // HBLK_SIDE[0] before the fetch runs, so a point far outside the grid
600 // resolves to the bbox edge instead of the stub -- a real divergence from
601 // HeightfieldNode::sample_height, and work this gate's scope excludes.
602 printf("\n3. KNOWN GAP (reported, not asserted)\n");
611 printf("\n4. A TILE ARRIVES AT RUNTIME -- and the SHADER DOES NOT CHANGE\n");
612 {
613 // The same set minus B, which is what the world looks like before B is
614 // fetched from a peer.
615 std::vector<HeightTileSrc> without;
616 for (const auto& t : tiles)
617 if (!(t.tx == B->tx && t.ty == B->ty)) without.push_back(t);
618 HeightGridPack g0 = erosion_heightmap_pack_tiles(without, STUB, world);
619 const std::string c0 = grid_consts(g0);
620 const std::string c1 = grid_consts(g);
621
622 // ★ THE ASSERTION THIS WHOLE STEP EXISTS FOR. If the emitted constants
623 // differ, adding a tile means recompiling the density shader, and a
624 // world that recompiles on every fetched tile is not a mutable tileset.
625 snprintf(det, sizeof(det), "%zu bytes, %d vs %d tiles packed",
626 c0.size(), g0.tiles, g.tiles);
627 ok("emitted constants are IDENTICAL with and without B", c0 == c1, det);
628
629 std::vector<float> before = run_sampler(c, c0, true, g0.data, pts, "pre-add");
630 snprintf(det, sizeof(det), "%.1f", before[I_B]);
631 ok("B reads the stub before it arrives", before[I_B] == STUB, det);
632 snprintf(det, sizeof(det), "%.2f m", got[I_B]);
633 ok("B reads real terrain after it arrives", got[I_B] != STUB &&
634 fabsf(got[I_B]) < 9000.0f, det);
635 // Removing B shifts every later tile's index in the packed buffer, so
636 // this also asserts the TABLE absorbed the reshuffle rather than A
637 // silently following a stale index.
638 ok(" and A is untouched by the addition", before[0] == got[0]);
639 }
640
641 printf("\n CONTROL: a tile outside the world window is REFUSED, not wrapped\n");
642 {
643 std::vector<HeightTileSrc> stray = tiles;
644 stray[0].tx = world.tx0 + world.nx + 5;
645 HeightGridPack gs = erosion_heightmap_pack_tiles(stray, STUB, world);
646 snprintf(det, sizeof(det), "%d packed, %d refused", gs.tiles, gs.rejected);
647 ok("the out-of-window tile is dropped", gs.rejected == 1 &&
648 gs.tiles == (int)tiles.size() - 1, det);
649 }
650
651 // REPORTED, NOT ASSERTED, AND NOW LATENT RATHER THAN LIVE.
652 //
653 // hblk_sample_level still clamps world->texel to HBLK_SIDE[0] BEFORE the
654 // fetch runs, so a point outside the world resolves to the edge cell rather
655 // than missing. With a footprint-sized table that edge cell was loaded and
656 // the probe returned -3871 m of somebody else's terrain. With the
657 // WORLD-sized table it is one of 14,161 cells of which 12 are loaded, so
658 // the clamp almost always lands on an absent cell and the stub comes back
659 // anyway -- masking, not fixing.
660 //
661 // It becomes live again the moment tiles reach the world edge. Left
662 // reported rather than asserted because this cache cannot demonstrate it:
663 // no tile sits at tx/ty 59.
664 printf("\n5. KNOWN GAP (reported, not asserted -- currently MASKED)\n");
603665 {
604666 // FAR ON X ONLY, and on tile A's own Z row. Going far on BOTH axes is
605667 // not a test: the second axis's bounds check returns the stub and the
……@@ -610,9 +672,10 @@ int main(int argc, char** argv) {
610672 far_pts.push_back(tile_centre_z(*A));
611673 far_pts.push_back(0.0f); far_pts.push_back(0.0f);
612674 std::vector<float> fg = run_sampler(c, grid_consts(g), true, g.data, far_pts, "far");
613 printf(" far outside the grid returns %.2f m (stub is %.1f)\n", fg[0], STUB);
614 printf(" hblk_sample_level's clamp runs BEFORE the fetch; the CPU twin\n");
615 printf(" returns the stub here. Out of scope for level-0 addressing.\n");
675 printf(" far outside the world returns %.2f m (stub is %.1f)\n", fg[0], STUB);
676 printf(" The clamp still runs before the fetch; it lands on an ABSENT\n");
677 printf(" cell here, so the stub masks it. Live again once tiles reach\n");
678 printf(" the world edge. Out of scope for level-0 addressing.\n");
616679 }
617680
618681 printf("\n%s (%d failure%s)\n\n", g_fails == 0 ? "PASS" : "FAIL", g_fails,