perf(mesh): skip immutable index re-upload on RT refit UPDATE (#68)

A hardware acceleration-structure UPDATE cannot change topology, so the
index buffer is immutable on the Refit UPDATE path. Re-uploading it was a
wasted memcpy + FlushDevice + barrier of unchanged data every refit —
genuinely per-frame for deforming meshes.

Skip the index memcpy and its FlushDevice on the UPDATE branch; the
RecordBLASBuild call still reads the stable, unchanged indexBuffer.address.
The `indicies` span is now read only for its count. Document the API
nuance: a bitwise-different but topologically-equivalent index array is
ignored on refit, consistent with "a refit may only move vertex positions."
The full-rebuild fallback path still re-uploads both buffers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
catbot 2026-06-17 17:34:29 +00:00
commit a55f15d332
2 changed files with 15 additions and 8 deletions

View file

@ -148,10 +148,13 @@ export namespace Crafter {
// a hardware UPDATE-mode build — much cheaper than a rebuild, and the
// BLAS handle / blasAddr are preserved, so TLAS instances referencing
// it stay valid. A hardware update may only move vertex positions,
// not change connectivity; the indices are re-uploaded for symmetry
// with the rebuild path but must describe the same topology. Without
// allowUpdate (or if the counts changed) it falls back to a full
// rebuild. Lifetime contract matches Build: the spans need only
// not change connectivity, so on the UPDATE path only the vertex
// buffer is re-uploaded; the index buffer is left untouched (its
// contents are immutable for an UPDATE). The `indicies` span is read
// only for its count — a bitwise-different but topologically-equivalent
// index array is ignored on refit. Without allowUpdate (or if the
// counts changed) it falls back to a full rebuild, which does re-upload
// both buffers. Lifetime contract matches Build: the spans need only
// outlive this call. Call this per frame to track a deforming mesh.
void Refit(std::span<Vector<float, 3, 3>> verticies, std::span<std::uint32_t> indicies, VkCommandBuffer cmd);
// Procedural analog of Refit: new object-space boxes, same count.