vk: Add video memory manager to monitor VRAM usage

This commit is contained in:
kd-11 2019-10-17 21:20:22 +03:00 committed by kd-11
parent d6664450df
commit 97ed95d21b
4 changed files with 68 additions and 3 deletions

View File

@ -321,6 +321,7 @@ namespace vk
{
vk::reset_compute_tasks();
vk::reset_resolve_resources();
vk::vmm_reset();
g_upload_heap.reset_allocation_stats();
}

View File

@ -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<VmaAllocation>(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);
}

View File

@ -1,11 +1,16 @@
#include "stdafx.h"
#include "stdafx.h"
#include "VKResourceManager.h"
namespace vk
{
std::unordered_map<uintptr_t, vmm_allocation_t> g_vmm_allocations;
std::unordered_map<uintptr_t, atomic_t<u64>> g_vmm_memory_usage;
resource_manager g_resource_manager;
atomic_t<u64> 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<uintptr_t>(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<uintptr_t>(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();
}
}

View File

@ -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();
}