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 ::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 ::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 ::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 ::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 ::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 ::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