mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-13 10:18:40 +12:00
vk: Rewrite resource management
This commit is contained in:
parent
48b54131f6
commit
f667b52cca
6 changed files with 85 additions and 77 deletions
|
@ -655,9 +655,6 @@ VKGSRender::~VKGSRender()
|
||||||
// Upscaler (references some global resources)
|
// Upscaler (references some global resources)
|
||||||
m_upscaler.reset();
|
m_upscaler.reset();
|
||||||
|
|
||||||
// Global resources
|
|
||||||
vk::destroy_global_resources();
|
|
||||||
|
|
||||||
// Heaps
|
// Heaps
|
||||||
m_attrib_ring_info.destroy();
|
m_attrib_ring_info.destroy();
|
||||||
m_fragment_env_ring_info.destroy();
|
m_fragment_env_ring_info.destroy();
|
||||||
|
@ -722,6 +719,9 @@ VKGSRender::~VKGSRender()
|
||||||
m_secondary_command_buffer.destroy();
|
m_secondary_command_buffer.destroy();
|
||||||
m_secondary_command_buffer_pool.destroy();
|
m_secondary_command_buffer_pool.destroy();
|
||||||
|
|
||||||
|
// Global resources
|
||||||
|
vk::destroy_global_resources();
|
||||||
|
|
||||||
// Device handles/contexts
|
// Device handles/contexts
|
||||||
m_swapchain->destroy();
|
m_swapchain->destroy();
|
||||||
m_instance.destroy();
|
m_instance.destroy();
|
||||||
|
|
|
@ -67,7 +67,6 @@ namespace vk
|
||||||
vk::clear_framebuffer_cache();
|
vk::clear_framebuffer_cache();
|
||||||
vk::clear_resolve_helpers();
|
vk::clear_resolve_helpers();
|
||||||
vk::clear_dma_resources();
|
vk::clear_dma_resources();
|
||||||
vk::vmm_reset();
|
|
||||||
vk::clear_scratch_resources();
|
vk::clear_scratch_resources();
|
||||||
|
|
||||||
vk::get_upload_heap()->destroy();
|
vk::get_upload_heap()->destroy();
|
||||||
|
@ -82,6 +81,9 @@ namespace vk
|
||||||
|
|
||||||
// This must be the last item destroyed
|
// This must be the last item destroyed
|
||||||
vk::get_resource_manager()->destroy();
|
vk::get_resource_manager()->destroy();
|
||||||
|
|
||||||
|
// Statistics counter reset. Also verifies that everything was deleted.
|
||||||
|
vk::vmm_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
const vk::render_device *get_current_renderer()
|
const vk::render_device *get_current_renderer()
|
||||||
|
|
|
@ -13,6 +13,16 @@ namespace vk
|
||||||
|
|
||||||
void clear()
|
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();
|
allocations.clear();
|
||||||
memory_usage.clear();
|
memory_usage.clear();
|
||||||
pool_usage.clear();
|
pool_usage.clear();
|
||||||
|
@ -44,12 +54,11 @@ namespace vk
|
||||||
ensure(max_allowed_samplers);
|
ensure(max_allowed_samplers);
|
||||||
rsx_log.warning("Trimming allocated samplers. Allocated = %u, Max = %u", allocated_sampler_count, limits.maxSamplerAllocationCount);
|
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();)
|
for (auto It = m_sampler_pool.begin(); It != m_sampler_pool.end();)
|
||||||
{
|
{
|
||||||
if (!It->second->has_refs())
|
if (!It->second->has_refs())
|
||||||
{
|
{
|
||||||
disposed_samplers_pool.emplace_back(std::move(It->second));
|
dispose(It->second);
|
||||||
It = m_sampler_pool.erase(It);
|
It = m_sampler_pool.erase(It);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
#include "vkutils/query_pool.hpp"
|
#include "vkutils/query_pool.hpp"
|
||||||
#include "vkutils/sampler.h"
|
#include "vkutils/sampler.h"
|
||||||
|
|
||||||
|
#include "Utilities/mutex.h"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -14,22 +16,47 @@ namespace vk
|
||||||
u64 last_completed_event_id();
|
u64 last_completed_event_id();
|
||||||
void on_event_completed(u64 event_id, bool flush = false);
|
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
|
struct eid_scope_t
|
||||||
{
|
{
|
||||||
u64 eid;
|
u64 eid;
|
||||||
const vk::render_device* m_device;
|
const vk::render_device* m_device;
|
||||||
std::vector<std::unique_ptr<vk::buffer>> m_disposed_buffers;
|
std::vector<disposable_t> m_disposables;
|
||||||
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;
|
|
||||||
|
|
||||||
eid_scope_t(u64 _eid):
|
eid_scope_t(u64 _eid):
|
||||||
eid(_eid), m_device(g_render_device)
|
eid(_eid), m_device(g_render_device)
|
||||||
|
@ -40,19 +67,15 @@ namespace vk
|
||||||
discard();
|
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()
|
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();
|
m_disposables.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -67,20 +90,18 @@ namespace vk
|
||||||
|
|
||||||
std::unordered_map<u64, std::unique_ptr<cached_sampler_object_t>> m_sampler_pool;
|
std::unordered_map<u64, std::unique_ptr<cached_sampler_object_t>> m_sampler_pool;
|
||||||
std::deque<eid_scope_t> m_eid_map;
|
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();
|
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
|
std::lock_guard lock(m_eid_map_lock);
|
||||||
if (auto &old = m_eid_map.back(); old.eid == eid)
|
if (m_eid_map.empty() || m_eid_map.back().eid != eid)
|
||||||
{
|
{
|
||||||
return old;
|
m_eid_map.emplace_back(eid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_eid_map.emplace_back(eid);
|
|
||||||
return m_eid_map.back();
|
return m_eid_map.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,47 +182,18 @@ namespace vk
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispose(std::unique_ptr<vk::buffer>& buf)
|
inline void dispose(vk::disposable_t& disposable)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
get_current_eid_scope().m_disposables.emplace_back(std::move(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)
|
void eid_completed(u64 eid)
|
||||||
{
|
{
|
||||||
while (!m_eid_map.empty())
|
while (!m_eid_map.empty())
|
||||||
|
@ -213,7 +205,12 @@ namespace vk
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_eid_map.pop_front();
|
eid_scope_t tmp(0);
|
||||||
|
{
|
||||||
|
std::lock_guard lock(m_eid_map_lock);
|
||||||
|
m_eid_map.front().swap(tmp);
|
||||||
|
m_eid_map.pop_front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace vk
|
||||||
this->data = std::move(previous);
|
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.
|
// Erase layout information to force TOP_OF_PIPE transition next time.
|
||||||
data->current_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
data->current_layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
@ -208,7 +208,7 @@ namespace vk
|
||||||
{
|
{
|
||||||
if (tex.is_managed() && tex.exists())
|
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);
|
vk::get_resource_manager()->dispose(disposable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -745,7 +745,7 @@ namespace vk
|
||||||
ensure(resource);
|
ensure(resource);
|
||||||
|
|
||||||
auto image = std::unique_ptr<vk::viewable_image>(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);
|
vk::get_resource_manager()->dispose(disposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1288,7 +1288,7 @@ namespace vk
|
||||||
|
|
||||||
auto result = image.get();
|
auto result = image.get();
|
||||||
const auto resource_memory = image->memory->size();
|
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);
|
vk::get_resource_manager()->dispose(disposable);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -356,13 +356,13 @@ namespace vk
|
||||||
using baseclass = rsx::texture_cache<vk::texture_cache, vk::texture_cache_traits>;
|
using baseclass = rsx::texture_cache<vk::texture_cache, vk::texture_cache_traits>;
|
||||||
friend baseclass;
|
friend baseclass;
|
||||||
|
|
||||||
struct cached_image_reference_t : vk::disposable_t
|
struct cached_image_reference_t
|
||||||
{
|
{
|
||||||
std::unique_ptr<vk::viewable_image> data;
|
std::unique_ptr<vk::viewable_image> data;
|
||||||
texture_cache* parent;
|
texture_cache* parent;
|
||||||
|
|
||||||
cached_image_reference_t(texture_cache* parent, std::unique_ptr<vk::viewable_image>& previous);
|
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
|
struct cached_image_t
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue