mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 00:40:11 +00:00
vk: Improve memory load balancing and reporting
- Track pool usage - Take allocation percentages into account when making decisions on whether there is overloading or not
This commit is contained in:
parent
342b25d00e
commit
53c9fb3e00
@ -5,8 +5,20 @@
|
||||
|
||||
namespace vk
|
||||
{
|
||||
std::unordered_map<uptr, vmm_allocation_t> g_vmm_allocations;
|
||||
std::unordered_map<uptr, atomic_t<u64>> g_vmm_memory_usage;
|
||||
struct vmm_memory_stats
|
||||
{
|
||||
std::unordered_map<uptr, vmm_allocation_t> allocations;
|
||||
std::unordered_map<uptr, atomic_t<u64>> memory_usage;
|
||||
std::unordered_map<vmm_allocation_pool, atomic_t<u64>> pool_usage;
|
||||
|
||||
void clear()
|
||||
{
|
||||
allocations.clear();
|
||||
memory_usage.clear();
|
||||
pool_usage.clear();
|
||||
}
|
||||
}
|
||||
g_vmm_stats;
|
||||
|
||||
resource_manager g_resource_manager;
|
||||
atomic_t<u64> g_event_ctr;
|
||||
@ -57,20 +69,22 @@ namespace vk
|
||||
void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size, vmm_allocation_pool pool)
|
||||
{
|
||||
auto key = reinterpret_cast<uptr>(handle);
|
||||
const vmm_allocation_t info = { memory_size, memory_type };
|
||||
const vmm_allocation_t info = { memory_size, memory_type, pool };
|
||||
|
||||
if (const auto ins = g_vmm_allocations.insert_or_assign(key, info);
|
||||
if (const auto ins = g_vmm_stats.allocations.insert_or_assign(key, info);
|
||||
!ins.second)
|
||||
{
|
||||
rsx_log.error("Duplicate vmm entry with memory handle 0x%llx", key);
|
||||
}
|
||||
|
||||
auto& vmm_size = g_vmm_memory_usage[memory_type];
|
||||
g_vmm_stats.pool_usage[pool] += memory_size;
|
||||
|
||||
auto& vmm_size = g_vmm_stats.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)
|
||||
{
|
||||
rsx_log.warning("Memory type 0x%x has allocated more than %.2fG. Currently allocated %.2fG",
|
||||
rsx_log.warning("Memory type 0x%x has allocated more than %04.2fG. Currently allocated %04.2fG",
|
||||
memory_type, size_in_GiB(s_vmm_warn_threshold_size), size_in_GiB(vmm_size));
|
||||
}
|
||||
}
|
||||
@ -78,19 +92,90 @@ namespace vk
|
||||
void vmm_notify_memory_freed(void* handle)
|
||||
{
|
||||
auto key = reinterpret_cast<uptr>(handle);
|
||||
if (auto found = g_vmm_allocations.find(key);
|
||||
found != g_vmm_allocations.end())
|
||||
if (auto found = g_vmm_stats.allocations.find(key);
|
||||
found != g_vmm_stats.allocations.end())
|
||||
{
|
||||
const auto& info = found->second;
|
||||
g_vmm_memory_usage[info.type_index] -= info.size;
|
||||
g_vmm_allocations.erase(found);
|
||||
g_vmm_stats.memory_usage[info.type_index] -= info.size;
|
||||
g_vmm_stats.pool_usage[info.pool] -= info.size;
|
||||
g_vmm_stats.allocations.erase(found);
|
||||
}
|
||||
}
|
||||
|
||||
void vmm_reset()
|
||||
{
|
||||
g_vmm_memory_usage.clear();
|
||||
g_vmm_allocations.clear();
|
||||
g_vmm_stats.clear();
|
||||
g_event_ctr = 0;
|
||||
g_last_completed_event = 0;
|
||||
}
|
||||
|
||||
u64 vmm_get_application_memory_usage(u32 memory_type)
|
||||
{
|
||||
return g_vmm_stats.memory_usage[memory_type];
|
||||
}
|
||||
|
||||
u64 vmm_get_application_pool_usage(vmm_allocation_pool pool)
|
||||
{
|
||||
return g_vmm_stats.pool_usage[pool];
|
||||
}
|
||||
|
||||
rsx::problem_severity vmm_determine_memory_load_severity()
|
||||
{
|
||||
const auto vmm_load = get_current_mem_allocator()->get_memory_usage();
|
||||
rsx::problem_severity load_severity = rsx::problem_severity::low;
|
||||
|
||||
// Fragmentation tuning
|
||||
if (vmm_load < 50.f)
|
||||
{
|
||||
get_current_mem_allocator()->set_fastest_allocation_flags();
|
||||
}
|
||||
else if (vmm_load > 75.f)
|
||||
{
|
||||
// Avoid fragmentation if we can
|
||||
get_current_mem_allocator()->set_safest_allocation_flags();
|
||||
|
||||
if (vmm_load > 95.f)
|
||||
{
|
||||
// Drivers will often crash long before returning OUT_OF_DEVICE_MEMORY errors.
|
||||
load_severity = rsx::problem_severity::fatal;
|
||||
}
|
||||
else if (vmm_load > 90.f)
|
||||
{
|
||||
load_severity = rsx::problem_severity::severe;
|
||||
}
|
||||
else
|
||||
{
|
||||
load_severity = rsx::problem_severity::moderate;
|
||||
}
|
||||
|
||||
// Query actual usage for comparison. Maybe we just have really fragmented memory...
|
||||
const auto mem_info = get_current_renderer()->get_memory_mapping();
|
||||
const auto local_memory_usage = vmm_get_application_memory_usage(mem_info.device_local);
|
||||
|
||||
constexpr u64 _1GB = (1024 * 0x100000);
|
||||
if (local_memory_usage < (mem_info.device_local_total_bytes / 2) || // Less than 50% VRAM usage OR
|
||||
(mem_info.device_local_total_bytes - local_memory_usage) > _1GB) // More than 1GiB of unallocated memory
|
||||
{
|
||||
// Lower severity to avoid slowing performance too much
|
||||
load_severity = rsx::problem_severity::low;
|
||||
}
|
||||
else if ((mem_info.device_local_total_bytes - local_memory_usage) > 512 * 0x100000)
|
||||
{
|
||||
// At least 512MB left, do not overreact
|
||||
load_severity = rsx::problem_severity::moderate;
|
||||
}
|
||||
|
||||
if (load_severity >= rsx::problem_severity::moderate)
|
||||
{
|
||||
// NOTE: For some reason fmt::format with a sized float followed by percentage sign causes random crashing.
|
||||
// This is a bug unrelated to this, but explains why we're going with integral percentages here.
|
||||
const auto application_memory_load = (local_memory_usage * 100) / mem_info.device_local_total_bytes;
|
||||
rsx_log.warning("Actual device memory used by internal allocations is %lluM (%llu%%)", local_memory_usage / 0x100000, application_memory_load);
|
||||
rsx_log.warning("Video memory usage is at %d%%. Will attempt to reclaim some resources.", static_cast<int>(vmm_load));
|
||||
}
|
||||
}
|
||||
|
||||
return load_severity;
|
||||
}
|
||||
|
||||
bool vmm_handle_memory_pressure(rsx::problem_severity severity)
|
||||
@ -105,21 +190,8 @@ namespace vk
|
||||
|
||||
void vmm_check_memory_usage()
|
||||
{
|
||||
const auto vmm_load = get_current_mem_allocator()->get_memory_usage();
|
||||
rsx::problem_severity load_severity = rsx::problem_severity::low;
|
||||
|
||||
if (vmm_load > 90.f)
|
||||
{
|
||||
rsx_log.warning("Video memory usage exceeding 90%. Will attempt to reclaim resources.");
|
||||
load_severity = rsx::problem_severity::severe;
|
||||
}
|
||||
else if (vmm_load > 75.f)
|
||||
{
|
||||
rsx_log.notice("Video memory usage exceeding 75%. Will attempt to reclaim resources.");
|
||||
load_severity = rsx::problem_severity::moderate;
|
||||
}
|
||||
|
||||
if (load_severity >= rsx::problem_severity::moderate)
|
||||
if (const auto load_severity = vmm_determine_memory_load_severity();
|
||||
load_severity >= rsx::problem_severity::moderate)
|
||||
{
|
||||
vmm_handle_memory_pressure(load_severity);
|
||||
}
|
||||
|
@ -183,6 +183,7 @@ namespace vk
|
||||
{
|
||||
u64 size;
|
||||
u32 type_index;
|
||||
vmm_allocation_pool pool;
|
||||
};
|
||||
|
||||
resource_manager* get_resource_manager();
|
||||
|
Loading…
x
Reference in New Issue
Block a user