diff options
| -rw-r--r-- | src/common/common_sizes.h | 1 | ||||
| -rw-r--r-- | src/video_core/buffer_cache/buffer_cache.h | 13 | ||||
| -rw-r--r-- | src/video_core/surface.cpp | 7 | ||||
| -rw-r--r-- | src/video_core/surface.h | 2 | ||||
| -rw-r--r-- | src/video_core/texture_cache/texture_cache.h | 38 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_graphics_advanced.ui | 2 |
6 files changed, 43 insertions, 20 deletions
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 { | |||
| 24 | Size_128_MB = 128ULL * Size_1_MB, | 24 | Size_128_MB = 128ULL * Size_1_MB, |
| 25 | Size_448_MB = 448ULL * Size_1_MB, | 25 | Size_448_MB = 448ULL * Size_1_MB, |
| 26 | Size_507_MB = 507ULL * Size_1_MB, | 26 | Size_507_MB = 507ULL * Size_1_MB, |
| 27 | Size_512_MB = 512ULL * Size_1_MB, | ||
| 27 | Size_562_MB = 562ULL * Size_1_MB, | 28 | Size_562_MB = 562ULL * Size_1_MB, |
| 28 | Size_1554_MB = 1554ULL * Size_1_MB, | 29 | Size_1554_MB = 1554ULL * Size_1_MB, |
| 29 | Size_2048_MB = 2048ULL * Size_1_MB, | 30 | 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 @@ | |||
| 16 | 16 | ||
| 17 | #include <boost/container/small_vector.hpp> | 17 | #include <boost/container/small_vector.hpp> |
| 18 | 18 | ||
| 19 | #include "common/common_sizes.h" | ||
| 19 | #include "common/common_types.h" | 20 | #include "common/common_types.h" |
| 20 | #include "common/div_ceil.h" | 21 | #include "common/div_ceil.h" |
| 21 | #include "common/microprofile.h" | 22 | #include "common/microprofile.h" |
| @@ -65,8 +66,8 @@ class BufferCache { | |||
| 65 | 66 | ||
| 66 | static constexpr BufferId NULL_BUFFER_ID{0}; | 67 | static constexpr BufferId NULL_BUFFER_ID{0}; |
| 67 | 68 | ||
| 68 | static constexpr u64 expected_memory = 512ULL * 1024ULL * 1024ULL; | 69 | static constexpr u64 EXPECTED_MEMORY = Common::Size_512_MB; |
| 69 | static constexpr u64 critical_memory = 1024ULL * 1024ULL * 1024ULL; | 70 | static constexpr u64 CRITICAL_MEMORY = Common::Size_1_GB; |
| 70 | 71 | ||
| 71 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 72 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 72 | 73 | ||
| @@ -368,13 +369,13 @@ void BufferCache<P>::TickFrame() { | |||
| 368 | const bool skip_preferred = hits * 256 < shots * 251; | 369 | const bool skip_preferred = hits * 256 < shots * 251; |
| 369 | uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0; | 370 | uniform_buffer_skip_cache_size = skip_preferred ? DEFAULT_SKIP_CACHE_SIZE : 0; |
| 370 | 371 | ||
| 371 | const bool activate_gc = enabled_gc && total_used_memory >= expected_memory; | 372 | const bool activate_gc = enabled_gc && total_used_memory >= EXPECTED_MEMORY; |
| 372 | if (!activate_gc) { | 373 | if (!activate_gc) { |
| 373 | return; | 374 | return; |
| 374 | } | 375 | } |
| 375 | const bool agressive_gc = total_used_memory >= critical_memory; | 376 | const bool aggressive_gc = total_used_memory >= CRITICAL_MEMORY; |
| 376 | const u64 ticks_to_destroy = agressive_gc ? 60 : 120; | 377 | const u64 ticks_to_destroy = aggressive_gc ? 60 : 120; |
| 377 | int num_iterations = agressive_gc ? 64 : 32; | 378 | int num_iterations = aggressive_gc ? 64 : 32; |
| 378 | for (; num_iterations > 0; --num_iterations) { | 379 | for (; num_iterations > 0; --num_iterations) { |
| 379 | if (deletion_iterator == slot_buffers.end()) { | 380 | if (deletion_iterator == slot_buffers.end()) { |
| 380 | deletion_iterator = slot_buffers.begin(); | 381 | 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<u32, u32> GetASTCBlockSize(PixelFormat format) { | |||
| 283 | return {DefaultBlockWidth(format), DefaultBlockHeight(format)}; | 283 | return {DefaultBlockWidth(format), DefaultBlockHeight(format)}; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | u64 EstimatedDecompressedSize(u64 base_size, PixelFormat format) { | ||
| 287 | constexpr u64 RGBA8_PIXEL_SIZE = 4; | ||
| 288 | const u64 base_block_size = static_cast<u64>(DefaultBlockWidth(format)) * | ||
| 289 | static_cast<u64>(DefaultBlockHeight(format)) * RGBA8_PIXEL_SIZE; | ||
| 290 | return (base_size * base_block_size) / BytesPerBlock(format); | ||
| 291 | } | ||
| 292 | |||
| 286 | } // namespace VideoCore::Surface | 293 | } // 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); | |||
| 462 | 462 | ||
| 463 | std::pair<u32, u32> GetASTCBlockSize(PixelFormat format); | 463 | std::pair<u32, u32> GetASTCBlockSize(PixelFormat format); |
| 464 | 464 | ||
| 465 | u64 EstimatedDecompressedSize(u64 base_size, PixelFormat format); | ||
| 466 | |||
| 465 | } // namespace VideoCore::Surface | 467 | } // 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 @@ | |||
| 20 | 20 | ||
| 21 | #include "common/alignment.h" | 21 | #include "common/alignment.h" |
| 22 | #include "common/common_funcs.h" | 22 | #include "common/common_funcs.h" |
| 23 | #include "common/common_sizes.h" | ||
| 23 | #include "common/common_types.h" | 24 | #include "common/common_types.h" |
| 24 | #include "common/logging/log.h" | 25 | #include "common/logging/log.h" |
| 25 | #include "common/settings.h" | 26 | #include "common/settings.h" |
| @@ -76,8 +77,8 @@ class TextureCache { | |||
| 76 | /// Sampler ID for bugged sampler ids | 77 | /// Sampler ID for bugged sampler ids |
| 77 | static constexpr SamplerId NULL_SAMPLER_ID{0}; | 78 | static constexpr SamplerId NULL_SAMPLER_ID{0}; |
| 78 | 79 | ||
| 79 | static constexpr u64 expected_memory = 1024ULL * 1024ULL * 1024ULL; | 80 | static constexpr u64 EXPECTED_MEMORY = Common::Size_1_GB; |
| 80 | static constexpr u64 critical_memory = 2 * 1024ULL * 1024ULL * 1024ULL; | 81 | static constexpr u64 CRITICAL_MEMORY = Common::Size_2_GB; |
| 81 | 82 | ||
| 82 | using Runtime = typename P::Runtime; | 83 | using Runtime = typename P::Runtime; |
| 83 | using Image = typename P::Image; | 84 | using Image = typename P::Image; |
| @@ -394,8 +395,8 @@ void TextureCache<P>::TickFrame() { | |||
| 394 | ++frame_tick; | 395 | ++frame_tick; |
| 395 | return; | 396 | return; |
| 396 | } | 397 | } |
| 397 | const bool high_priority_mode = total_used_memory >= expected_memory; | 398 | const bool high_priority_mode = total_used_memory >= EXPECTED_MEMORY; |
| 398 | const bool aggressive_mode = total_used_memory >= critical_memory; | 399 | const bool aggressive_mode = total_used_memory >= CRITICAL_MEMORY; |
| 399 | const u64 ticks_to_destroy = high_priority_mode ? 60 : 100; | 400 | const u64 ticks_to_destroy = high_priority_mode ? 60 : 100; |
| 400 | int num_iterations = aggressive_mode ? 256 : (high_priority_mode ? 128 : 64); | 401 | int num_iterations = aggressive_mode ? 256 : (high_priority_mode ? 128 : 64); |
| 401 | for (; num_iterations > 0; --num_iterations) { | 402 | for (; num_iterations > 0; --num_iterations) { |
| @@ -405,7 +406,8 @@ void TextureCache<P>::TickFrame() { | |||
| 405 | break; | 406 | break; |
| 406 | } | 407 | } |
| 407 | } | 408 | } |
| 408 | const auto [image_id, image] = *deletion_iterator; | 409 | auto [image_id, image_tmp] = *deletion_iterator; |
| 410 | Image* image = image_tmp; // fix clang error. | ||
| 409 | const bool is_alias = True(image->flags & ImageFlagBits::Alias); | 411 | const bool is_alias = True(image->flags & ImageFlagBits::Alias); |
| 410 | const bool is_bad_overlap = True(image->flags & ImageFlagBits::BadOverlap); | 412 | const bool is_bad_overlap = True(image->flags & ImageFlagBits::BadOverlap); |
| 411 | const bool must_download = image->IsSafeDownload(); | 413 | const bool must_download = image->IsSafeDownload(); |
| @@ -417,8 +419,8 @@ void TextureCache<P>::TickFrame() { | |||
| 417 | should_care |= aggressive_mode; | 419 | should_care |= aggressive_mode; |
| 418 | if (should_care && image->frame_tick + ticks_needed < frame_tick) { | 420 | if (should_care && image->frame_tick + ticks_needed < frame_tick) { |
| 419 | if (is_bad_overlap) { | 421 | if (is_bad_overlap) { |
| 420 | const bool overlap_check = | 422 | const bool overlap_check = std::ranges::all_of( |
| 421 | std::ranges::all_of(image->overlapping_images, [&](const ImageId& overlap_id) { | 423 | image->overlapping_images, [&, image](const ImageId& overlap_id) { |
| 422 | auto& overlap = slot_images[overlap_id]; | 424 | auto& overlap = slot_images[overlap_id]; |
| 423 | return overlap.frame_tick >= image->frame_tick; | 425 | return overlap.frame_tick >= image->frame_tick; |
| 424 | }); | 426 | }); |
| @@ -428,8 +430,8 @@ void TextureCache<P>::TickFrame() { | |||
| 428 | } | 430 | } |
| 429 | } | 431 | } |
| 430 | if (!is_bad_overlap && must_download) { | 432 | if (!is_bad_overlap && must_download) { |
| 431 | const bool alias_check = | 433 | const bool alias_check = std::ranges::none_of( |
| 432 | std::ranges::none_of(image->aliased_images, [&](const AliasedImage& alias) { | 434 | image->aliased_images, [&, image](const AliasedImage& alias) { |
| 433 | auto& alias_image = slot_images[alias.id]; | 435 | auto& alias_image = slot_images[alias.id]; |
| 434 | return (alias_image.frame_tick < image->frame_tick) || | 436 | return (alias_image.frame_tick < image->frame_tick) || |
| 435 | (alias_image.modification_tick < image->modification_tick); | 437 | (alias_image.modification_tick < image->modification_tick); |
| @@ -1275,8 +1277,13 @@ void TextureCache<P>::RegisterImage(ImageId image_id) { | |||
| 1275 | image.flags |= ImageFlagBits::Registered; | 1277 | image.flags |= ImageFlagBits::Registered; |
| 1276 | ForEachPage(image.cpu_addr, image.guest_size_bytes, | 1278 | ForEachPage(image.cpu_addr, image.guest_size_bytes, |
| 1277 | [this, image_id](u64 page) { page_table[page].push_back(image_id); }); | 1279 | [this, image_id](u64 page) { page_table[page].push_back(image_id); }); |
| 1278 | total_used_memory += | 1280 | u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); |
| 1279 | Common::AlignUp(std::max(image.guest_size_bytes, image.unswizzled_size_bytes), 1024); | 1281 | if ((IsPixelFormatASTC(image.info.format) && |
| 1282 | True(image.flags & ImageFlagBits::AcceleratedUpload)) || | ||
| 1283 | True(image.flags & ImageFlagBits::Converted)) { | ||
| 1284 | tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); | ||
| 1285 | } | ||
| 1286 | total_used_memory += Common::AlignUp(tentative_size, 1024); | ||
| 1280 | } | 1287 | } |
| 1281 | 1288 | ||
| 1282 | template <class P> | 1289 | template <class P> |
| @@ -1286,8 +1293,13 @@ void TextureCache<P>::UnregisterImage(ImageId image_id) { | |||
| 1286 | "Trying to unregister an already registered image"); | 1293 | "Trying to unregister an already registered image"); |
| 1287 | image.flags &= ~ImageFlagBits::Registered; | 1294 | image.flags &= ~ImageFlagBits::Registered; |
| 1288 | image.flags &= ~ImageFlagBits::BadOverlap; | 1295 | image.flags &= ~ImageFlagBits::BadOverlap; |
| 1289 | total_used_memory -= | 1296 | u64 tentative_size = std::max(image.guest_size_bytes, image.unswizzled_size_bytes); |
| 1290 | Common::AlignUp(std::max(image.guest_size_bytes, image.unswizzled_size_bytes), 1024); | 1297 | if ((IsPixelFormatASTC(image.info.format) && |
| 1298 | True(image.flags & ImageFlagBits::AcceleratedUpload)) || | ||
| 1299 | True(image.flags & ImageFlagBits::Converted)) { | ||
| 1300 | tentative_size = EstimatedDecompressedSize(tentative_size, image.info.format); | ||
| 1301 | } | ||
| 1302 | total_used_memory -= Common::AlignUp(tentative_size, 1024); | ||
| 1291 | ForEachPage(image.cpu_addr, image.guest_size_bytes, [this, image_id](u64 page) { | 1303 | ForEachPage(image.cpu_addr, image.guest_size_bytes, [this, image_id](u64 page) { |
| 1292 | const auto page_it = page_table.find(page); | 1304 | const auto page_it = page_table.find(page); |
| 1293 | if (page_it == page_table.end()) { | 1305 | 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 @@ | |||
| 106 | <item> | 106 | <item> |
| 107 | <widget class="QCheckBox" name="use_caches_gc"> | 107 | <widget class="QCheckBox" name="use_caches_gc"> |
| 108 | <property name="toolTip"> | 108 | <property name="toolTip"> |
| 109 | <string>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</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 caches garbage collection (unsafe)</string> |