Download a ComputeMeshBuffer's current live geometry to CPU.
ComputeMeshBuffer's own doc states its live rendering path never reads back vertex data; this is the deliberate, one-shot exception for export. Reads the true live vertex count off the atomic counter buffer's mapped pointer (host-visible, no transfer), then downloads exactly that many vertices from the buffer itself, not its worst-case allocated capacity. The result is non-indexed triangles, so a trivial sequential index array (0..N-1) is synthesized to satisfy Kakshya::MeshData's index requirement.
292{
294 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
"download_compute_mesh: null buffer");
295 return std::nullopt;
296 }
297
298 auto processor =
buffer->get_mesh_processor();
299 if (!processor) {
300 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
301 "download_compute_mesh: no mesh processor; setup_processors() has not been called");
302 return std::nullopt;
303 }
304
305 auto counter_buf = processor->counter_buf();
306 const auto* counter_ptr = counter_buf
307 ? static_cast<const uint32_t*>(counter_buf->get_mapped_ptr())
308 : nullptr;
309 if (!counter_ptr) {
310 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
311 "download_compute_mesh: counter buffer is not host-visible or not allocated yet");
312 return std::nullopt;
313 }
314
315 const uint32_t vertex_count = *counter_ptr;
316 if (vertex_count == 0) {
317 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
318 "download_compute_mesh: live vertex count is zero");
319 return std::nullopt;
320 }
321
322 std::vector<Kakshya::MeshVertex> verts(vertex_count);
323 std::shared_ptr<Buffers::VKBuffer> staging;
324 Buffers::download_from_gpu_async(
325 buffer, verts.data(), verts.size() *
sizeof(Kakshya::MeshVertex), staging);
326
327 std::vector<uint32_t> indices(vertex_count);
328 std::ranges::iota(indices, 0U);
329
330 auto mesh_data = Kakshya::MeshData::empty();
331 Kakshya::MeshInsertion ins(mesh_data.vertex_variant, mesh_data.index_variant);
332 ins.insert_flat(
333 std::span<const uint8_t>(
334 reinterpret_cast<const uint8_t*>(verts.data()),
335 verts.size() * sizeof(Kakshya::MeshVertex)),
336 std::span<const uint32_t>(indices),
337 Kakshya::VertexLayout::for_meshes(sizeof(Kakshya::MeshVertex)));
338 auto access = ins.build();
339 if (!access) {
340 MF_ERROR(Journal::Component::IO, Journal::Context::FileIO,
341 "download_compute_mesh: MeshInsertion::build() failed");
342 return std::nullopt;
343 }
344 mesh_data.layout = access->layout;
345
346 return mesh_data;
347}
#define MF_ERROR(comp, ctx,...)
std::shared_ptr< NetworkGeometryBuffer > buffer