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

@ -357,12 +357,16 @@ void Mesh::Refit(std::span<Vector<float, 3, 3>> verticies, std::span<std::uint32
return;
}
// Same-sized buffers: overwrite in place so the device addresses (and
// thus the geometry the UPDATE reads) stay stable.
// Same-sized buffers: overwrite the vertex positions in place so the
// device address (and thus the geometry the UPDATE reads) stays stable.
// The index buffer is deliberately left untouched: a hardware AS UPDATE
// cannot change topology, so the indices are immutable here — re-uploading
// them would be a wasted memcpy + flush + barrier of unchanged data every
// refit. This means a bitwise-different-but-topologically-equivalent index
// array passed on refit is ignored, consistent with the documented
// contract that a refit may only move vertex positions.
std::memcpy(vertexBuffer.value, verticies.data(), verticies.size() * sizeof(Vector<float, 3, 3>));
std::memcpy(indexBuffer.value, indicies.data(), indicies.size() * sizeof(std::uint32_t));
vertexBuffer.FlushDevice(cmd, VK_ACCESS_MEMORY_READ_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
indexBuffer.FlushDevice(cmd, VK_ACCESS_MEMORY_READ_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR);
RecordBLASBuild(*this, static_cast<std::uint32_t>(verticies.size()), static_cast<std::uint32_t>(indicies.size()), buildFlags, /*update*/ true, cmd);
}