diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 061611bdb7..6066609e45 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -33,10 +33,12 @@ BufferCache

::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, R device_local_memory = runtime.GetDeviceLocalMemory(); const auto thresholds = VideoCommon::MakeReclaimThresholds( device_local_memory, static_cast(TARGET_THRESHOLD), - static_cast(DEFAULT_EXPECTED_MEMORY), static_cast(DEFAULT_CRITICAL_MEMORY)); + static_cast(DEFAULT_EXPECTED_MEMORY), static_cast(DEFAULT_CRITICAL_MEMORY), + HEAP_PRESSURE_HEADROOM); minimum_memory = thresholds.minimum; expected_memory = thresholds.expected; critical_memory = thresholds.critical; + heap_headroom = thresholds.headroom; } template @@ -52,11 +54,11 @@ void BufferCache

::ReclaimInline() { if (num_iterations == 0) { return true; } + --num_iterations; Buffer& buffer = slot_buffers[buffer_id]; if (memory_tracker.IsRegionGpuModified(buffer.CpuAddr(), buffer.SizeBytes())) { return false; } - --num_iterations; DeleteBuffer(buffer_id); return false; }; @@ -116,8 +118,7 @@ void BufferCache

::TickFrame() { heap_pressure = false; if (device_local_memory != 0 && runtime.CanReportMemoryUsage()) { - heap_pressure = runtime.GetDeviceMemoryUsage() + HEAP_PRESSURE_HEADROOM >= - device_local_memory; + heap_pressure = runtime.GetDeviceMemoryUsage() + heap_headroom >= device_local_memory; } if (total_used_memory >= minimum_memory || heap_pressure) { RunGarbageCollector(); @@ -363,6 +364,7 @@ void BufferCache

::DisableGraphicsUniformBuffer(size_t stage, u32 index) { template void BufferCache

::UpdateGraphicsBuffers(bool is_indexed) { + ReclaimInline(); do { channel_state->has_deleted_buffers = false; DoUpdateGraphicsBuffers(is_indexed); @@ -371,6 +373,7 @@ void BufferCache

::UpdateGraphicsBuffers(bool is_indexed) { template void BufferCache

::UpdateComputeBuffers() { + ReclaimInline(); do { channel_state->has_deleted_buffers = false; DoUpdateComputeBuffers(); @@ -1343,7 +1346,7 @@ void BufferCache

::UpdateIndexBuffer() { inline_buffer_id = CreateBuffer(0, buffer_size, false); } if (slot_buffers[inline_buffer_id].SizeBytes() < buffer_size) [[unlikely]] { - slot_buffers.erase(inline_buffer_id); + DeleteBuffer(inline_buffer_id, true); inline_buffer_id = CreateBuffer(0, buffer_size, false); } channel_state->index_buffer = Binding{ @@ -1693,7 +1696,6 @@ void BufferCache

::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, template BufferId BufferCache

::CreateBuffer(DAddr device_addr, u32 wanted_size, bool sparse_compatible) { - ReclaimInline(); DAddr device_addr_end = Common::AlignUp(device_addr + wanted_size, CACHING_PAGESIZE); device_addr = Common::AlignDown(device_addr, CACHING_PAGESIZE); wanted_size = static_cast(device_addr_end - device_addr); @@ -1994,6 +1996,10 @@ void BufferCache

::DeleteBuffer(BufferId buffer_id, bool do_not_mark) { memory_tracker.MarkRegionAsCpuModified(buffer.CpuAddr(), buffer.SizeBytes()); } + if (inline_buffer_id == buffer_id) { + inline_buffer_id = NULL_BUFFER_ID; + } + Unregister(buffer_id); #ifdef YUZU_LEGACY diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index 8afa93b433..b4af2820d5 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -549,6 +549,7 @@ private: u64 minimum_memory = 0; u64 expected_memory = 0; u64 critical_memory = 0; + u64 heap_headroom = 0; bool heap_pressure = false; BufferId inline_buffer_id; #ifdef YUZU_LEGACY diff --git a/src/video_core/cache_reclaim.h b/src/video_core/cache_reclaim.h index aa5c43552f..a8870ea96b 100644 --- a/src/video_core/cache_reclaim.h +++ b/src/video_core/cache_reclaim.h @@ -13,12 +13,14 @@ struct ReclaimThresholds { u64 minimum{}; u64 expected{}; u64 critical{}; + u64 headroom{}; }; [[nodiscard]] constexpr ReclaimThresholds MakeReclaimThresholds(u64 device_local_memory, u64 target_threshold, u64 default_expected, - u64 default_critical) { + u64 default_critical, + u64 default_headroom) { u64 critical = default_critical; if (device_local_memory != 0) { const u64 budget = (std::min)(device_local_memory, target_threshold); @@ -29,6 +31,7 @@ struct ReclaimThresholds { .minimum = (expected * 3) / 4, .expected = expected, .critical = critical, + .headroom = (std::clamp)(device_local_memory / 4, default_headroom, default_headroom * 2), }; } diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 2c3a19eb20..4092036b9e 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -62,10 +62,12 @@ TextureCache

::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag } const auto thresholds = VideoCommon::MakeReclaimThresholds( device_local_memory, static_cast(TARGET_THRESHOLD), - static_cast(DEFAULT_EXPECTED_MEMORY), static_cast(DEFAULT_CRITICAL_MEMORY)); + static_cast(DEFAULT_EXPECTED_MEMORY), static_cast(DEFAULT_CRITICAL_MEMORY), + HEAP_PRESSURE_HEADROOM); minimum_memory = thresholds.minimum; expected_memory = thresholds.expected; critical_memory = thresholds.critical; + heap_headroom = thresholds.headroom; } template @@ -127,8 +129,7 @@ template void TextureCache

::TickFrame() { heap_pressure = false; if (device_local_memory != 0 && runtime.CanReportMemoryUsage()) { - heap_pressure = runtime.GetDeviceMemoryUsage() + HEAP_PRESSURE_HEADROOM >= - device_local_memory; + heap_pressure = runtime.GetDeviceMemoryUsage() + heap_headroom >= device_local_memory; } if (total_used_memory > minimum_memory || heap_pressure) { RunGarbageCollector(); @@ -1320,8 +1321,6 @@ u64 TextureCache

::GetScaledImageSizeBytes(const ImageBase& image) { template void TextureCache

::QueueAsyncDecode(Image& image, ImageId image_id) { UNIMPLEMENTED_IF(False(image.flags & ImageFlagBits::Converted)); - LOG_INFO(HW_GPU, "Queuing async texture decode"); - image.flags |= ImageFlagBits::IsDecoding; auto decode = std::make_unique(); auto* decode_ptr = decode.get(); diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 63b83050e6..7a46134490 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -446,6 +446,7 @@ private: u64 minimum_memory = 0; u64 expected_memory = 0; u64 critical_memory = 0; + u64 heap_headroom = 0; bool heap_pressure = false; struct BufferDownload { @@ -498,8 +499,7 @@ private: u64 modification_tick = 0; u64 frame_tick = 0; - Common::ThreadWorker texture_decode_worker{1, "TextureDecoder", {}, - Common::ThreadPlacement::Efficiency}; + Common::ThreadWorker texture_decode_worker{1, "TextureDecoder"}; std::vector> async_decodes; // Join caching