vk: Rewrite resource management

This commit is contained in:
kd-11 2022-02-09 00:44:17 +03:00 committed by kd-11
parent 48b54131f6
commit f667b52cca
6 changed files with 85 additions and 77 deletions

View File

@ -655,9 +655,6 @@ VKGSRender::~VKGSRender()
// Upscaler (references some global resources)
m_upscaler.reset();
// Global resources
vk::destroy_global_resources();
// Heaps
m_attrib_ring_info.destroy();
m_fragment_env_ring_info.destroy();
@ -722,6 +719,9 @@ VKGSRender::~VKGSRender()
m_secondary_command_buffer.destroy();
m_secondary_command_buffer_pool.destroy();
// Global resources
vk::destroy_global_resources();
// Device handles/contexts
m_swapchain->destroy();
m_instance.destroy();

View File

@ -67,7 +67,6 @@ namespace vk
vk::clear_framebuffer_cache();
vk::clear_resolve_helpers();
vk::clear_dma_resources();
vk::vmm_reset();
vk::clear_scratch_resources();
vk::get_upload_heap()->destroy();
@ -82,6 +81,9 @@ namespace vk
// This must be the last item destroyed
vk::get_resource_manager()->destroy();
// Statistics counter reset. Also verifies that everything was deleted.
vk::vmm_reset();
}
const vk::render_device *get_current_renderer()

View File

@ -13,6 +13,16 @@ namespace vk
void clear()
{
if (!allocations.empty())
{
rsx_log.error("Leaking memory allocations!");
for (auto& leak : allocations)
{
rsx_log.error("Memory handle 0x%llx (%llu bytes) allocated from pool %d was not freed.",
leak.first, leak.second.size, static_cast<int>(leak.second.pool));
}
}
allocations.clear();
memory_usage.clear();
pool_usage.clear();
@ -44,12 +54,11 @@ namespace vk
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));
dispose(It->second);
It = m_sampler_pool.erase(It);
continue;
}

View File

@ -3,6 +3,8 @@
#include "vkutils/query_pool.hpp"
#include "vkutils/sampler.h"
#include "Utilities/mutex.h"
#include <unordered_map>
#include <deque>
#include <memory>
@ -14,22 +16,47 @@ namespace vk
u64 last_completed_event_id();
void on_event_completed(u64 event_id, bool flush = false);
struct disposable_t
class disposable_t
{
virtual void dispose() = 0;
void* ptr;
std::function<void(void*)> deleter;
disposable_t(void* ptr_, std::function<void(void*)> deleter_) :
ptr(ptr_), deleter(deleter_) {}
public:
disposable_t() = delete;
disposable_t(const disposable_t&) = delete;
disposable_t(disposable_t&& other):
ptr(std::exchange(other.ptr, nullptr)),
deleter(other.deleter)
{}
~disposable_t()
{
if (ptr)
{
deleter(ptr);
ptr = nullptr;
}
}
template <typename T>
static disposable_t make(T* raw)
{
return disposable_t(raw, [](void *raw)
{
delete static_cast<T*>(raw);
});
}
};
struct eid_scope_t
{
u64 eid;
const vk::render_device* m_device;
std::vector<std::unique_ptr<vk::buffer>> m_disposed_buffers;
std::vector<std::unique_ptr<vk::image_view>> m_disposed_image_views;
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;
std::vector<std::unique_ptr<vk::disposable_t>> m_disposables;
std::vector<disposable_t> m_disposables;
eid_scope_t(u64 _eid):
eid(_eid), m_device(g_render_device)
@ -40,19 +67,15 @@ namespace vk
discard();
}
void swap(eid_scope_t& other)
{
std::swap(eid, other.eid);
std::swap(m_device, other.m_device);
std::swap(m_disposables, other.m_disposables);
}
void discard()
{
m_disposed_buffers.clear();
m_disposed_events.clear();
m_disposed_image_views.clear();
m_disposed_images.clear();
m_disposed_query_pools.clear();
m_disposed_samplers.clear();
for (auto& disposable : m_disposables)
{
disposable->dispose();
}
m_disposables.clear();
}
};
@ -67,20 +90,18 @@ namespace vk
std::unordered_map<u64, std::unique_ptr<cached_sampler_object_t>> m_sampler_pool;
std::deque<eid_scope_t> m_eid_map;
shared_mutex m_eid_map_lock;
eid_scope_t& get_current_eid_scope()
inline eid_scope_t& get_current_eid_scope()
{
const auto eid = current_event_id();
if (!m_eid_map.empty())
{
// Elements are insterted in order, so just check the last entry for a match
if (auto &old = m_eid_map.back(); old.eid == eid)
std::lock_guard lock(m_eid_map_lock);
if (m_eid_map.empty() || m_eid_map.back().eid != eid)
{
return old;
}
}
m_eid_map.emplace_back(eid);
}
}
return m_eid_map.back();
}
@ -161,47 +182,18 @@ namespace vk
return ret;
}
void dispose(std::unique_ptr<vk::buffer>& buf)
{
get_current_eid_scope().m_disposed_buffers.emplace_back(std::move(buf));
}
void dispose(std::unique_ptr<vk::image_view>& view)
{
get_current_eid_scope().m_disposed_image_views.emplace_back(std::move(view));
}
void dispose(std::unique_ptr<vk::image>& img)
{
get_current_eid_scope().m_disposed_images.emplace_back(std::move(img));
}
void dispose(std::unique_ptr<vk::viewable_image>& img)
{
get_current_eid_scope().m_disposed_images.emplace_back(std::move(img));
}
void dispose(std::unique_ptr<vk::event>& event)
{
get_current_eid_scope().m_disposed_events.emplace_back(std::move(event));
event = VK_NULL_HANDLE;
}
void dispose(std::unique_ptr<vk::query_pool>& pool)
{
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 dispose(std::unique_ptr<vk::disposable_t>& disposable)
inline void dispose(vk::disposable_t& disposable)
{
get_current_eid_scope().m_disposables.emplace_back(std::move(disposable));
}
template<typename T>
inline void dispose(std::unique_ptr<T>& object)
{
auto ptr = vk::disposable_t::make(object.release());
dispose(ptr);
}
void eid_completed(u64 eid)
{
while (!m_eid_map.empty())
@ -213,10 +205,15 @@ namespace vk
}
else
{
eid_scope_t tmp(0);
{
std::lock_guard lock(m_eid_map_lock);
m_eid_map.front().swap(tmp);
m_eid_map.pop_front();
}
}
}
}
void trim();
};

View File

@ -26,7 +26,7 @@ namespace vk
this->data = std::move(previous);
}
void texture_cache::cached_image_reference_t::dispose()
texture_cache::cached_image_reference_t::~cached_image_reference_t()
{
// Erase layout information to force TOP_OF_PIPE transition next time.
data->current_layout = VK_IMAGE_LAYOUT_UNDEFINED;
@ -208,7 +208,7 @@ namespace vk
{
if (tex.is_managed() && tex.exists())
{
auto disposable = std::unique_ptr<vk::disposable_t>(new cached_image_reference_t(this, tex.get_texture()));
auto disposable = vk::disposable_t::make(new cached_image_reference_t(this, tex.get_texture()));
vk::get_resource_manager()->dispose(disposable);
}
}
@ -745,7 +745,7 @@ namespace vk
ensure(resource);
auto image = std::unique_ptr<vk::viewable_image>(resource);
auto disposable = std::unique_ptr<vk::disposable_t>(new cached_image_reference_t(this, image));
auto disposable = vk::disposable_t::make(new cached_image_reference_t(this, image));
vk::get_resource_manager()->dispose(disposable);
}
@ -1288,7 +1288,7 @@ namespace vk
auto result = image.get();
const auto resource_memory = image->memory->size();
auto disposable = std::unique_ptr<vk::disposable_t>(new cached_image_reference_t(this, image));
auto disposable = vk::disposable_t::make(new cached_image_reference_t(this, image));
vk::get_resource_manager()->dispose(disposable);
return result;

View File

@ -356,13 +356,13 @@ namespace vk
using baseclass = rsx::texture_cache<vk::texture_cache, vk::texture_cache_traits>;
friend baseclass;
struct cached_image_reference_t : vk::disposable_t
struct cached_image_reference_t
{
std::unique_ptr<vk::viewable_image> data;
texture_cache* parent;
cached_image_reference_t(texture_cache* parent, std::unique_ptr<vk::viewable_image>& previous);
void dispose() override;
~cached_image_reference_t();
};
struct cached_image_t