WIP: [video_core] Fix memory leak when GPU accuracy level is set to Normal #26

Closed
MaranBr wants to merge 1 commit from memory-leak-fix into master
3 changed files with 8 additions and 23 deletions

View file

@ -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. // Try up to 64 times to allocate memory at random addresses in the range.
for (int i = 0; i < 64; i++) { for (int i = 0; i < 64; i++) {
// Calculate a possible location. // 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. // 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 = void* map_pointer =
mmap(reinterpret_cast<void*>(hint_address), virtual_size, PROT_READ | PROT_WRITE, mmap(reinterpret_cast<void*>(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 we successfully mapped, we're done.
if (reinterpret_cast<uintptr_t>(map_pointer) == hint_address) { if (reinterpret_cast<uintptr_t>(map_pointer) == hint_address) {
@ -463,7 +463,7 @@ public:
} }
backing_base = static_cast<u8*>( backing_base = static_cast<u8*>(
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) { if (backing_base == MAP_FAILED) {
LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno)); LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno));
throw std::bad_alloc{}; throw std::bad_alloc{};

View file

@ -72,7 +72,6 @@ public:
} }
void SignalFence(std::function<void()>&& func) { void SignalFence(std::function<void()>&& func) {
bool delay_fence = Settings::IsGPULevelHigh();
if constexpr (!can_async_check) { if constexpr (!can_async_check) {
TryReleasePendingFences<false>(); TryReleasePendingFences<false>();
} }
@ -82,14 +81,9 @@ public:
if constexpr (can_async_check) { if constexpr (can_async_check) {
guard.lock(); 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)); pending_operations.emplace_back(std::move(uncommitted_operations));
QueueFence(new_fence); QueueFence(new_fence);
if (!delay_fence) {
func();
}
fences.push(std::move(new_fence)); fences.push(std::move(new_fence));
if (should_flush) { if (should_flush) {
rasterizer.FlushCommands(); rasterizer.FlushCommands();

View file

@ -257,13 +257,10 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
}; };
u8* pointer = impl->device_memory.template GetPointer<u8>(cpu_addr); u8* pointer = impl->device_memory.template GetPointer<u8>(cpu_addr);
u8* pointer_timestamp = impl->device_memory.template GetPointer<u8>(cpu_addr + 8); u8* pointer_timestamp = impl->device_memory.template GetPointer<u8>(cpu_addr + 8);
bool is_synced = !Settings::IsGPULevelHigh() && is_fence; std::function<void()> operation([this, streamer, query_base = query, query_location,
std::function<void()> operation([this, is_synced, streamer, query_base = query, query_location,
pointer, pointer_timestamp] { pointer, pointer_timestamp] {
if (True(query_base->flags & QueryFlagBits::IsInvalidated)) { 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; return;
} }
if (False(query_base->flags & QueryFlagBits::IsFinalValueSynced)) [[unlikely]] { if (False(query_base->flags & QueryFlagBits::IsFinalValueSynced)) [[unlikely]] {
@ -280,9 +277,7 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
u32 value = static_cast<u32>(query_base->value); u32 value = static_cast<u32>(query_base->value);
std::memcpy(pointer, &value, sizeof(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) { if (is_fence) {
impl->rasterizer.SignalFence(std::move(operation)); impl->rasterizer.SignalFence(std::move(operation));
@ -301,10 +296,6 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
} }
impl->rasterizer.SyncOperation(std::move(operation)); impl->rasterizer.SyncOperation(std::move(operation));
} }
if (is_synced) {
streamer->Free(new_query_id);
return;
}
auto [cont_addr, base] = gen_caching_indexing(cpu_addr); auto [cont_addr, base] = gen_caching_indexing(cpu_addr);
{ {
std::scoped_lock lock(cache_mutex); std::scoped_lock lock(cache_mutex);