diff options
| author | 2022-01-16 05:05:34 +0100 | |
|---|---|---|
| committer | 2022-03-25 01:51:51 +0100 | |
| commit | 5e982a781201a12c4cee6af2908e4732b4c8d945 (patch) | |
| tree | 480bba2bae6f2618b657e3ddb9729eff65c94c2d | |
| parent | Garbage Collection: Redesign the algorithm to do a better use of memory. (diff) | |
| download | yuzu-5e982a781201a12c4cee6af2908e4732b4c8d945.tar.gz yuzu-5e982a781201a12c4cee6af2908e4732b4c8d945.tar.xz yuzu-5e982a781201a12c4cee6af2908e4732b4c8d945.zip | |
Buffer Cache: Tune to the levels of the new GC.
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 34 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.cpp | 18 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_buffer_cache.h | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.cpp | 12 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_buffer_cache.h | 6 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache_base.h | 2 |
6 files changed, 78 insertions, 6 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 200d792dd..644c6e57e 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -76,8 +76,9 @@ class BufferCache { | |||
| 76 | 76 | ||
| 77 | static constexpr BufferId NULL_BUFFER_ID{0}; | 77 | static constexpr BufferId NULL_BUFFER_ID{0}; |
| 78 | 78 | ||
| 79 | static constexpr u64 EXPECTED_MEMORY = 512_MiB; | 79 | static constexpr s64 DEFAULT_EXPECTED_MEMORY = 512_MiB; |
| 80 | static constexpr u64 CRITICAL_MEMORY = 1_GiB; | 80 | static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB; |
| 81 | static constexpr s64 TARGET_THRESHOLD = 4_GiB; | ||
| 81 | 82 | ||
| 82 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 83 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 83 | 84 | ||
| @@ -436,6 +437,8 @@ private: | |||
| 436 | Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache; | 437 | Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache; |
| 437 | u64 frame_tick = 0; | 438 | u64 frame_tick = 0; |
| 438 | u64 total_used_memory = 0; | 439 | u64 total_used_memory = 0; |
| 440 | u64 minimum_memory = 0; | ||
| 441 | u64 critical_memory = 0; | ||
| 439 | 442 | ||
| 440 | std::array<BufferId, ((1ULL << 39) >> PAGE_BITS)> page_table; | 443 | std::array<BufferId, ((1ULL << 39) >> PAGE_BITS)> page_table; |
| 441 | }; | 444 | }; |
| @@ -451,11 +454,30 @@ BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_, | |||
| 451 | // Ensure the first slot is used for the null buffer | 454 | // Ensure the first slot is used for the null buffer |
| 452 | void(slot_buffers.insert(runtime, NullBufferParams{})); | 455 | void(slot_buffers.insert(runtime, NullBufferParams{})); |
| 453 | common_ranges.clear(); | 456 | common_ranges.clear(); |
| 457 | |||
| 458 | if (!runtime.CanReportMemoryUsage()) { | ||
| 459 | minimum_memory = DEFAULT_EXPECTED_MEMORY; | ||
| 460 | critical_memory = DEFAULT_CRITICAL_MEMORY; | ||
| 461 | return; | ||
| 462 | } | ||
| 463 | |||
| 464 | const s64 device_memory = static_cast<s64>(runtime.GetDeviceLocalMemory()); | ||
| 465 | const s64 min_spacing_expected = device_memory - 1_GiB - 512_MiB; | ||
| 466 | const s64 min_spacing_critical = device_memory - 1_GiB; | ||
| 467 | const s64 mem_tresshold = std::min(device_memory, TARGET_THRESHOLD); | ||
| 468 | const s64 min_vacancy_expected = (6 * mem_tresshold) / 10; | ||
| 469 | const s64 min_vacancy_critical = (3 * mem_tresshold) / 10; | ||
| 470 | minimum_memory = static_cast<u64>( | ||
| 471 | std::max(std::min(device_memory - min_vacancy_expected, min_spacing_expected), | ||
| 472 | DEFAULT_EXPECTED_MEMORY)); | ||
| 473 | critical_memory = static_cast<u64>( | ||
| 474 | std::max(std::min(device_memory - min_vacancy_critical, min_spacing_critical), | ||
| 475 | DEFAULT_CRITICAL_MEMORY)); | ||
| 454 | } | 476 | } |
| 455 | 477 | ||
| 456 | template <class P> | 478 | template <class P> |
| 457 | void BufferCache<P>::RunGarbageCollector() { | 479 | void BufferCache<P>::RunGarbageCollector() { |
| 458 | const bool aggressive_gc = total_used_memory >= CRITICAL_MEMORY; | 480 | const bool aggressive_gc = total_used_memory >= critical_memory; |
| 459 | const u64 ticks_to_destroy = aggressive_gc ? 60 : 120; | 481 | const u64 ticks_to_destroy = aggressive_gc ? 60 : 120; |
| 460 | int num_iterations = aggressive_gc ? 64 : 32; | 482 | int num_iterations = aggressive_gc ? 64 : 32; |
| 461 | const auto clean_up = [this, &num_iterations](BufferId buffer_id) { | 483 | const auto clean_up = [this, &num_iterations](BufferId buffer_id) { |
| @@ -486,7 +508,11 @@ void BufferCache<P>::TickFrame() { | |||
| 486 | const bool skip_preferred = hits * 256 < shots * 251; | 508 | const bool skip_preferred = hits * 256 < shots * 251; |
| 487 | uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0; | 509 | uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0; |
| 488 | 510 | ||
| 489 | if (total_used_memory >= EXPECTED_MEMORY) { | 511 | // If we can obtain the memory info, use it instead of the estimate. |
| 512 | if (runtime.CanReportMemoryUsage()) { | ||
| 513 | total_used_memory = runtime.GetDeviceMemoryUsage(); | ||
| 514 | } | ||
| 515 | if (total_used_memory >= minimum_memory) { | ||
| 490 | RunGarbageCollector(); | 516 | RunGarbageCollector(); |
| 491 | } | 517 | } |
| 492 | ++frame_tick; | 518 | ++frame_tick; |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index d4dd10bb6..45db72e6f 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -135,6 +135,24 @@ BufferCacheRuntime::BufferCacheRuntime(const Device& device_) | |||
| 135 | buffer.Create(); | 135 | buffer.Create(); |
| 136 | glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY); | 136 | glNamedBufferData(buffer.handle, 0x10'000, nullptr, GL_STREAM_COPY); |
| 137 | } | 137 | } |
| 138 | |||
| 139 | device_access_memory = []() -> u64 { | ||
| 140 | if (GLAD_GL_NVX_gpu_memory_info) { | ||
| 141 | GLint cur_avail_mem_kb = 0; | ||
| 142 | glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &cur_avail_mem_kb); | ||
| 143 | return static_cast<u64>(cur_avail_mem_kb) * 1_KiB; | ||
| 144 | } | ||
| 145 | return 2_GiB; // Return minimum requirements | ||
| 146 | }(); | ||
| 147 | } | ||
| 148 | |||
| 149 | u64 BufferCacheRuntime::GetDeviceMemoryUsage() const { | ||
| 150 | if (GLAD_GL_NVX_gpu_memory_info) { | ||
| 151 | GLint cur_avail_mem_kb = 0; | ||
| 152 | glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &cur_avail_mem_kb); | ||
| 153 | return static_cast<u64>(cur_avail_mem_kb) * 1_KiB; | ||
| 154 | } | ||
| 155 | return 2_GiB; | ||
| 138 | } | 156 | } |
| 139 | 157 | ||
| 140 | void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer, | 158 | void BufferCacheRuntime::CopyBuffer(Buffer& dst_buffer, Buffer& src_buffer, |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 7287731b6..86a265fee 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
| @@ -151,6 +151,16 @@ public: | |||
| 151 | use_storage_buffers = use_storage_buffers_; | 151 | use_storage_buffers = use_storage_buffers_; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | u64 GetDeviceLocalMemory() const { | ||
| 155 | return device_access_memory; | ||
| 156 | } | ||
| 157 | |||
| 158 | u64 GetDeviceMemoryUsage() const; | ||
| 159 | |||
| 160 | bool CanReportMemoryUsage() const { | ||
| 161 | return GLAD_GL_NVX_gpu_memory_info; | ||
| 162 | } | ||
| 163 | |||
| 154 | private: | 164 | private: |
| 155 | static constexpr std::array PABO_LUT{ | 165 | static constexpr std::array PABO_LUT{ |
| 156 | GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV, GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV, | 166 | GL_VERTEX_PROGRAM_PARAMETER_BUFFER_NV, GL_TESS_CONTROL_PROGRAM_PARAMETER_BUFFER_NV, |
| @@ -184,6 +194,8 @@ private: | |||
| 184 | std::array<OGLBuffer, VideoCommon::NUM_COMPUTE_UNIFORM_BUFFERS> copy_compute_uniforms; | 194 | std::array<OGLBuffer, VideoCommon::NUM_COMPUTE_UNIFORM_BUFFERS> copy_compute_uniforms; |
| 185 | 195 | ||
| 186 | u32 index_buffer_offset = 0; | 196 | u32 index_buffer_offset = 0; |
| 197 | |||
| 198 | u64 device_access_memory; | ||
| 187 | }; | 199 | }; |
| 188 | 200 | ||
| 189 | struct BufferCacheParams { | 201 | struct BufferCacheParams { |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 5ffd93499..def838c34 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -141,6 +141,18 @@ StagingBufferRef BufferCacheRuntime::DownloadStagingBuffer(size_t size) { | |||
| 141 | return staging_pool.Request(size, MemoryUsage::Download); | 141 | return staging_pool.Request(size, MemoryUsage::Download); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | u64 BufferCacheRuntime::GetDeviceLocalMemory() const { | ||
| 145 | return device.GetDeviceLocalMemory(); | ||
| 146 | } | ||
| 147 | |||
| 148 | u64 BufferCacheRuntime::GetDeviceMemoryUsage() const { | ||
| 149 | return device.GetDeviceMemoryUsage(); | ||
| 150 | } | ||
| 151 | |||
| 152 | bool BufferCacheRuntime::CanReportMemoryUsage() const { | ||
| 153 | return device.CanReportMemoryUsage(); | ||
| 154 | } | ||
| 155 | |||
| 144 | void BufferCacheRuntime::Finish() { | 156 | void BufferCacheRuntime::Finish() { |
| 145 | scheduler.Finish(); | 157 | scheduler.Finish(); |
| 146 | } | 158 | } |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 1ee0d8420..d7fdd18ff 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -65,6 +65,12 @@ public: | |||
| 65 | 65 | ||
| 66 | void Finish(); | 66 | void Finish(); |
| 67 | 67 | ||
| 68 | u64 GetDeviceLocalMemory() const; | ||
| 69 | |||
| 70 | u64 GetDeviceMemoryUsage() const; | ||
| 71 | |||
| 72 | bool CanReportMemoryUsage() const; | ||
| 73 | |||
| 68 | [[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size); | 74 | [[nodiscard]] StagingBufferRef UploadStagingBuffer(size_t size); |
| 69 | 75 | ||
| 70 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); | 76 | [[nodiscard]] StagingBufferRef DownloadStagingBuffer(size_t size); |
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 5dabc344b..b1324edf3 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -60,8 +60,6 @@ class TextureCache { | |||
| 60 | static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; | 60 | static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; |
| 61 | 61 | ||
| 62 | static constexpr s64 TARGET_THRESHOLD = 4_GiB; | 62 | static constexpr s64 TARGET_THRESHOLD = 4_GiB; |
| 63 | static constexpr s64 MIN_VACANCY_EXPECTED = (6 * TARGET_THRESHOLD) / 10; | ||
| 64 | static constexpr s64 MIN_VACANCY_CRITICAL = (3 * TARGET_THRESHOLD) / 10; | ||
| 65 | static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB; | 63 | static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB; |
| 66 | static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB + 625_MiB; | 64 | static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB + 625_MiB; |
| 67 | static constexpr size_t GC_EMERGENCY_COUNTS = 2; | 65 | static constexpr size_t GC_EMERGENCY_COUNTS = 2; |