1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

vk: Keep the total number of allocated samplers under control

This commit is contained in:
kd-11 2022-01-19 00:47:50 +03:00 committed by kd-11
parent 8c3fb3998c
commit 2331dc3256
6 changed files with 90 additions and 7 deletions

View File

@ -285,8 +285,14 @@ void VKGSRender::load_texture_env()
if (replace)
{
fs_sampler_handles[i] = vk::get_resource_manager()->find_sampler(*m_device, wrap_s, wrap_t, wrap_r, false, lod_bias, af_level, min_lod, max_lod,
min_filter.filter, mag_filter, min_filter.mipmap_mode, border_color, compare_enabled, depth_compare_mode);
fs_sampler_handles[i] = vk::get_resource_manager()->get_sampler(
*m_device,
fs_sampler_handles[i],
wrap_s, wrap_t, wrap_r,
false,
lod_bias, af_level, min_lod, max_lod,
min_filter.filter, mag_filter, min_filter.mipmap_mode,
border_color, compare_enabled, depth_compare_mode);
}
}
else
@ -338,8 +344,9 @@ void VKGSRender::load_texture_env()
if (replace)
{
vs_sampler_handles[i] = vk::get_resource_manager()->find_sampler(
vs_sampler_handles[i] = vk::get_resource_manager()->get_sampler(
*m_device,
vs_sampler_handles[i],
VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT,
unnormalized_coords,
0.f, 1.f, min_lod, max_lod,

View File

@ -223,6 +223,8 @@ void VKGSRender::frame_context_cleanup(vk::frame_context_t *ctx, bool free_resou
m_overlay_manager->dispose(uids_to_dispose);
}
vk::get_resource_manager()->trim();
vk::reset_global_resources();
ctx->buffer_views_to_clean.clear();

View File

@ -31,6 +31,34 @@ namespace vk
return &g_resource_manager;
}
void resource_manager::trim()
{
// For any managed resources, try to keep the number of unused/idle resources as low as possible.
// Improves search times as well as keeping us below the hardware limit.
const auto limits = get_current_renderer()->gpu().get_limits();
const auto allocated_sampler_count = vmm_get_application_pool_usage(VMM_ALLOCATION_POOL_SAMPLER);
const auto max_allowed_samplers = std::min((limits.maxSamplerAllocationCount * 3u) / 4u, 2048u);
if (allocated_sampler_count > max_allowed_samplers)
{
ensure(max_allowed_samplers);
rsx_log.warning("Trimming allocated samplers. Allocated = %u, Max = %u", allocated_sampler_count, limits.maxSamplerAllocationCount);
auto& disposed_samplers_pool = get_current_eid_scope().m_disposed_samplers;
for (auto It = m_sampler_pool.begin(); It != m_sampler_pool.end();)
{
if (!It->second->has_refs())
{
disposed_samplers_pool.emplace_back(std::move(It->second));
It = m_sampler_pool.erase(It);
continue;
}
++It;
}
}
}
u64 get_event_id()
{
return g_event_ctr++;
@ -212,4 +240,16 @@ namespace vk
vmm_handle_memory_pressure(load_severity);
}
}
void vmm_notify_object_allocated(vmm_allocation_pool pool)
{
ensure(pool >= VMM_ALLOCATION_POOL_SAMPLER);
g_vmm_stats.pool_usage[pool]++;
}
void vmm_notify_object_freed(vmm_allocation_pool pool)
{
ensure(pool >= VMM_ALLOCATION_POOL_SAMPLER);
g_vmm_stats.pool_usage[pool]--;
}
}

View File

@ -23,6 +23,7 @@ namespace vk
std::vector<std::unique_ptr<vk::image>> m_disposed_images;
std::vector<std::unique_ptr<vk::event>> m_disposed_events;
std::vector<std::unique_ptr<vk::query_pool>> m_disposed_query_pools;
std::vector<std::unique_ptr<vk::sampler>> m_disposed_samplers;
eid_scope_t(u64 _eid):
eid(_eid), m_device(g_render_device)
@ -40,13 +41,19 @@ namespace vk
m_disposed_image_views.clear();
m_disposed_images.clear();
m_disposed_query_pools.clear();
m_disposed_samplers.clear();
}
};
class resource_manager
{
private:
std::unordered_map<u64, std::unique_ptr<vk::sampler>> m_sampler_pool;
struct cached_sampler_object_t : public vk::sampler, public rsx::ref_counted
{
using vk::sampler::sampler;
};
std::unordered_map<u64, std::unique_ptr<cached_sampler_object_t>> m_sampler_pool;
std::deque<eid_scope_t> m_eid_map;
eid_scope_t& get_current_eid_scope()
@ -98,7 +105,8 @@ namespace vk
m_sampler_pool.clear();
}
vk::sampler* find_sampler(const vk::render_device& dev, VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
vk::sampler* get_sampler(const vk::render_device& dev, vk::sampler* previous,
VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
VkBool32 unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod,
VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, VkBorderColor border_color,
VkBool32 depth_compare = VK_FALSE, VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER)
@ -115,20 +123,30 @@ namespace vk
key |= u64(encode_fxp<true>(mipLodBias)) << 44; // 13 bits
key |= u64(max_anisotropy) << 57; // 4 bits
if (previous)
{
auto as_cached_object = static_cast<cached_sampler_object_t*>(previous);
ensure(as_cached_object->has_refs());
as_cached_object->release();
}
if (const auto found = m_sampler_pool.find(key);
found != m_sampler_pool.end())
{
found->second->add_ref();
return found->second.get();
}
auto result = std::make_unique<vk::sampler>(
auto result = std::make_unique<cached_sampler_object_t>(
dev, clamp_u, clamp_v, clamp_w, unnormalized_coordinates,
mipLodBias, max_anisotropy, min_lod, max_lod,
min_filter, mag_filter, mipmap_mode, border_color,
depth_compare, depth_compare_mode);
auto It = m_sampler_pool.emplace(key, std::move(result));
return It.first->second.get();
auto ret = It.first->second.get();
ret->add_ref();
return ret;
}
void dispose(std::unique_ptr<vk::buffer>& buf)
@ -162,6 +180,11 @@ namespace vk
get_current_eid_scope().m_disposed_query_pools.emplace_back(std::move(pool));
}
void dispose(std::unique_ptr<vk::sampler>& sampler)
{
get_current_eid_scope().m_disposed_samplers.emplace_back(std::move(sampler));
}
void eid_completed(u64 eid)
{
while (!m_eid_map.empty())
@ -177,6 +200,8 @@ namespace vk
}
}
}
void trim();
};
struct vmm_allocation_t

View File

@ -18,6 +18,7 @@ namespace vk
VMM_ALLOCATION_POOL_TEXTURE_CACHE,
VMM_ALLOCATION_POOL_SWAPCHAIN,
VMM_ALLOCATION_POOL_SCRATCH,
VMM_ALLOCATION_POOL_SAMPLER,
};
}
@ -173,6 +174,7 @@ namespace vk
void* m_host_pointer;
};
// Tracking for memory usage. Constrained largely by amount of VRAM + shared video memory.
void vmm_notify_memory_allocated(void* handle, u32 memory_type, u64 memory_size, vmm_allocation_pool pool);
void vmm_notify_memory_freed(void* handle);
void vmm_reset();
@ -182,5 +184,9 @@ namespace vk
bool vmm_handle_memory_pressure(rsx::problem_severity severity);
rsx::problem_severity vmm_determine_memory_load_severity();
// Tracking for host memory objects. Allocated count is more important than actual memory amount.
void vmm_notify_object_allocated(vmm_allocation_pool pool);
void vmm_notify_object_freed(vmm_allocation_pool pool);
mem_allocator_base* get_current_mem_allocator();
}

View File

@ -1,3 +1,4 @@
#include "memory.h"
#include "sampler.h"
#include "../../rsx_utils.h"
@ -27,11 +28,13 @@ namespace vk
info.borderColor = border_color;
CHECK_RESULT(vkCreateSampler(m_device, &info, nullptr, &value));
vmm_notify_object_allocated(VMM_ALLOCATION_POOL_SAMPLER);
}
sampler::~sampler()
{
vkDestroySampler(m_device, value, nullptr);
vmm_notify_object_freed(VMM_ALLOCATION_POOL_SAMPLER);
}
bool sampler::matches(VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,