mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-07 04:46:25 +00:00
Surface VRAM shortfall to the user and let them unload models
When the geometry in view needs more GPU memory than the cache can hold, the viewer keeps the largest on-screen chunks resident and streams the rest as the camera moves. That is the right degradation, but it was invisible: nothing told the user the scene did not fit, and the only lever was removing or hiding models, neither of which is "keep it in the federation but stop spending GPU memory on it". Viewer core: - ModelGpuData::unloaded, with drawable() = !hidden && !unloaded now the test every cull / draw / pick / streaming pass uses. unloadModel evicts every chunk and releases the model's own buffers; loadModel recreates them from the CPU mirrors (no disk read) and lets chunks stream back. Recompose keeps the CPU instances current while a model is unloaded so a reload sees up-to-date transforms. The MeshGpu/InstanceGpu record builders are factored out so load and reload share them. - FrameStats reports the camera's working set: chunks wanted, how many of those are not resident, and their bytes. - modelVramBytes / isModelUnloaded accessors, forwarded by ViewportWindow. BonsaiViewer: - Models tree gains a memory column (name | MB | eye) refreshed once a second and on load-state changes; unloaded models read "unloaded" in italics. The viewport stays the single authority for the state; SessionState only carries the modelLoadStateChanged notification. - Context menu: "Unload Model" / "Load Model", distinct from hide and remove, reporting the MB freed in the status bar. - Status bar notice, independent of the perf-stats toggle, once the shortfall has persisted for 3 s (a moment of missing chunks after any camera move is normal): "GPU memory full: N of M visible chunks (X MB) not loaded", with a tooltip pointing at Unload. The perf label also shows "N/M chunks waiting". Verified on the GPU: unloading a 497 MB model frees it immediately with the others still rendering; reloading streams all 180 chunks back. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -44,6 +44,15 @@ struct FrameStats {
|
||||
std::uint64_t vram_used_bytes;
|
||||
std::uint64_t vram_capacity_bytes;
|
||||
std::uint64_t vram_budget_bytes;
|
||||
// The camera's working set: chunks the streaming driver wants resident
|
||||
// (in frustum and large enough on screen) and how many of those are
|
||||
// not — i.e. geometry the user should be seeing but is not yet, or
|
||||
// cannot be because it does not fit the cache. Transiently non-zero
|
||||
// after any camera move; persistently non-zero means the scene does
|
||||
// not fit in VRAM.
|
||||
std::uint32_t chunks_wanted;
|
||||
std::uint32_t chunks_wanted_missing;
|
||||
std::uint64_t wanted_missing_bytes; // raw vertex + index bytes of the missing chunks
|
||||
// Whole-device VRAM from the driver (NVML / sysfs, see GpuMemory.h).
|
||||
// Desktop only; zero on web or when no backend could answer, so
|
||||
// consumers must treat 0 as "unknown" rather than as empty.
|
||||
|
||||
Reference in New Issue
Block a user