diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.cpp b/rpcs3/Emu/RSX/VK/VKHelpers.cpp index a1dbbef440..82382e214d 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.cpp +++ b/rpcs3/Emu/RSX/VK/VKHelpers.cpp @@ -321,6 +321,7 @@ namespace vk { vk::reset_compute_tasks(); vk::reset_resolve_resources(); + vk::vmm_reset(); g_upload_heap.reset_allocation_stats(); } diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index c896feaa8d..12040b2f56 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -151,6 +151,10 @@ namespace vk void destroy_global_resources(); void reset_global_resources(); + void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size); + void vmm_notify_memory_freed(void* handle); + void vmm_reset(); + /** * Allocate enough space in upload_buffer and write all mipmap/layer data into the subbuffer. * Then copy all layers into dst_image. @@ -319,11 +323,14 @@ namespace vk mem_req.alignment = alignment; create_info.memoryTypeBits = 1u << memory_type_index; CHECK_RESULT(vmaAllocateMemory(m_allocator, &mem_req, &create_info, &vma_alloc, nullptr)); + + vmm_notify_memory_allocated(vma_alloc, memory_type_index, block_sz); return vma_alloc; } void free(mem_handle_t mem_handle) override { + vmm_notify_memory_freed(mem_handle); vmaFreeMemory(m_allocator, static_cast(mem_handle)); } @@ -380,13 +387,15 @@ namespace vk info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; info.allocationSize = block_sz; info.memoryTypeIndex = memory_type_index; - CHECK_RESULT(vkAllocateMemory(m_device, &info, nullptr, &memory)); + + vmm_notify_memory_allocated(memory, memory_type_index, block_sz); return memory; } void free(mem_handle_t mem_handle) override { + vmm_notify_memory_freed(mem_handle); vkFreeMemory(m_device, (VkDeviceMemory)mem_handle, nullptr); } diff --git a/rpcs3/Emu/RSX/VK/VKResourceManager.cpp b/rpcs3/Emu/RSX/VK/VKResourceManager.cpp index d91a2d8f28..9bfff2f525 100644 --- a/rpcs3/Emu/RSX/VK/VKResourceManager.cpp +++ b/rpcs3/Emu/RSX/VK/VKResourceManager.cpp @@ -1,11 +1,16 @@ -#include "stdafx.h" +#include "stdafx.h" #include "VKResourceManager.h" namespace vk { + std::unordered_map g_vmm_allocations; + std::unordered_map> g_vmm_memory_usage; + resource_manager g_resource_manager; atomic_t g_event_ctr; + constexpr u64 s_vmm_warn_threshold_size = 2000 * 0x100000; // Warn if allocation on a single heap exceeds this value + resource_manager* get_resource_manager() { return &g_resource_manager; @@ -26,4 +31,48 @@ namespace vk // TODO: Offload this to a secondary thread g_resource_manager.eid_completed(event_id); } + + static constexpr f32 size_in_GiB(u64 size) + { + return size / (1024.f * 1024.f * 1024.f); + } + + void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size) + { + auto key = reinterpret_cast(handle); + const vmm_allocation_t info = { memory_size, memory_type }; + + if (const auto ins = g_vmm_allocations.insert_or_assign(key, info); + !ins.second) + { + LOG_ERROR(RSX, "Duplicate vmm entry with memory handle 0x%llx", key); + } + + auto& vmm_size = g_vmm_memory_usage[memory_type]; + vmm_size += memory_size; + + if (vmm_size > s_vmm_warn_threshold_size && (vmm_size - memory_size) <= s_vmm_warn_threshold_size) + { + LOG_WARNING(RSX, "Memory type 0x%x has allocated more than %.2fG. Currently allocated %.2fG", + memory_type, size_in_GiB(s_vmm_warn_threshold_size), size_in_GiB(vmm_size)); + } + } + + void vmm_notify_memory_freed(void* handle) + { + auto key = reinterpret_cast(handle); + if (auto found = g_vmm_allocations.find(key); + found != g_vmm_allocations.end()) + { + const auto& info = found->second; + g_vmm_memory_usage[info.type_index] -= info.size; + g_vmm_allocations.erase(found); + } + } + + void vmm_reset() + { + g_vmm_memory_usage.clear(); + g_vmm_allocations.clear(); + } } diff --git a/rpcs3/Emu/RSX/VK/VKResourceManager.h b/rpcs3/Emu/RSX/VK/VKResourceManager.h index 1fb1a526df..375bac2bac 100644 --- a/rpcs3/Emu/RSX/VK/VKResourceManager.h +++ b/rpcs3/Emu/RSX/VK/VKResourceManager.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include "VKHelpers.h" namespace vk @@ -143,5 +143,11 @@ namespace vk } }; + struct vmm_allocation_t + { + u64 size; + u32 type_index; + }; + resource_manager* get_resource_manager(); }