perf(mesh): dirty-range vertex upload for deforming-mesh Refit (#119)
Mesh::Refit re-uploaded the entire vertex array every frame on the in-place UPDATE path (full host write + flush + barrier on the direct path; full re-stage + copy on the staged path), even when only a handful of vertices moved. Add VulkanBuffer::UploadDeviceLocalRange — a dirty-range counterpart to UploadDeviceLocal that writes/flushes/stages/copies and barriers only the half-open element range [offset, offset+count) of an already-allocated device-local buffer. It picks direct-map vs staged-copy from the memory type the buffer was actually allocated with (not the sub-range size, which PreferDirectDeviceWrite would mis-route), and the direct path's ranged flush is rounded to nonCoherentAtomSize and clamped to the allocation size (mappedSize is now recorded for every buffer, not just mapped ones). Add a dirty-range Refit overload taking the full vertex/index arrays plus a (dirtyVertexOffset, dirtyVertexCount) window. The full-span Refit now delegates to it with the whole array as the window. On the in-place UPDATE path only the declared window is uploaded — the rest of the device buffer retains last refit's positions; when an UPDATE isn't possible it falls back to the full-span rebuild, which is why the full arrays are still passed. The WebGPU/DOM backend keeps API symmetry: it has no hardware AS, so it ignores the window and rebuilds the host BVH from the full geometry. BLASBuildOptions exercises the dirty-range refit on the direct path, the staged path, and the count-change rebuild fallback, asserting AS-handle / blasAddr stability and zero Vulkan validation errors. Resolves #119 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
5948bb91c1
commit
1f4c77000a
5 changed files with 199 additions and 8 deletions
|
|
@ -377,6 +377,18 @@ void Mesh::Refit(std::span<Vector<float, 3, 3>> vertices,
|
|||
Build(vertices, indices, cmd);
|
||||
}
|
||||
|
||||
void Mesh::Refit(std::span<Vector<float, 3, 3>> vertices,
|
||||
std::span<std::uint32_t> indices,
|
||||
std::uint32_t /*dirtyVertexOffset*/,
|
||||
std::uint32_t /*dirtyVertexCount*/,
|
||||
WebGPUCommandEncoderRef cmd) {
|
||||
// No hardware AS, so there is no sub-range to update in place — the
|
||||
// software path rebuilds the host BVH over the full geometry regardless.
|
||||
// The dirty window only matters to the hardware backend's ranged upload
|
||||
// (#119); here it is ignored and this is identical to the full-span Refit.
|
||||
Build(vertices, indices, cmd);
|
||||
}
|
||||
|
||||
void Mesh::RefitProcedural(std::span<const RTAabb> aabbs,
|
||||
WebGPUCommandEncoderRef cmd) {
|
||||
BuildProcedural(aabbs, opaque, cmd);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue