mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-31 17:06:29 +00:00
ifcviewer: stop the live budget from over-shrinking and from going stale
A 66-model session showed the pool reach a 1938 MB ceiling, the next poll lower the budget to 1756, and the shrink drop 402 MB (73+73+256) for a 182 MB excess, which the pool then spent seconds re-growing. Two causes. The release granularity is whole sub-buffers but the shrink ran "until capacity ≤ target", so the last 36 MB of excess cost a 256 MB sub-buffer. shrinkToCapacity now never undershoots — it releases only while doing so keeps capacity ≥ target, leaving a sub-buffer's worth of excess for the margin to absorb — and the pressure path uses a separate releaseAtLeast(bytes), whose contract is the opposite: free at least what the failed allocation needs, whatever the granularity. Resident geometry is also only evicted once the pool is over budget by half the margin (GpuBudget::shrinkTarget), so report jitter does not trigger a shrink-and-reload. The ceiling was a second old when the pool grew into it, and the upload staging that rides on growth had pushed device free memory to ~74 MB — below the driver's observed refusal point — before the next scheduled poll. pollDeviceMemory now re-derives the budget immediately after any sub-buffer is added, so the next growth decision sees the device as it is. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1657,9 +1657,15 @@ ifcviewer::GpuMemoryInfo ViewportCore::queryDeviceMemory() const {
|
||||
}
|
||||
|
||||
void ViewportCore::pollDeviceMemory() {
|
||||
if (device_vram_poll_timer_.isValid()
|
||||
// Re-derive immediately after the pool has grown: a ceiling computed
|
||||
// from a second-old report can be reached by growth plus the upload
|
||||
// staging that rides on it, leaving the device far below the margin
|
||||
// before the next scheduled poll notices.
|
||||
const bool pool_grew = pool_.sub_buffer_count() != polled_sub_buffer_count_;
|
||||
if (!pool_grew && device_vram_poll_timer_.isValid()
|
||||
&& device_vram_poll_timer_.elapsed() < 1000) return;
|
||||
device_vram_poll_timer_.start();
|
||||
polled_sub_buffer_count_ = pool_.sub_buffer_count();
|
||||
const ifcviewer::GpuMemoryInfo mem = queryDeviceMemory();
|
||||
if (!mem.valid) return;
|
||||
device_vram_used_bytes_ = mem.used_bytes;
|
||||
@@ -1672,12 +1678,10 @@ void ViewportCore::applyBudgetToPool() {
|
||||
if (!budget_.bounded()) return;
|
||||
const std::uint64_t budget = budget_.cache_budget_bytes();
|
||||
pool_.setMaxTotalCapacity(budget);
|
||||
// Whole sub-buffers are the release granularity, so only act once the
|
||||
// excess is worth one; below that the fixed margin covers it.
|
||||
const std::uint64_t capacity = pool_.total_capacity_bytes();
|
||||
if (capacity < budget + BufferPool::MIN_SUB_BUFFER_BYTES) return;
|
||||
const std::uint64_t target = budget_.shrinkTarget(pool_.total_capacity_bytes());
|
||||
if (target == 0) return;
|
||||
const std::uint64_t released = pool_.shrinkToCapacity(
|
||||
budget, [this](int sub_idx) { evictChunksInSubBuffer(sub_idx); });
|
||||
target, [this](int sub_idx) { evictChunksInSubBuffer(sub_idx); });
|
||||
if (released > 0) {
|
||||
const double mb = 1.0 / (1024.0 * 1024.0);
|
||||
Log::info() << "[wgpu] device has less to give: geometry cache budget now "
|
||||
@@ -1712,8 +1716,10 @@ bool ViewportCore::onRequiredAllocationFailed(const char* what, std::uint64_t by
|
||||
return false;
|
||||
}
|
||||
pool_.setMaxTotalCapacity(budget_.cache_budget_bytes());
|
||||
const std::uint64_t released = pool_.shrinkToCapacity(
|
||||
budget_.cache_budget_bytes(),
|
||||
// The budget was just lowered by what the allocation needs; free at
|
||||
// least that much, whatever the sub-buffer granularity.
|
||||
const std::uint64_t released = pool_.releaseAtLeast(
|
||||
capacity_before - budget_.cache_budget_bytes(),
|
||||
[this](int sub_idx) { evictChunksInSubBuffer(sub_idx); });
|
||||
Log::warn() << "[wgpu] out of memory allocating " << what << " ("
|
||||
<< double(bytes) * mb << " MB); geometry cache budget lowered to "
|
||||
|
||||
Reference in New Issue
Block a user