From 954ad2a61ee597b67b978b36898f008885d3adb0 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 14 Jun 2021 11:58:36 +0200 Subject: Reaper: Setup settings and final tuning. --- src/yuzu/configuration/config.cpp | 2 ++ src/yuzu/configuration/configure_graphics_advanced.cpp | 6 ++++++ src/yuzu/configuration/configure_graphics_advanced.h | 1 + src/yuzu/configuration/configure_graphics_advanced.ui | 10 ++++++++++ 4 files changed, 19 insertions(+) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 916a22724..57843ac5a 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -817,6 +817,7 @@ void Config::ReadRendererValues() { QStringLiteral("use_asynchronous_shaders"), false); ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), true); + ReadSettingGlobal(Settings::values.use_caches_gc, QStringLiteral("use_caches_gc"), false); ReadSettingGlobal(Settings::values.bg_red, QStringLiteral("bg_red"), 0.0); ReadSettingGlobal(Settings::values.bg_green, QStringLiteral("bg_green"), 0.0); ReadSettingGlobal(Settings::values.bg_blue, QStringLiteral("bg_blue"), 0.0); @@ -1401,6 +1402,7 @@ void Config::SaveRendererValues() { Settings::values.use_asynchronous_shaders, false); WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, true); + WriteSettingGlobal(QStringLiteral("use_caches_gc"), Settings::values.use_caches_gc, false); // Cast to double because Qt's written float values are not human-readable WriteSettingGlobal(QStringLiteral("bg_red"), Settings::values.bg_red, 0.0); WriteSettingGlobal(QStringLiteral("bg_green"), Settings::values.bg_green, 0.0); diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 35bf9c6be..a9e611125 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp @@ -30,6 +30,7 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); + ui->use_caches_gc->setChecked(Settings::values.use_caches_gc.GetValue()); ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); if (Settings::IsConfiguringGlobal()) { @@ -62,6 +63,8 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, ui->use_asynchronous_shaders, use_asynchronous_shaders); + ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_caches_gc, ui->use_caches_gc, + use_caches_gc); ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, ui->use_fast_gpu_time, use_fast_gpu_time); @@ -101,6 +104,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { ui->use_asynchronous_shaders->setEnabled( Settings::values.use_asynchronous_shaders.UsingGlobal()); ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); + ui->use_caches_gc->setEnabled(Settings::values.use_caches_gc.UsingGlobal()); ui->anisotropic_filtering_combobox->setEnabled( Settings::values.max_anisotropy.UsingGlobal()); @@ -115,6 +119,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { use_asynchronous_shaders); ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, Settings::values.use_fast_gpu_time, use_fast_gpu_time); + ConfigurationShared::SetColoredTristate(ui->use_caches_gc, Settings::values.use_caches_gc, + use_caches_gc); ConfigurationShared::SetColoredComboBox( ui->gpu_accuracy, ui->label_gpu_accuracy, static_cast(Settings::values.gpu_accuracy.GetValue(true))); diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index e61b571c7..9148aacf2 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h @@ -38,4 +38,5 @@ private: ConfigurationShared::CheckState use_assembly_shaders; ConfigurationShared::CheckState use_asynchronous_shaders; ConfigurationShared::CheckState use_fast_gpu_time; + ConfigurationShared::CheckState use_caches_gc; }; diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index 846a30586..3566e9bfa 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui @@ -103,6 +103,16 @@ + + + + Enables garbage collection for the GPU caches, this will try to keep VRAM within 3-4Gb and flush least used textures/buffers. This option may be unsafe on a few games + + + Enable GPU caches garbage collection (unsafe) + + + -- cgit v1.2.3 From 0dd98842bf87bdd0735d187f8d183ef7593ad747 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Mon, 14 Jun 2021 13:42:22 +0200 Subject: Reaper: Address Feedback. --- src/common/common_sizes.h | 1 + src/video_core/buffer_cache/buffer_cache.h | 13 ++++---- src/video_core/surface.cpp | 7 ++++ src/video_core/surface.h | 2 ++ src/video_core/texture_cache/texture_cache.h | 38 ++++++++++++++-------- .../configuration/configure_graphics_advanced.ui | 2 +- 6 files changed, 43 insertions(+), 20 deletions(-) (limited to 'src/yuzu') diff --git a/src/common/common_sizes.h b/src/common/common_sizes.h index 7e9fd968b..d07b7ee5a 100644 --- a/src/common/common_sizes.h +++ b/src/common/common_sizes.h @@ -24,6 +24,7 @@ enum : u64 { Size_128_MB = 128ULL * Size_1_MB, Size_448_MB = 448ULL * Size_1_MB, Size_507_MB = 507ULL * Size_1_MB, + Size_512_MB = 512ULL * Size_1_MB, Size_562_MB = 562ULL * Size_1_MB, Size_1554_MB = 1554ULL * Size_1_MB, Size_2048_MB = 2048ULL * Size_1_MB, diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index a8fb21d92..82a4a10d6 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -16,6 +16,7 @@ #include +#include "common/common_sizes.h" #include "common/common_types.h" #include "common/div_ceil.h" #include "common/microprofile.h" @@ -65,8 +66,8 @@ class BufferCache { static constexpr BufferId NULL_BUFFER_ID{0}; - static constexpr u64 expected_memory = 512ULL * 1024ULL * 1024ULL; - static constexpr u64 critical_memory = 1024ULL * 1024ULL * 1024ULL; + static constexpr u64 EXPECTED_MEMORY = Common::Size_512_MB; + static constexpr u64 CRITICAL_MEMORY = Common::Size_1_GB; using Maxwell = Tegra::Engines::Maxwell3D::Regs; @@ -368,13 +369,13 @@ void BufferCache

::TickFrame() { const bool skip_preferred = hits * 256 < shots * 251; uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0; - const bool activate_gc = enabled_gc && total_used_memory >= expected_memory; + const bool activate_gc = enabled_gc && total_used_memory >= EXPECTED_MEMORY; if (!activate_gc) { return; } - const bool agressive_gc = total_used_memory >= critical_memory; - const u64 ticks_to_destroy = agressive_gc ? 60 : 120; - int num_iterations = agressive_gc ? 64 : 32; + const bool aggressive_gc = total_used_memory >= CRITICAL_MEMORY; + const u64 ticks_to_destroy = aggressive_gc ? 60 : 120; + int num_iterations = aggressive_gc ? 64 : 32; for (; num_iterations > 0; --num_iterations) { if (deletion_iterator == slot_buffers.end()) { deletion_iterator = slot_buffers.begin(); diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index 6308aef94..eb1746265 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp @@ -283,4 +283,11 @@ std::pair GetASTCBlockSize(PixelFormat format) { return {DefaultBlockWidth(format), DefaultBlockHeight(format)}; } +u64 EstimatedDecompressedSize(u64 base_size, PixelFormat format) { + constexpr u64 RGBA8_PIXEL_SIZE = 4; + const u64 base_block_size = static_cast(DefaultBlockWidth(format)) * + static_cast(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE; + return (base_size * base_block_size) / BytesPerBlock(format); +} + } // namespace VideoCore::Surface diff --git a/src/video_core/surface.h b/src/video_core/surface.h index c40ab89d0..1503db81f 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h @@ -462,4 +462,6 @@ bool IsPixelFormatSRGB(PixelFormat format); std::pair GetASTCBlockSize(PixelFormat format); +u64 EstimatedDecompressedSize(u64 base_size, PixelFormat format); + } // namespace VideoCore::Surface diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 8685f4418..8ff6f4e01 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -20,6 +20,7 @@ #include "common/alignment.h" #include "common/common_funcs.h" +#include "common/common_sizes.h" #include "common/common_types.h" #include "common/logging/log.h" #include "common/settings.h" @@ -76,8 +77,8 @@ class TextureCache { /// Sampler ID for bugged sampler ids static constexpr SamplerId NULL_SAMPLER_ID{0}; - static constexpr u64 expected_memory = 1024ULL * 1024ULL * 1024ULL; - static constexpr u64 critical_memory = 2 * 1024ULL * 1024ULL * 1024ULL; + static constexpr u64 EXPECTED_MEMORY = Common::Size_1_GB; + static constexpr u64 CRITICAL_MEMORY = Common::Size_2_GB; using Runtime = typename P::Runtime; using Image = typename P::Image; @@ -394,8 +395,8 @@ void TextureCache

::TickFrame() { ++frame_tick; return; } - const bool high_priority_mode = total_used_memory >= expected_memory; - const bool aggressive_mode = total_used_memory >= critical_memory; + const bool high_priority_mode = total_used_memory >= EXPECTED_MEMORY; + const bool aggressive_mode = total_used_memory >= CRITICAL_MEMORY; const u64 ticks_to_destroy = high_priority_mode ? 60 : 100; int num_iterations = aggressive_mode ? 256 : (high_priority_mode ? 128 : 64); for (; num_iterations > 0; --num_iterations) { @@ -405,7 +406,8 @@ void TextureCache

::TickFrame() { break; } } - const auto [image_id, image] = *deletion_iterator; + auto [image_id, image_tmp] = *deletion_iterator; + Image* image = image_tmp; // fix clang error. const bool is_alias = True(image->flags & ImageFlagBits::Alias); const bool is_bad_overlap = True(image->flags & ImageFlagBits::BadOverlap); const bool must_download = image->IsSafeDownload(); @@ -417,8 +419,8 @@ void TextureCache

::TickFrame() { should_care |= aggressive_mode; if (should_care && image->frame_tick + ticks_needed < frame_tick) { if (is_bad_overlap) { - const bool overlap_check = - std::ranges::all_of(image->overlapping_images, [&](const ImageId& overlap_id) { + const bool overlap_check = std::ranges::all_of( + image->overlapping_images, [&, image](const ImageId& overlap_id) { auto& overlap = slot_images[overlap_id]; return overlap.frame_tick >= image->frame_tick; }); @@ -428,8 +430,8 @@ void TextureCache

::TickFrame() { } } if (!is_bad_overlap && must_download) { - const bool alias_check = - std::ranges::none_of(image->aliased_images, [&](const AliasedImage& alias) { + const bool alias_check = std::ranges::none_of( + image->aliased_images, [&, image](const AliasedImage& alias) { auto& alias_image = slot_images[alias.id]; return (alias_image.frame_tick < image->frame_tick) || (alias_image.modification_tick < image->modification_tick); @@ -1275,8 +1277,13 @@ void TextureCache

::RegisterImage(ImageId image_id) { image.flags |= ImageFlagBits::Registered; ForEachPage(image.cpu_addr, image.guest_size_bytes, [this, image_id](u64 page) { page_table[page].push_back(image_id); }); - total_used_memory += - Common::AlignUp(std::max(image.guest_size_bytes, image.unswizzled_size_bytes), 1024); + u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); + if ((IsPixelFormatASTC(image.info.format) && + True(image.flags & ImageFlagBits::AcceleratedUpload)) || + True(image.flags & ImageFlagBits::Converted)) { + tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); + } + total_used_memory += Common::AlignUp(tentative_size, 1024); } template @@ -1286,8 +1293,13 @@ void TextureCache

::UnregisterImage(ImageId image_id) { "Trying to unregister an already registered image"); image.flags &= ~ImageFlagBits::Registered; image.flags &= ~ImageFlagBits::BadOverlap; - total_used_memory -= - Common::AlignUp(std::max(image.guest_size_bytes, image.unswizzled_size_bytes), 1024); + u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); + if ((IsPixelFormatASTC(image.info.format) && + True(image.flags & ImageFlagBits::AcceleratedUpload)) || + True(image.flags & ImageFlagBits::Converted)) { + tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); + } + total_used_memory -= Common::AlignUp(tentative_size, 1024); ForEachPage(image.cpu_addr, image.guest_size_bytes, [this, image_id](u64 page) { const auto page_it = page_table.find(page); if (page_it == page_table.end()) { diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index 3566e9bfa..4bab3d074 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui @@ -106,7 +106,7 @@ - Enables garbage collection for the GPU caches, this will try to keep VRAM within 3-4Gb and flush least used textures/buffers. This option may be unsafe on a few games + 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. Enable GPU caches garbage collection (unsafe) -- cgit v1.2.3 From ca6f47c6862a24dfa78f3d25c8b7819636218cdd Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 17 Jun 2021 00:29:48 +0200 Subject: Reaper: Change memory restrictions on TC depending on host memory on VK. --- src/video_core/buffer_cache/buffer_cache.h | 48 +++++++++++----------- src/video_core/renderer_opengl/gl_texture_cache.h | 1 + .../renderer_vulkan/vk_texture_cache.cpp | 4 ++ src/video_core/renderer_vulkan/vk_texture_cache.h | 3 ++ src/video_core/texture_cache/slot_vector.h | 2 +- src/video_core/texture_cache/texture_cache.h | 46 ++++++++++++++------- src/video_core/vulkan_common/vulkan_device.cpp | 14 +++++++ src/video_core/vulkan_common/vulkan_device.h | 9 ++++ .../configuration/configure_graphics_advanced.ui | 2 +- src/yuzu_cmd/default_ini.h | 2 +- 10 files changed, 90 insertions(+), 41 deletions(-) (limited to 'src/yuzu') 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: void TickFrame(); + void RunGarbageCollector(); + void WriteMemory(VAddr cpu_addr, u64 size); void CachedWriteMemory(VAddr cpu_addr, u64 size); @@ -350,29 +352,7 @@ BufferCache

::BufferCache(VideoCore::RasterizerInterface& rasterizer_, } template -void BufferCache

::TickFrame() { - const bool enabled_gc = Settings::values.use_caches_gc.GetValue(); - SCOPE_EXIT({ - ++frame_tick; - delayed_destruction_ring.Tick(); - }); - // Calculate hits and shots and move hit bits to the right - const u32 hits = std::reduce(uniform_cache_hits.begin(), uniform_cache_hits.end()); - const u32 shots = std::reduce(uniform_cache_shots.begin(), uniform_cache_shots.end()); - std::copy_n(uniform_cache_hits.begin(), uniform_cache_hits.size() - 1, - uniform_cache_hits.begin() + 1); - std::copy_n(uniform_cache_shots.begin(), uniform_cache_shots.size() - 1, - uniform_cache_shots.begin() + 1); - uniform_cache_hits[0] = 0; - uniform_cache_shots[0] = 0; - - const bool skip_preferred = hits * 256 < shots * 251; - uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0; - - const bool activate_gc = enabled_gc && total_used_memory >= EXPECTED_MEMORY; - if (!activate_gc) { - return; - } +void BufferCache

::RunGarbageCollector() { const bool aggressive_gc = total_used_memory >= CRITICAL_MEMORY; const u64 ticks_to_destroy = aggressive_gc ? 60 : 120; int num_iterations = aggressive_gc ? 64 : 32; @@ -392,6 +372,28 @@ void BufferCache

::TickFrame() { } } +template +void BufferCache

::TickFrame() { + // Calculate hits and shots and move hit bits to the right + const u32 hits = std::reduce(uniform_cache_hits.begin(), uniform_cache_hits.end()); + const u32 shots = std::reduce(uniform_cache_shots.begin(), uniform_cache_shots.end()); + std::copy_n(uniform_cache_hits.begin(), uniform_cache_hits.size() - 1, + uniform_cache_hits.begin() + 1); + std::copy_n(uniform_cache_shots.begin(), uniform_cache_shots.size() - 1, + uniform_cache_shots.begin() + 1); + uniform_cache_hits[0] = 0; + uniform_cache_shots[0] = 0; + + const bool skip_preferred = hits * 256 < shots * 251; + uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0; + + if (Settings::values.use_caches_gc.GetValue() && total_used_memory >= EXPECTED_MEMORY) { + RunGarbageCollector(); + } + ++frame_tick; + delayed_destruction_ring.Tick(); +} + template void BufferCache

::WriteMemory(VAddr cpu_addr, u64 size) { ForEachBufferInRange(cpu_addr, size, [&](BufferId, Buffer& buffer) { 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 { static constexpr bool ENABLE_VALIDATION = true; static constexpr bool FRAMEBUFFER_BLITS = true; static constexpr bool HAS_EMULATED_COPIES = true; + static constexpr bool HAS_DEVICE_MEMORY_INFO = false; using Runtime = OpenGL::TextureCacheRuntime; 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, }); } +u64 TextureCacheRuntime::GetDeviceLocalMemory() const { + return device.GetDeviceLocalMemory(); +} + Image::Image(TextureCacheRuntime& runtime, const ImageInfo& info_, GPUVAddr gpu_addr_, VAddr cpu_addr_) : 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 { // All known Vulkan drivers can natively handle BGR textures return true; } + + u64 GetDeviceLocalMemory() const; }; class Image : public VideoCommon::ImageBase { @@ -257,6 +259,7 @@ struct TextureCacheParams { static constexpr bool ENABLE_VALIDATION = true; static constexpr bool FRAMEBUFFER_BLITS = false; static constexpr bool HAS_EMULATED_COPIES = false; + static constexpr bool HAS_DEVICE_MEMORY_INFO = true; using Runtime = Vulkan::TextureCacheRuntime; 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: Iterator(SlotVector* slot_vector_, SlotId id_) noexcept : slot_vector{slot_vector_}, id{id_} {} - bool IsValid(const u64* bitset) noexcept { + bool IsValid(const u64* bitset) const noexcept { return ((bitset[id.index / 64] >> (id.index % 64)) & 1) != 0; } 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 { static constexpr bool FRAMEBUFFER_BLITS = P::FRAMEBUFFER_BLITS; /// True when some copies have to be emulated static constexpr bool HAS_EMULATED_COPIES = P::HAS_EMULATED_COPIES; + /// True when the API can provide info about the memory of the device. + static constexpr bool HAS_DEVICE_MEMORY_INFO = P::HAS_DEVICE_MEMORY_INFO; /// Image view ID for null descriptors static constexpr ImageViewId NULL_IMAGE_VIEW_ID{0}; /// Sampler ID for bugged sampler ids static constexpr SamplerId NULL_SAMPLER_ID{0}; - static constexpr u64 EXPECTED_MEMORY = Common::Size_1_GB; - static constexpr u64 CRITICAL_MEMORY = Common::Size_2_GB; + static constexpr u64 DEFAULT_EXPECTED_MEMORY = Common::Size_1_GB; + static constexpr u64 DEFAULT_CRITICAL_MEMORY = Common::Size_2_GB; using Runtime = typename P::Runtime; using Image = typename P::Image; @@ -108,6 +110,9 @@ public: /// Notify the cache that a new frame has been queued void TickFrame(); + /// Runs the Garbage Collector. + void RunGarbageCollector(); + /// Return a constant reference to the given image view id [[nodiscard]] const ImageView& GetImageView(ImageViewId id) const noexcept; @@ -339,6 +344,8 @@ private: bool has_deleted_images = false; u64 total_used_memory = 0; + u64 expected_memory; + u64 critical_memory; SlotVector slot_images; SlotVector slot_image_views; @@ -382,21 +389,23 @@ TextureCache

::TextureCache(Runtime& runtime_, VideoCore::RasterizerInterface& void(slot_samplers.insert(runtime, sampler_descriptor)); deletion_iterator = slot_images.begin(); + + if constexpr (HAS_DEVICE_MEMORY_INFO) { + const auto device_memory = runtime.GetDeviceLocalMemory(); + const u64 possible_expected_memory = (device_memory * 3) / 10; + const u64 possible_critical_memory = (device_memory * 6) / 10; + expected_memory = std::max(possible_expected_memory, DEFAULT_EXPECTED_MEMORY); + critical_memory = std::max(possible_critical_memory, DEFAULT_CRITICAL_MEMORY); + } else { + expected_memory = DEFAULT_EXPECTED_MEMORY; + critical_memory = DEFAULT_CRITICAL_MEMORY; + } } template -void TextureCache

::TickFrame() { - const bool enabled_gc = Settings::values.use_caches_gc.GetValue(); - if (!enabled_gc) { - // @Note(Blinkhawk): compile error with SCOPE_EXIT on msvc. - sentenced_images.Tick(); - sentenced_framebuffers.Tick(); - sentenced_image_view.Tick(); - ++frame_tick; - return; - } - const bool high_priority_mode = total_used_memory >= EXPECTED_MEMORY; - const bool aggressive_mode = total_used_memory >= CRITICAL_MEMORY; +void TextureCache

::RunGarbageCollector() { + const bool high_priority_mode = total_used_memory >= expected_memory; + const bool aggressive_mode = total_used_memory >= critical_memory; const u64 ticks_to_destroy = high_priority_mode ? 60 : 100; int num_iterations = aggressive_mode ? 256 : (high_priority_mode ? 128 : 64); for (; num_iterations > 0; --num_iterations) { @@ -451,11 +460,18 @@ void TextureCache

::TickFrame() { UnregisterImage(image_id); DeleteImage(image_id); if (is_bad_overlap) { - num_iterations++; + ++num_iterations; } } ++deletion_iterator; } +} + +template +void TextureCache

::TickFrame() { + if (Settings::values.use_caches_gc.GetValue()) { + RunGarbageCollector(); + } sentenced_images.Tick(); sentenced_framebuffers.Tick(); 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 } logical = vk::Device::Create(physical, queue_cis, extensions, first_next, dld); + CollectPhysicalMemoryInfo(); CollectTelemetryParameters(); CollectToolingInfo(); @@ -818,6 +819,19 @@ void Device::CollectTelemetryParameters() { } } +void Device::CollectPhysicalMemoryInfo() { + const auto mem_properties = physical.GetMemoryProperties(); + const std::size_t num_properties = mem_properties.memoryTypeCount; + device_access_memory = 0; + for (std::size_t element = 0; element < num_properties; element++) { + if ((mem_properties.memoryTypes[element].propertyFlags & + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0) { + const std::size_t heap_index = mem_properties.memoryTypes[element].heapIndex; + device_access_memory += mem_properties.memoryHeaps[heap_index].size; + } + } +} + void Device::CollectToolingInfo() { if (!ext_tooling_info) { 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: return use_asynchronous_shaders; } + u64 GetDeviceLocalMemory() const { + return device_access_memory; + } + private: /// Checks if the physical device is suitable. void CheckSuitability(bool requires_swapchain) const; @@ -244,6 +248,9 @@ private: /// Collects information about attached tools. void CollectToolingInfo(); + /// Collects information about the device's local memory. + void CollectPhysicalMemoryInfo(); + /// Returns a list of queue initialization descriptors. std::vector GetDeviceQueueCreateInfos() const; @@ -302,6 +309,8 @@ private: /// Nsight Aftermath GPU crash tracker std::unique_ptr nsight_aftermath_tracker; + + u64 device_access_memory; }; } // 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 @@ 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. - Enable GPU caches garbage collection (unsafe) + Enable GPU cache garbage collection (unsafe) 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 = # 0: Off, 1 (default): On use_vsync = -# Whether to use garbage collection or not. +# Whether to use garbage collection or not for GPU caches. # 0 (default): Off, 1: On use_caches_gc = -- cgit v1.2.3 From 865dd615ca05be7599dd9f866daff670877a27c3 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 20 Jun 2021 12:35:19 +0200 Subject: Reaper: Upgrade label from unsafe to experimental as no regressions are known now. --- src/yuzu/configuration/configure_graphics_advanced.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/yuzu') diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index eaf55c517..ad0840355 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui @@ -109,7 +109,7 @@ 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. - Enable GPU cache garbage collection (unsafe) + Enable GPU cache garbage collection (experimental) -- cgit v1.2.3