Let's try this on memory reclamations

This commit is contained in:
CamilleLaVey
2026-08-27 01:21:10 -04:00
parent 06dba55923
commit ad075400a4
7 changed files with 38 additions and 7 deletions
@@ -129,6 +129,10 @@ public:
return master_semaphore->IsFree(tick); return master_semaphore->IsFree(tick);
} }
void RefreshTick() {
master_semaphore->Refresh();
}
/// Waits for the given GPU tick, optionally pacing frames. /// Waits for the given GPU tick, optionally pacing frames.
void Wait(u64 tick, double target_fps = 0.0) { void Wait(u64 tick, double target_fps = 0.0) {
if (tick > 0) { if (tick > 0) {
@@ -3235,6 +3235,14 @@ u64 TextureCacheRuntime::CurrentTick() const noexcept {
return scheduler.CurrentTick(); return scheduler.CurrentTick();
} }
bool TextureCacheRuntime::IsDirectUploadRetired(u64 tick) {
if (scheduler.IsFree(tick)) {
return true;
}
scheduler.RefreshTick();
return scheduler.IsFree(tick);
}
void TextureCacheRuntime::TransitionImageLayout(Image& image) { void TextureCacheRuntime::TransitionImageLayout(Image& image) {
if (!image.ExchangeInitialization()) { if (!image.ExchangeInitialization()) {
VkImageMemoryBarrier barrier{ VkImageMemoryBarrier barrier{
@@ -116,6 +116,8 @@ public:
[[nodiscard]] u64 CurrentTick() const noexcept; [[nodiscard]] u64 CurrentTick() const noexcept;
[[nodiscard]] bool IsDirectUploadRetired(u64 tick);
void InsertUploadMemoryBarrier() {} void InsertUploadMemoryBarrier() {}
void TransitionImageLayout(Image& image); void TransitionImageLayout(Image& image);
+1 -1
View File
@@ -95,7 +95,7 @@ struct ImageBase {
u32 scale_rating = 0; u32 scale_rating = 0;
u64 scale_tick = 0; u64 scale_tick = 0;
bool has_scaled = false; bool has_scaled = false;
bool direct_upload_used = false; u64 direct_upload_tick = 0;
bool direct_upload_blocked = false; bool direct_upload_blocked = false;
size_t channel = 0; size_t channel = 0;
+17 -5
View File
@@ -119,13 +119,16 @@ void TextureCache<P>::RunGarbageCollector() {
bool aggressive_mode = false; bool aggressive_mode = false;
u64 ticks_to_destroy = 0; u64 ticks_to_destroy = 0;
size_t num_iterations = 0; size_t num_iterations = 0;
size_t num_downloads = 0;
const auto Configure = [&](bool allow_aggressive) { const auto Configure = [&](bool allow_aggressive) {
high_priority_mode = total_used_memory >= expected_memory; high_priority_mode = total_used_memory >= expected_memory;
aggressive_mode = allow_aggressive && total_used_memory >= critical_memory; aggressive_mode = allow_aggressive && total_used_memory >= critical_memory;
ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL; ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL;
num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10); num_iterations = aggressive_mode ? 40 : (high_priority_mode ? 20 : 10);
num_downloads = MAX_GC_DOWNLOADS_PER_PASS;
}; };
const auto Cleanup = [this, &num_iterations, &high_priority_mode, &aggressive_mode](ImageId image_id) { const auto Cleanup = [this, &num_iterations, &num_downloads, &high_priority_mode,
&aggressive_mode](ImageId image_id) {
if (num_iterations == 0) { if (num_iterations == 0) {
return true; return true;
} }
@@ -139,6 +142,10 @@ void TextureCache<P>::RunGarbageCollector() {
return false; return false;
} }
if (must_download) { if (must_download) {
if (num_downloads == 0) {
return false;
}
--num_downloads;
auto map = runtime.DownloadStagingBuffer(image.unswizzled_size_bytes); auto map = runtime.DownloadStagingBuffer(image.unswizzled_size_bytes);
const auto copies = FixSmallVectorADL(FullDownloadCopies(image.info)); const auto copies = FixSmallVectorADL(FullDownloadCopies(image.info));
image.DownloadMemory(map, copies); image.DownloadMemory(map, copies);
@@ -585,9 +592,14 @@ FramebufferId TextureCache<P>::GetFramebufferId(const RenderTargets& key) {
template <class P> template <class P>
void TextureCache<P>::WriteMemory(DAddr cpu_addr, size_t size) { void TextureCache<P>::WriteMemory(DAddr cpu_addr, size_t size) {
ForEachImageInRegion(cpu_addr, size, [this](ImageId image_id, Image& image) { ForEachImageInRegion(cpu_addr, size, [this](ImageId image_id, Image& image) {
if (image.direct_upload_used) { if constexpr (USE_UNIFIED_MEMORY) {
image.direct_upload_used = false; if (image.direct_upload_tick != 0) {
image.direct_upload_blocked = true; const u64 upload_tick = image.direct_upload_tick;
image.direct_upload_tick = 0;
if (!runtime.IsDirectUploadRetired(upload_tick)) {
image.direct_upload_blocked = true;
}
}
} }
if (True(image.flags & ImageFlagBits::CpuModified)) { if (True(image.flags & ImageFlagBits::CpuModified)) {
return; return;
@@ -1195,7 +1207,7 @@ bool TextureCache<P>::TryUploadFromUnifiedMemory([[maybe_unused]] Image& image)
local_offset, FixSmallVectorADL(swizzles))) { local_offset, FixSmallVectorADL(swizzles))) {
return false; return false;
} }
image.direct_upload_used = true; image.direct_upload_tick = runtime.CurrentTick();
return true; return true;
} else { } else {
return false; return false;
@@ -121,6 +121,7 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI
static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB; static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB;
static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB + 625_MiB; static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB + 625_MiB;
static constexpr size_t GC_EMERGENCY_COUNTS = 2; static constexpr size_t GC_EMERGENCY_COUNTS = 2;
static constexpr size_t MAX_GC_DOWNLOADS_PER_PASS = 4;
using Runtime = typename P::Runtime; using Runtime = typename P::Runtime;
using Image = typename P::Image; using Image = typename P::Image;
@@ -1525,7 +1525,11 @@ u64 Device::GetDeviceMemoryUsage() const {
for (const size_t heap : valid_heap_memory) { for (const size_t heap : valid_heap_memory) {
result += budget.heapUsage[heap]; result += budget.heapUsage[heap];
} }
return result; const u64 committed_backing = Common::GetCommittedBackingSize();
if (result <= committed_backing) {
return result;
}
return result - committed_backing;
} }
void Device::CollectPhysicalMemoryInfo() { void Device::CollectPhysicalMemoryInfo() {