|
|
@@ -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<Image> slot_images;
|
|
|
SlotVector<ImageView> slot_image_views;
|
|
|
@@ -382,21 +389,23 @@ TextureCache<P>::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 <class P>
|
|
|
-void TextureCache<P>::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<P>::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<P>::TickFrame() {
|
|
|
UnregisterImage(image_id);
|
|
|
DeleteImage(image_id);
|
|
|
if (is_bad_overlap) {
|
|
|
- num_iterations++;
|
|
|
+ ++num_iterations;
|
|
|
}
|
|
|
}
|
|
|
++deletion_iterator;
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+template <class P>
|
|
|
+void TextureCache<P>::TickFrame() {
|
|
|
+ if (Settings::values.use_caches_gc.GetValue()) {
|
|
|
+ RunGarbageCollector();
|
|
|
+ }
|
|
|
sentenced_images.Tick();
|
|
|
sentenced_framebuffers.Tick();
|
|
|
sentenced_image_view.Tick();
|