summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2021-06-17 00:29:48 +0200
committerGravatar Fernando Sahmkow2021-06-17 00:29:48 +0200
commitca6f47c6862a24dfa78f3d25c8b7819636218cdd (patch)
treed45fea664fa1e1d4de04b206289f638ffe1ceedc
parentReaper: Address Feedback. (diff)
downloadyuzu-ca6f47c6862a24dfa78f3d25c8b7819636218cdd.tar.gz
yuzu-ca6f47c6862a24dfa78f3d25c8b7819636218cdd.tar.xz
yuzu-ca6f47c6862a24dfa78f3d25c8b7819636218cdd.zip
Reaper: Change memory restrictions on TC depending on host memory on VK.
-rw-r--r--src/video_core/buffer_cache/buffer_cache.h48
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h1
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h3
-rw-r--r--src/video_core/texture_cache/slot_vector.h2
-rw-r--r--src/video_core/texture_cache/texture_cache.h46
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp14
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h9
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.ui2
-rw-r--r--src/yuzu_cmd/default_ini.h2
10 files changed, 90 insertions, 41 deletions
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h
index 82a4a10d6..6d04d00da 100644
--- a/src/video_core/buffer_cache/buffer_cache.h
+++ b/src/video_core/buffer_cache/buffer_cache.h
@@ -106,6 +106,8 @@ public:
106 106
107 void TickFrame(); 107 void TickFrame();
108 108
109 void RunGarbageCollector();
110
109 void WriteMemory(VAddr cpu_addr, u64 size); 111 void WriteMemory(VAddr cpu_addr, u64 size);
110 112
111 void CachedWriteMemory(VAddr cpu_addr, u64 size); 113 void CachedWriteMemory(VAddr cpu_addr, u64 size);
@@ -350,29 +352,7 @@ BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_,
350} 352}
351 353
352template <class P> 354template <class P>
353void BufferCache<P>::TickFrame() { 355void BufferCache<P>::RunGarbageCollector() {
354 const bool enabled_gc = Settings::values.use_caches_gc.GetValue();
355 SCOPE_EXIT({
356 ++frame_tick;
357 delayed_destruction_ring.Tick();
358 });
359 // Calculate hits and shots and move hit bits to the right
360 const u32 hits = std::reduce(uniform_cache_hits.begin(), uniform_cache_hits.end());
361 const u32 shots = std::reduce(uniform_cache_shots.begin(), uniform_cache_shots.end());
362 std::copy_n(uniform_cache_hits.begin(), uniform_cache_hits.size() - 1,
363 uniform_cache_hits.begin() + 1);
364 std::copy_n(uniform_cache_shots.begin(), uniform_cache_shots.size() - 1,
365 uniform_cache_shots.begin() + 1);
366 uniform_cache_hits[0] = 0;
367 uniform_cache_shots[0] = 0;
368
369 const bool skip_preferred = hits * 256 < shots * 251;
370 uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0;
371
372 const bool activate_gc = enabled_gc && total_used_memory >= EXPECTED_MEMORY;
373 if (!activate_gc) {
374 return;
375 }
376 const bool aggressive_gc = total_used_memory >= CRITICAL_MEMORY; 356 const bool aggressive_gc = total_used_memory >= CRITICAL_MEMORY;
377 const u64 ticks_to_destroy = aggressive_gc ? 60 : 120; 357 const u64 ticks_to_destroy = aggressive_gc ? 60 : 120;
378 int num_iterations = aggressive_gc ? 64 : 32; 358 int num_iterations = aggressive_gc ? 64 : 32;
@@ -393,6 +373,28 @@ void BufferCache<P>::TickFrame() {
393} 373}
394 374
395template <class P> 375template <class P>
376void BufferCache<P>::TickFrame() {
377 // Calculate hits and shots and move hit bits to the right
378 const u32 hits = std::reduce(uniform_cache_hits.begin(), uniform_cache_hits.end());
379 const u32 shots = std::reduce(uniform_cache_shots.begin(), uniform_cache_shots.end());
380 std::copy_n(uniform_cache_hits.begin(), uniform_cache_hits.size() - 1,
381 uniform_cache_hits.begin() + 1);
382 std::copy_n(uniform_cache_shots.begin(), uniform_cache_shots.size() - 1,
383 uniform_cache_shots.begin() + 1);
384 uniform_cache_hits[0] = 0;
385 uniform_cache_shots[0] = 0;
386
387 const bool skip_preferred = hits * 256 < shots * 251;
388 uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0;
389
390 if (Settings::values.use_caches_gc.GetValue() && total_used_memory >= EXPECTED_MEMORY) {
391 RunGarbageCollector();
392 }
393 ++frame_tick;
394 delayed_destruction_ring.Tick();
395}
396
397template <class P>
396void BufferCache<P>::WriteMemory(VAddr cpu_addr, u64 size) { 398void BufferCache<P>::WriteMemory(VAddr cpu_addr, u64 size) {
397 ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) { 399 ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) {
398 buffer.MarkRegionAsCpuModified(cpu_addr, size); 400 buffer.MarkRegionAsCpuModified(cpu_addr, size);
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index df8be12ff..12c619aca 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -235,6 +235,7 @@ struct TextureCacheParams {
235 static constexpr bool ENABLE_VALIDATION = true; 235 static constexpr bool ENABLE_VALIDATION = true;
236 static constexpr bool FRAMEBUFFER_BLITS = true; 236 static constexpr bool FRAMEBUFFER_BLITS = true;
237 static constexpr bool HAS_EMULATED_COPIES = true; 237 static constexpr bool HAS_EMULATED_COPIES = true;
238 static constexpr bool HAS_DEVICE_MEMORY_INFO = false;
238 239
239 using Runtime = OpenGL::TextureCacheRuntime; 240 using Runtime = OpenGL::TextureCacheRuntime;
240 using Image = OpenGL::Image; 241 using Image = OpenGL::Image;
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 52860b4cf..e8ef6f5c3 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -818,6 +818,10 @@ void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
818 }); 818 });
819} 819}
820 820
821u64 TextureCacheRuntime::GetDeviceLocalMemory() const {
822 return device.GetDeviceLocalMemory();
823}
824
821Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_addr_, 825Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_addr_,
822 VAddr cpu_addr_) 826 VAddr cpu_addr_)
823 : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime.scheduler}, 827 : VideoCommon::ImageBase(info_, gpu_addr_, cpu_addr_), scheduler{&runtime.scheduler},
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 4a57d378b..d392f721b 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -97,6 +97,8 @@ struct TextureCacheRuntime {
97 // All known Vulkan drivers can natively handle BGR textures 97 // All known Vulkan drivers can natively handle BGR textures
98 return true; 98 return true;
99 } 99 }
100
101 u64 GetDeviceLocalMemory() const;
100}; 102};
101 103
102class Image : public VideoCommon::ImageBase { 104class Image : public VideoCommon::ImageBase {
@@ -257,6 +259,7 @@ struct TextureCacheParams {
257 static constexpr bool ENABLE_VALIDATION = true; 259 static constexpr bool ENABLE_VALIDATION = true;
258 static constexpr bool FRAMEBUFFER_BLITS = false; 260 static constexpr bool FRAMEBUFFER_BLITS = false;
259 static constexpr bool HAS_EMULATED_COPIES = false; 261 static constexpr bool HAS_EMULATED_COPIES = false;
262 static constexpr bool HAS_DEVICE_MEMORY_INFO = true;
260 263
261 using Runtime = Vulkan::TextureCacheRuntime; 264 using Runtime = Vulkan::TextureCacheRuntime;
262 using Image = Vulkan::Image; 265 using Image = Vulkan::Image;
diff --git a/src/video_core/texture_cache/slot_vector.h b/src/video_core/texture_cache/slot_vector.h
index 1259e8263..6180b8c0e 100644
--- a/src/video_core/texture_cache/slot_vector.h
+++ b/src/video_core/texture_cache/slot_vector.h
@@ -79,7 +79,7 @@ public:
79 Iterator(SlotVector<T>* slot_vector_, SlotId id_) noexcept 79 Iterator(SlotVector<T>* slot_vector_, SlotId id_) noexcept
80 : slot_vector{slot_vector_}, id{id_} {} 80 : slot_vector{slot_vector_}, id{id_} {}
81 81
82 bool IsValid(const u64* bitset) noexcept { 82 bool IsValid(const u64* bitset) const noexcept {
83 return ((bitset[id.index / 64] >> (id.index % 64)) & 1) != 0; 83 return ((bitset[id.index / 64] >> (id.index % 64)) & 1) != 0;
84 } 84 }
85 85
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 8ff6f4e01..64b576cbc 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -71,14 +71,16 @@ class TextureCache {
71 static constexpr bool FRAMEBUFFER_BLITS = P::FRAMEBUFFER_BLITS; 71 static constexpr bool FRAMEBUFFER_BLITS = P::FRAMEBUFFER_BLITS;
72 /// True when some copies have to be emulated 72 /// True when some copies have to be emulated
73 static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES; 73 static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES;
74 /// True when the API can provide info about the memory of the device.
75 static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO;
74 76
75 /// Image view ID for null descriptors 77 /// Image view ID for null descriptors
76 static constexpr ImageViewId NULL_IMAGE_VIEW_ID{0}; 78 static constexpr ImageViewId NULL_IMAGE_VIEW_ID{0};
77 /// Sampler ID for bugged sampler ids 79 /// Sampler ID for bugged sampler ids
78 static constexpr SamplerId NULL_SAMPLER_ID{0}; 80 static constexpr SamplerId NULL_SAMPLER_ID{0};
79 81
80 static constexpr u64 EXPECTED_MEMORY = Common::Size_1_GB; 82 static constexpr u64 DEFAULT_EXPECTED_MEMORY = Common::Size_1_GB;
81 static constexpr u64 CRITICAL_MEMORY = Common::Size_2_GB; 83 static constexpr u64 DEFAULT_CRITICAL_MEMORY = Common::Size_2_GB;
82 84
83 using Runtime = typename P::Runtime; 85 using Runtime = typename P::Runtime;
84 using Image = typename P::Image; 86 using Image = typename P::Image;
@@ -108,6 +110,9 @@ public:
108 /// Notify the cache that a new frame has been queued 110 /// Notify the cache that a new frame has been queued
109 void TickFrame(); 111 void TickFrame();
110 112
113 /// Runs the Garbage Collector.
114 void RunGarbageCollector();
115
111 /// Return a constant reference to the given image view id 116 /// Return a constant reference to the given image view id
112 [[nodiscard]] const ImageView& GetImageView(ImageViewId id) const noexcept; 117 [[nodiscard]] const ImageView& GetImageView(ImageViewId id) const noexcept;
113 118
@@ -339,6 +344,8 @@ private:
339 344
340 bool has_deleted_images = false; 345 bool has_deleted_images = false;
341 u64 total_used_memory = 0; 346 u64 total_used_memory = 0;
347 u64 expected_memory;
348 u64 critical_memory;
342 349
343 SlotVector<Image> slot_images; 350 SlotVector<Image> slot_images;
344 SlotVector<ImageView> slot_image_views; 351 SlotVector<ImageView> slot_image_views;
@@ -382,21 +389,23 @@ TextureCache<P>::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface&
382 void(slot_samplers.insert(runtime, sampler_descriptor)); 389 void(slot_samplers.insert(runtime, sampler_descriptor));
383 390
384 deletion_iterator = slot_images.begin(); 391 deletion_iterator = slot_images.begin();
392
393 if constexpr (HAS_DEVICE_MEMORY_INFO) {
394 const auto device_memory = runtime.GetDeviceLocalMemory();
395 const u64 possible_expected_memory = (device_memory * 3) / 10;
396 const u64 possible_critical_memory = (device_memory * 6) / 10;
397 expected_memory = std::max(possible_expected_memory, DEFAULT_EXPECTED_MEMORY);
398 critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY);
399 } else {
400 expected_memory = DEFAULT_EXPECTED_MEMORY;
401 critical_memory = DEFAULT_CRITICAL_MEMORY;
402 }
385} 403}
386 404
387template <class P> 405template <class P>
388void TextureCache<P>::TickFrame() { 406void TextureCache<P>::RunGarbageCollector() {
389 const bool enabled_gc = Settings::values.use_caches_gc.GetValue(); 407 const bool high_priority_mode = total_used_memory >= expected_memory;
390 if (!enabled_gc) { 408 const bool aggressive_mode = total_used_memory >= critical_memory;
391 // @Note(Blinkhawk): compile error with SCOPE_EXIT on msvc.
392 sentenced_images.Tick();
393 sentenced_framebuffers.Tick();
394 sentenced_image_view.Tick();
395 ++frame_tick;
396 return;
397 }
398 const bool high_priority_mode = total_used_memory >= EXPECTED_MEMORY;
399 const bool aggressive_mode = total_used_memory >= CRITICAL_MEMORY;
400 const u64 ticks_to_destroy = high_priority_mode ? 60 : 100; 409 const u64 ticks_to_destroy = high_priority_mode ? 60 : 100;
401 int num_iterations = aggressive_mode ? 256 : (high_priority_mode ? 128 : 64); 410 int num_iterations = aggressive_mode ? 256 : (high_priority_mode ? 128 : 64);
402 for (; num_iterations > 0; --num_iterations) { 411 for (; num_iterations > 0; --num_iterations) {
@@ -451,11 +460,18 @@ void TextureCache<P>::TickFrame() {
451 UnregisterImage(image_id); 460 UnregisterImage(image_id);
452 DeleteImage(image_id); 461 DeleteImage(image_id);
453 if (is_bad_overlap) { 462 if (is_bad_overlap) {
454 num_iterations++; 463 ++num_iterations;
455 } 464 }
456 } 465 }
457 ++deletion_iterator; 466 ++deletion_iterator;
458 } 467 }
468}
469
470template <class P>
471void TextureCache<P>::TickFrame() {
472 if (Settings::values.use_caches_gc.GetValue()) {
473 RunGarbageCollector();
474 }
459 sentenced_images.Tick(); 475 sentenced_images.Tick();
460 sentenced_framebuffers.Tick(); 476 sentenced_framebuffers.Tick();
461 sentenced_image_view.Tick(); 477 sentenced_image_view.Tick();
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 64206b3d2..724a0141c 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -408,6 +408,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
408 } 408 }
409 logical = vk::Device::Create(physical, queue_cis, extensions, first_next, dld); 409 logical = vk::Device::Create(physical, queue_cis, extensions, first_next, dld);
410 410
411 CollectPhysicalMemoryInfo();
411 CollectTelemetryParameters(); 412 CollectTelemetryParameters();
412 CollectToolingInfo(); 413 CollectToolingInfo();
413 414
@@ -818,6 +819,19 @@ void Device::CollectTelemetryParameters() {
818 } 819 }
819} 820}
820 821
822void Device::CollectPhysicalMemoryInfo() {
823 const auto mem_properties = physical.GetMemoryProperties();
824 const std::size_t num_properties = mem_properties.memoryTypeCount;
825 device_access_memory = 0;
826 for (std::size_t element = 0; element < num_properties; element++) {
827 if ((mem_properties.memoryTypes[element].propertyFlags &
828 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) {
829 const std::size_t heap_index = mem_properties.memoryTypes[element].heapIndex;
830 device_access_memory += mem_properties.memoryHeaps[heap_index].size;
831 }
832 }
833}
834
821void Device::CollectToolingInfo() { 835void Device::CollectToolingInfo() {
822 if (!ext_tooling_info) { 836 if (!ext_tooling_info) {
823 return; 837 return;
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index 67d70cd22..a1aba973b 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -225,6 +225,10 @@ public:
225 return use_asynchronous_shaders; 225 return use_asynchronous_shaders;
226 } 226 }
227 227
228 u64 GetDeviceLocalMemory() const {
229 return device_access_memory;
230 }
231
228private: 232private:
229 /// Checks if the physical device is suitable. 233 /// Checks if the physical device is suitable.
230 void CheckSuitability(bool requires_swapchain) const; 234 void CheckSuitability(bool requires_swapchain) const;
@@ -244,6 +248,9 @@ private:
244 /// Collects information about attached tools. 248 /// Collects information about attached tools.
245 void CollectToolingInfo(); 249 void CollectToolingInfo();
246 250
251 /// Collects information about the device's local memory.
252 void CollectPhysicalMemoryInfo();
253
247 /// Returns a list of queue initialization descriptors. 254 /// Returns a list of queue initialization descriptors.
248 std::vector<VkDeviceQueueCreateInfo> GetDeviceQueueCreateInfos() const; 255 std::vector<VkDeviceQueueCreateInfo> GetDeviceQueueCreateInfos() const;
249 256
@@ -302,6 +309,8 @@ private:
302 309
303 /// Nsight Aftermath GPU crash tracker 310 /// Nsight Aftermath GPU crash tracker
304 std::unique_ptr<NsightAftermathTracker> nsight_aftermath_tracker; 311 std::unique_ptr<NsightAftermathTracker> nsight_aftermath_tracker;
312
313 u64 device_access_memory;
305}; 314};
306 315
307} // namespace Vulkan 316} // namespace Vulkan
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui
index 4bab3d074..eaf55c517 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.ui
+++ b/src/yuzu/configuration/configure_graphics_advanced.ui
@@ -109,7 +109,7 @@
109 <string>Enables garbage collection for the GPU caches, this will try to keep VRAM within 3-4 GB by flushing the least used textures/buffers. May cause issues in a few games.</string> 109 <string>Enables garbage collection for the GPU caches, this will try to keep VRAM within 3-4 GB by flushing the least used textures/buffers. May cause issues in a few games.</string>
110 </property> 110 </property>
111 <property name="text"> 111 <property name="text">
112 <string>Enable GPU caches garbage collection (unsafe)</string> 112 <string>Enable GPU cache garbage collection (unsafe)</string>
113 </property> 113 </property>
114 </widget> 114 </widget>
115 </item> 115 </item>
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 839919062..f0a0ec398 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -227,7 +227,7 @@ use_asynchronous_gpu_emulation =
227# 0: Off, 1 (default): On 227# 0: Off, 1 (default): On
228use_vsync = 228use_vsync =
229 229
230# Whether to use garbage collection or not. 230# Whether to use garbage collection or not for GPU caches.
231# 0 (default): Off, 1: On 231# 0 (default): Off, 1: On
232use_caches_gc = 232use_caches_gc =
233 233