diff options
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.cpp | 4 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_texture_cache.h | 2 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 23 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 1 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.cpp | 10 | ||||
| -rw-r--r-- | src/video_core/vulkan_common/vulkan_device.h | 8 |
6 files changed, 45 insertions, 3 deletions
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp index 09e7961ff9..cb0453c178 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp @@ -2082,6 +2082,10 @@ u64 TextureCacheRuntime::GetDeviceMemoryBudget() const { return device.GetDeviceMemoryBudget(); } +u64 TextureCacheRuntime::GetDeviceMemorySlack() const { + return device.GetDeviceMemorySlack(); +} + bool TextureCacheRuntime::CanDownloadMsaa(const VideoCommon::ImageInfo& info) const { const VkImageAspectFlags aspect_mask = ImageAspectMask(info.format); if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != 0) { diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h index 5ac833e787..d5f8756486 100644 --- a/src/video_core/renderer_vulkan/vk_texture_cache.h +++ b/src/video_core/renderer_vulkan/vk_texture_cache.h @@ -74,6 +74,8 @@ public: u64 GetDeviceMemoryBudget() const; + u64 GetDeviceMemorySlack() const; + bool CanReportMemoryUsage() const; /// Images that did not fit the device memory budget so far (see MemoryAllocator). diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index cf042c1488..45bc35dee6 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -313,14 +313,33 @@ void TextureCache<P>::TickFrame() { if (budget > 2_GiB) { const u64 old_critical = critical_memory; const u64 margin = (std::min)(budget / 8, 1_GiB); - critical_memory = budget - (std::min)(margin + pressure_margin, budget / 2); + if constexpr (requires { runtime.GetDeviceMemorySlack(); }) { + // The usage counted here leaves out the unused part of the allocator's + // blocks, which the driver counts and a full heap cannot hand to a new + // image (RX 7800 XT: 1.06 GiB of it, the whole margin, with the heap at + // its budget for a minute before images stopped fitting). Reserve it + // too: at once when it grows, slowly when it shrinks, so evicting images + // (which leaves partly used blocks) does not chase the threshold down. + const u64 slack = (std::min)(runtime.GetDeviceMemorySlack(), 1536_MiB); + slack_margin = slack >= slack_margin + ? slack + : slack_margin - (std::min)(slack_margin - slack, 16_MiB); + } + critical_memory = + budget - (std::min)(margin + pressure_margin + slack_margin, budget / 2); expected_memory = critical_memory - (std::min)(margin, critical_memory / 2); // Log the first values and real changes (the budget moves by a few MiB all // the time). const u64 change = critical_memory > old_critical ? critical_memory - old_critical : old_critical - critical_memory; - ApplyThresholdOverrides(budget_check_frames == 1 || change >= 256_MiB); + const bool log = budget_check_frames == 1 || change >= 256_MiB; + ApplyThresholdOverrides(log); + if (log) { + LOG_INFO(HW_GPU, + "Memory margins: base {} MiB, out of memory {} MiB, block slack {} MiB", + margin >> 20, pressure_margin >> 20, slack_margin >> 20); + } } } } diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 1a6931d18a..24ebaf0689 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -139,6 +139,7 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI u32 seen_pressure_events{}; ///< Allocator pressure events already answered u64 pressure_margin{}; ///< Extra room under the budget after images did not fit u64 pressure_quiet_frames{}; ///< Frames since the last such image + u64 slack_margin{}; ///< Extra room for allocator block space the driver counts as used u64 astc_opaque_images{}; u64 astc_alpha_images{}; std::vector<u8> astc_scan_buffer; diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 2ecbd2cb94..01e13cb384 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -1684,6 +1684,16 @@ u64 Device::GetDeviceMemoryUsage() const { return result; } +u64 Device::GetDeviceMemorySlack() const { + if (allocator == nullptr) { + return 0; + } + std::array<VmaBudget, VK_MAX_MEMORY_HEAPS> heap_budgets{}; + vmaGetHeapBudgets(allocator, heap_budgets.data()); + const VmaStatistics& statistics = heap_budgets[main_heap].statistics; + return statistics.blockBytes - (std::min)(statistics.blockBytes, statistics.allocationBytes); +} + u64 Device::GetDeviceMemoryBudget() const { if (!extensions.memory_budget) { return 0; diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 2d19321145..622d792210 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h @@ -1019,9 +1019,15 @@ FN_MAX_LIMIT_LIST /// The driver's current memory budget for this process (VK_EXT_memory_budget), in /// GetDeviceMemoryUsage() terms: the usage at which the main device-local heap reaches its - /// budget. 0 without the extension. + /// budget. 0 without the extension. The unused part of the allocator's blocks is not + /// subtracted: see GetDeviceMemorySlack(). u64 GetDeviceMemoryBudget() const; + /// Memory the allocator holds from the driver in the main device-local heap but has no + /// allocation in (the unused part of its blocks). GetDeviceMemoryUsage() does not count it, + /// yet the driver does: with the heap at its budget it is not available to new images. + u64 GetDeviceMemorySlack() const; + u32 GetSetsPerPool() const { return sets_per_pool; } |
