From ddb7cd4797d42bffa422f2eac401e5348809f631 Mon Sep 17 00:00:00 2001 From: MaranBr Date: Tue, 8 Jul 2025 13:54:24 -0400 Subject: [PATCH] Fix memory leak when GPU accuracy level is set to Normal --- src/common/host_memory.cpp | 8 ++++---- src/video_core/fence_manager.h | 8 +------- src/video_core/query_cache/query_cache.h | 15 +++------------ 3 files changed, 8 insertions(+), 23 deletions(-) diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index e0b5a6a67c..cf2412d552 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -384,13 +384,13 @@ static void* ChooseVirtualBase(size_t virtual_size) { // Try up to 64 times to allocate memory at random addresses in the range. for (int i = 0; i < 64; i++) { // Calculate a possible location. - uintptr_t hint_address = ((rng() % range) + lower) * HugePageSize; + uintptr_t hint_address = ((((i == 0) ? 0 : rng()) % range) + lower) * HugePageSize; // Try to map. - // Note: we may be able to take advantage of MAP_FIXED_NOREPLACE here. + // Added MAP_FIXED_NOREPLACE here to stop mprotect eventually (20+ mins) failing with out of memory. void* map_pointer = mmap(reinterpret_cast(hint_address), virtual_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED_NOREPLACE, -1, 0); // If we successfully mapped, we're done. if (reinterpret_cast(map_pointer) == hint_address) { @@ -463,7 +463,7 @@ public: } backing_base = static_cast( - mmap(nullptr, backing_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); + mmap(nullptr, backing_size, PROT_READ | PROT_WRITE | MAP_FIXED_NOREPLACE, MAP_SHARED, fd, 0)); if (backing_base == MAP_FAILED) { LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno)); throw std::bad_alloc{}; diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index 2135f1f2da..5077f91cac 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h @@ -72,7 +72,6 @@ public: } void SignalFence(std::function&& func) { - bool delay_fence = Settings::IsGPULevelHigh(); if constexpr (!can_async_check) { TryReleasePendingFences(); } @@ -82,14 +81,9 @@ public: if constexpr (can_async_check) { guard.lock(); } - if (delay_fence) { - uncommitted_operations.emplace_back(std::move(func)); - } + uncommitted_operations.emplace_back(std::move(func)); pending_operations.emplace_back(std::move(uncommitted_operations)); QueueFence(new_fence); - if (!delay_fence) { - func(); - } fences.push(std::move(new_fence)); if (should_flush) { rasterizer.FlushCommands(); diff --git a/src/video_core/query_cache/query_cache.h b/src/video_core/query_cache/query_cache.h index 08b7790555..76ff00b587 100644 --- a/src/video_core/query_cache/query_cache.h +++ b/src/video_core/query_cache/query_cache.h @@ -257,13 +257,10 @@ void QueryCacheBase::CounterReport(GPUVAddr addr, QueryType counter_type }; u8* pointer = impl->device_memory.template GetPointer(cpu_addr); u8* pointer_timestamp = impl->device_memory.template GetPointer(cpu_addr + 8); - bool is_synced = !Settings::IsGPULevelHigh() && is_fence; - std::function operation([this, is_synced, streamer, query_base = query, query_location, + std::function operation([this, streamer, query_base = query, query_location, pointer, pointer_timestamp] { if (True(query_base->flags & QueryFlagBits::IsInvalidated)) { - if (!is_synced) [[likely]] { - impl->pending_unregister.push_back(query_location); - } + impl->pending_unregister.push_back(query_location); return; } if (False(query_base->flags & QueryFlagBits::IsFinalValueSynced)) [[unlikely]] { @@ -280,9 +277,7 @@ void QueryCacheBase::CounterReport(GPUVAddr addr, QueryType counter_type u32 value = static_cast(query_base->value); std::memcpy(pointer, &value, sizeof(value)); } - if (!is_synced) [[likely]] { - impl->pending_unregister.push_back(query_location); - } + impl->pending_unregister.push_back(query_location); }); if (is_fence) { impl->rasterizer.SignalFence(std::move(operation)); @@ -301,10 +296,6 @@ void QueryCacheBase::CounterReport(GPUVAddr addr, QueryType counter_type } impl->rasterizer.SyncOperation(std::move(operation)); } - if (is_synced) { - streamer->Free(new_query_id); - return; - } auto [cont_addr, base] = gen_caching_indexing(cpu_addr); { std::scoped_lock lock(cache_mutex); -- 2.39.5