mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-31 00:46:36 +00:00
ab99024307
Loading enough models drove the chunk pool to the driver's refusal point, after which the first click aborted: the pick attachments are allocated lazily, wgpu-native reported their OOM as a validation error nobody observed, and the invalid views reached wgpuQueueSubmit, which panics across the FFI boundary. Two policy defects compounding: the cache was allowed to take the last byte, and nothing but the pool's own growth was treated as fallible. GPU memory is now two tiers. Required allocations (per-pixel attachments, a model's metadata buffers, readback staging) are eager, deterministic and fallible; the chunk pool is an elastic cache that grows only to a budget and yields whenever a required allocation fails. - GpuBudget (pure, unit-tested): desktop derives the budget from the driver's free-memory report minus a reserve for the attachments at 4K; web keeps the wasm-heap cap; either lowers it on pressure. The budget's source differs per platform, the mechanism does not. - GpuAllocScope: the OOM/Validation error-scope dance in one place, synchronous on wgpu-native, provisional on Dawn-web. BufferPool's inline copy now uses it. - BufferPool::shrinkToCapacity releases whole sub-buffers newest-first after the owner empties them; growth clamps to the budget instead of overshooting. - ViewportCore::allocateRequired runs any required creation under a scope and, on failure, lowers the budget, evicts and releases cache sub-buffers, waits for the device to reclaim them, and retries until it fits or the cache is at its floor. Pick attachments are created with the other attachments in configureSurface; render() skips a frame rather than submit invalid views; a model whose buffers cannot fit is not loaded instead of aborting. Verified on a 4 GB GeForce: the pool clamps itself at the derived budget (256+256+67 MB for a 579 MB budget) and, in a standalone check against the real device, a pool grown to the driver's refusal point observes a failed required allocation, releases 320 MB and succeeds on retry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
68 lines
3.3 KiB
C++
68 lines
3.3 KiB
C++
/********************************************************************************
|
|
* *
|
|
* This file is part of IfcOpenShell. *
|
|
* *
|
|
* IfcOpenShell is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the Lesser GNU General Public License as published by *
|
|
* the Free Software Foundation, either version 3.0 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* IfcOpenShell is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* Lesser GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the Lesser GNU General Public License *
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
********************************************************************************/
|
|
|
|
#ifndef IFCVIEWER_GPUALLOCSCOPE_H
|
|
#define IFCVIEWER_GPUALLOCSCOPE_H
|
|
|
|
#include <webgpu/webgpu.h>
|
|
|
|
#include <functional>
|
|
|
|
// Brackets one or more wgpu resource creations so an out-of-memory is
|
|
// observed instead of silently producing an invalid resource.
|
|
//
|
|
// WebGPU never returns null from createBuffer / createTexture: a failed
|
|
// allocation yields an *error* resource, and the failure is only reported
|
|
// through an error scope. Left unobserved it surfaces later as a validation
|
|
// error on the first use -- and on wgpu-native an invalid attachment in
|
|
// wgpuQueueSubmit is a Rust panic across the FFI boundary, i.e. an abort
|
|
// with no recovery path. So every allocation the renderer cannot do
|
|
// without goes through one of these.
|
|
//
|
|
// Two filters are pushed, not one: wgpu-native classifies "Not enough
|
|
// memory left" as a Validation error, Dawn as OutOfMemory.
|
|
//
|
|
// Desktop and web differ only in *when* the answer arrives. On wgpu-native
|
|
// the scope pops synchronously (the instance is spun until the callback
|
|
// fires) and `end` invokes the callback before returning. On Dawn-web the
|
|
// pop is a promise and spinning would deadlock the JS event loop, so the
|
|
// callback fires later from the event loop; callers use the resource
|
|
// provisionally and correct course in the callback if it turns out bad.
|
|
class GpuAllocScope {
|
|
public:
|
|
using Callback = std::function<void(bool ok)>;
|
|
|
|
GpuAllocScope(WGPUInstance instance, WGPUDevice device);
|
|
~GpuAllocScope();
|
|
|
|
GpuAllocScope(const GpuAllocScope&) = delete;
|
|
GpuAllocScope& operator=(const GpuAllocScope&) = delete;
|
|
|
|
// Pop the scopes and deliver the verdict: `ok` is true when no error
|
|
// fired between construction and here. Must be called exactly once.
|
|
void end(Callback on_result);
|
|
|
|
private:
|
|
WGPUInstance instance_ = nullptr;
|
|
WGPUDevice device_ = nullptr;
|
|
bool ended_ = false;
|
|
};
|
|
|
|
#endif // IFCVIEWER_GPUALLOCSCOPE_H
|