test(mesh): pin static-build deletion count for #67 staging-release (#110) #112

Merged
catbot merged 1 commit from claude/issue-110 into master 2026-06-17 20:51:19 +02:00
Member

Summary

Issue #110 reported crafter-build test MeshDecompressStagingRelease failing deterministically on the GPU decompress path (RTX 4090 + validation layers): the deletionQueue.size() == 1 assertion saw more than one entry, which also tripped the later "not freed before framesInFlight" check.

Root cause (confirmed at implementations/Crafter.Graphics-Mesh.cpp:175-176): a static (allowUpdate=false) Build cannot refit, so it DeferredClear()s its now-dead per-mesh BLAS scratch in addition to the compressed staging (#67). That is two deferred allocations, not one. The test at the issue's reported commit built statically yet asserted size==1, so the BLAS scratch was exactly the "extra deferred allocation the test doesn't account for" the issue flagged.

The behaviour was already corrected on master by PR #109 (the #73 merge, commit ed9b3f6), which switched the assertion's build to allowUpdate=true so the scratch is retained and only the staging lands in the queue — that's why the test passes on current master.

What this PR does

Hardens that fix so the count can't silently regress. It adds a sibling case that:

  • Builds the same compressed asset with allowUpdate=false,
  • Asserts the deletion queue holds exactly two entries (compressed staging + dead BLAS scratch) — making the "#110 extra deletion" a named, explicitly-tested quantity instead of an implicit code comment,
  • Confirms the static build still produces a non-zero BLAS address with zero validation errors,
  • Confirms both deferred entries retire on schedule (so nothing leaks).

No production code changes — this is test-only regression coverage.

Testing

  • MeshDecompressStagingRelease: all 15 checks PASS (10 existing + 5 new), zero validation errors, on the real GPU decompress path.
  • Full suite green: crafter-build test --jobs=120 passed.

Note: crafter-build test with the default parallel job count fails ~all tests with git pull ... not something we can merge in .git/FETCH_HEAD — a pre-existing race where parallel test builds concurrently git pull the shared external-dep cache (e.g. Vulkan-Headers) and corrupt FETCH_HEAD. Unrelated to this change; --jobs=1 avoids it. Worth a separate fix in crafter-build's external-dep handling.

Resolves #110

🤖 Generated with Claude Code

## Summary Issue #110 reported `crafter-build test MeshDecompressStagingRelease` failing deterministically on the GPU decompress path (RTX 4090 + validation layers): the `deletionQueue.size() == 1` assertion saw more than one entry, which also tripped the later "not freed before framesInFlight" check. **Root cause** (confirmed at `implementations/Crafter.Graphics-Mesh.cpp:175-176`): a *static* (`allowUpdate=false`) `Build` cannot refit, so it `DeferredClear()`s its now-dead per-mesh BLAS scratch **in addition to** the compressed staging (#67). That is two deferred allocations, not one. The test at the issue's reported commit built statically yet asserted `size==1`, so the BLAS scratch was exactly the "extra deferred allocation the test doesn't account for" the issue flagged. The behaviour was **already corrected on master** by PR #109 (the #73 merge, commit `ed9b3f6`), which switched the assertion's build to `allowUpdate=true` so the scratch is retained and only the staging lands in the queue — that's why the test passes on current `master`. ## What this PR does Hardens that fix so the count can't silently regress. It adds a sibling case that: - Builds the same compressed asset with `allowUpdate=false`, - Asserts the deletion queue holds **exactly two** entries (compressed staging + dead BLAS scratch) — making the "#110 extra deletion" a named, explicitly-tested quantity instead of an implicit code comment, - Confirms the static build still produces a non-zero BLAS address with **zero validation errors**, - Confirms both deferred entries retire on schedule (so nothing leaks). No production code changes — this is test-only regression coverage. ## Testing - `MeshDecompressStagingRelease`: all 15 checks PASS (10 existing + 5 new), zero validation errors, on the real GPU decompress path. - Full suite green: `crafter-build test --jobs=1` → **20 passed**. > Note: `crafter-build test` with the default parallel job count fails ~all tests with `git pull ... not something we can merge in .git/FETCH_HEAD` — a pre-existing race where parallel test builds concurrently `git pull` the *shared* external-dep cache (e.g. Vulkan-Headers) and corrupt `FETCH_HEAD`. Unrelated to this change; `--jobs=1` avoids it. Worth a separate fix in crafter-build's external-dep handling. Resolves #110 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Issue #110 reported `crafter-build test MeshDecompressStagingRelease` failing
deterministically on the GPU decompress path: the "exactly one allocation
handed to the deletion queue" assertion saw more than one entry.

Root cause (confirmed at Crafter.Graphics-Mesh.cpp:175-176): a static
(allowUpdate=false) Build cannot refit, so it DeferredClear()s its now-dead
per-mesh BLAS scratch in addition to the compressed staging (#67) — two
deferred allocations, not one. The original test built statically yet asserted
size==1, so the scratch was the unaccounted-for second entry. The behaviour
was already corrected on master by PR #109 (the #73 merge, ed9b3f6), which
switched the assertion's build to allowUpdate=true so the scratch is retained.

This hardens that fix: it adds a sibling case that Builds with allowUpdate=false
and asserts the queue holds exactly TWO entries (staging + dead scratch),
builds with zero validation errors, and that both retire on schedule. The count
the #67 assertion relies on is now a named, explicitly-tested quantity rather
than an implicit comment, so a future change to scratch deferral can't silently
shift it back.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
catbot merged commit 9d9f9d9d2c into master 2026-06-17 20:51:19 +02:00
catbot deleted branch claude/issue-110 2026-06-17 20:51:19 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Catcrafts/Crafter.Graphics!112
No description provided.