mirror of
https://github.com/ARMSX2/ARMSX3.git
synced 2026-08-24 16:58:52 -07:00
vk: Run GC on the driver manager thread
This commit is contained in:
@@ -412,6 +412,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar)
|
||||
{
|
||||
// Initialize dependencies
|
||||
g_fxo->need<rsx::dma_manager>();
|
||||
g_fxo->need<vk::driver_manager_thread>();
|
||||
|
||||
if (!m_instance.create("RPCS3"))
|
||||
{
|
||||
@@ -1028,6 +1029,7 @@ bool VKGSRender::on_vram_exhausted(rsx::problem_severity severity)
|
||||
// Hard sync before trying to evict anything. This guarantees no UAF crashes in the driver.
|
||||
// As a bonus, we also get a free gc pass
|
||||
flush_command_queue(true, true);
|
||||
g_fxo->get<vk::driver_manager_thread>().drain();
|
||||
|
||||
if (m_texture_cache.is_overallocated())
|
||||
{
|
||||
@@ -2689,12 +2691,6 @@ void VKGSRender::renderctl(u32 request_code, void* args)
|
||||
free(packet);
|
||||
break;
|
||||
}
|
||||
case vk::rctrl_run_gc:
|
||||
{
|
||||
auto eid = reinterpret_cast<u64>(args);
|
||||
vk::on_event_completed(eid, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rsx::thread::renderctl(request_code, args);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace vk
|
||||
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;
|
||||
shared_mutex mutex;
|
||||
|
||||
void clear()
|
||||
{
|
||||
@@ -87,19 +88,13 @@ namespace vk
|
||||
return g_last_completed_event.load();
|
||||
}
|
||||
|
||||
void on_event_completed(u64 event_id, bool flush)
|
||||
void on_event_completed(u64 event_id)
|
||||
{
|
||||
if (!flush && g_cfg.video.multithreaded_rsx)
|
||||
g_fxo->get<vk::driver_manager_thread>().notify_completed(event_id);
|
||||
g_last_completed_event.atomic_op([event_id](u64& value)
|
||||
{
|
||||
auto& offloader_thread = g_fxo->get<rsx::dma_manager>();
|
||||
ensure(!offloader_thread.is_current_thread());
|
||||
|
||||
offloader_thread.backend_ctrl(rctrl_run_gc, reinterpret_cast<void*>(event_id));
|
||||
return;
|
||||
}
|
||||
|
||||
g_resource_manager.eid_completed(event_id);
|
||||
g_last_completed_event = std::max(event_id, g_last_completed_event.load());
|
||||
value = std::max(event_id, value);
|
||||
});
|
||||
}
|
||||
|
||||
void print_debug_markers()
|
||||
@@ -120,6 +115,8 @@ namespace vk
|
||||
auto key = reinterpret_cast<uptr>(handle);
|
||||
const vmm_allocation_t info = { memory_size, memory_type, pool };
|
||||
|
||||
std::lock_guard lock(g_vmm_stats.mutex);
|
||||
|
||||
if (const auto ins = g_vmm_stats.allocations.insert_or_assign(key, info);
|
||||
!ins.second)
|
||||
{
|
||||
@@ -140,6 +137,8 @@ namespace vk
|
||||
|
||||
void vmm_notify_memory_freed(void* handle)
|
||||
{
|
||||
std::lock_guard lock(g_vmm_stats.mutex);
|
||||
|
||||
auto key = reinterpret_cast<uptr>(handle);
|
||||
if (auto found = g_vmm_stats.allocations.find(key);
|
||||
found != g_vmm_stats.allocations.end())
|
||||
@@ -153,12 +152,14 @@ namespace vk
|
||||
|
||||
void vmm_reset()
|
||||
{
|
||||
std::lock_guard lock(g_vmm_stats.mutex);
|
||||
|
||||
g_vmm_stats.clear();
|
||||
g_event_ctr = 0;
|
||||
g_last_completed_event = 0;
|
||||
}
|
||||
|
||||
u64 vmm_get_application_memory_usage(const memory_type_info& memory_type)
|
||||
u64 vmm_get_application_memory_usage_impl(const memory_type_info& memory_type)
|
||||
{
|
||||
u64 result = 0;
|
||||
for (const auto& memory_type_index : memory_type)
|
||||
@@ -175,13 +176,32 @@ namespace vk
|
||||
return result;
|
||||
}
|
||||
|
||||
u64 vmm_get_application_memory_usage(const memory_type_info& memory_type)
|
||||
{
|
||||
reader_lock lock(g_vmm_stats.mutex);
|
||||
return vmm_get_application_memory_usage_impl(memory_type);
|
||||
}
|
||||
|
||||
u64 vmm_get_application_pool_usage_impl(vmm_allocation_pool pool)
|
||||
{
|
||||
if (auto found = g_vmm_stats.pool_usage.find(pool);
|
||||
found != g_vmm_stats.pool_usage.end())
|
||||
{
|
||||
return found->second;
|
||||
}
|
||||
return 0ull;
|
||||
}
|
||||
|
||||
u64 vmm_get_application_pool_usage(vmm_allocation_pool pool)
|
||||
{
|
||||
return g_vmm_stats.pool_usage[pool];
|
||||
reader_lock lock(g_vmm_stats.mutex);
|
||||
return vmm_get_application_pool_usage_impl(pool);
|
||||
}
|
||||
|
||||
rsx::problem_severity vmm_determine_memory_load_severity()
|
||||
{
|
||||
reader_lock lock(g_vmm_stats.mutex);
|
||||
|
||||
const auto vmm_load = get_current_mem_allocator()->get_memory_usage();
|
||||
rsx::problem_severity load_severity = rsx::problem_severity::low;
|
||||
|
||||
@@ -211,7 +231,7 @@ namespace vk
|
||||
|
||||
// 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);
|
||||
const auto local_memory_usage = vmm_get_application_memory_usage_impl(mem_info.device_local);
|
||||
|
||||
constexpr u64 _1M = 0x100000;
|
||||
const auto res_scale = rsx::get_current_renderer()->resolution_scaling_config.scale_factor();
|
||||
@@ -264,12 +284,16 @@ namespace vk
|
||||
|
||||
void vmm_notify_object_allocated(vmm_allocation_pool pool)
|
||||
{
|
||||
std::lock_guard lock(g_vmm_stats.mutex);
|
||||
|
||||
ensure(pool >= VMM_ALLOCATION_POOL_SAMPLER);
|
||||
g_vmm_stats.pool_usage[pool]++;
|
||||
}
|
||||
|
||||
void vmm_notify_object_freed(vmm_allocation_pool pool)
|
||||
{
|
||||
std::lock_guard lock(g_vmm_stats.mutex);
|
||||
|
||||
ensure(pool >= VMM_ALLOCATION_POOL_SAMPLER);
|
||||
g_vmm_stats.pool_usage[pool]--;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "Utilities/mutex.h"
|
||||
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
namespace vk
|
||||
@@ -14,7 +14,7 @@ namespace vk
|
||||
u64 get_event_id();
|
||||
u64 current_event_id();
|
||||
u64 last_completed_event_id();
|
||||
void on_event_completed(u64 event_id, bool flush = false);
|
||||
void on_event_completed(u64 event_id);
|
||||
|
||||
struct eid_scope_t
|
||||
{
|
||||
@@ -52,8 +52,8 @@ namespace vk
|
||||
private:
|
||||
sampler_pool_t m_sampler_pool;
|
||||
|
||||
std::deque<eid_scope_t> m_eid_map;
|
||||
shared_mutex m_eid_map_lock;
|
||||
std::list<eid_scope_t> m_eid_map;
|
||||
mutable shared_mutex m_eid_map_lock;
|
||||
|
||||
std::vector<std::function<void()>> m_exit_handlers;
|
||||
|
||||
@@ -61,7 +61,6 @@ namespace vk
|
||||
{
|
||||
const auto eid = current_event_id();
|
||||
{
|
||||
std::lock_guard lock(m_eid_map_lock);
|
||||
if (m_eid_map.empty() || m_eid_map.back().eid != eid)
|
||||
{
|
||||
m_eid_map.emplace_back(eid);
|
||||
@@ -88,7 +87,12 @@ namespace vk
|
||||
|
||||
void flush()
|
||||
{
|
||||
m_eid_map.clear();
|
||||
std::list<eid_scope_t> dispose_queue;
|
||||
{
|
||||
std::lock_guard lock(m_eid_map_lock);
|
||||
dispose_queue.splice(dispose_queue.begin(), m_eid_map);
|
||||
}
|
||||
|
||||
m_sampler_pool.clear();
|
||||
}
|
||||
|
||||
@@ -135,11 +139,13 @@ namespace vk
|
||||
|
||||
void dispose(vk::disposable_t& disposable) override
|
||||
{
|
||||
std::lock_guard lock(m_eid_map_lock);
|
||||
get_current_eid_scope().m_disposables.emplace_back(std::move(disposable));
|
||||
}
|
||||
|
||||
inline void dispose(std::unique_ptr<vk::gpu_debug_marker>& object)
|
||||
{
|
||||
std::lock_guard lock(m_eid_map_lock);
|
||||
// Special case as we may need to read these out.
|
||||
// FIXME: We can manage these markers better and remove this exception.
|
||||
get_current_eid_scope().m_debug_markers.emplace_back(std::move(object));
|
||||
@@ -154,32 +160,51 @@ namespace vk
|
||||
|
||||
void push_down_current_scope()
|
||||
{
|
||||
std::lock_guard lock(m_eid_map_lock);
|
||||
get_current_eid_scope().eid++;
|
||||
}
|
||||
|
||||
void eid_completed(u64 eid)
|
||||
{
|
||||
while (!m_eid_map.empty())
|
||||
// We move scope objects into this so that they're destroyed outside the lock.
|
||||
// These objects should outlive the lock, the idea is to release the main thread while the caller handles the callback spam.
|
||||
std::list<eid_scope_t> discarded_scopes;
|
||||
{
|
||||
const auto& scope = m_eid_map.front();
|
||||
if (scope.eid > eid)
|
||||
reader_lock lock(m_eid_map_lock);
|
||||
|
||||
// First, scan to find the newest item that is going out of scope
|
||||
auto newest_it = m_eid_map.begin();
|
||||
while (newest_it != m_eid_map.end() && newest_it->eid <= eid)
|
||||
{
|
||||
break;
|
||||
newest_it++;
|
||||
}
|
||||
|
||||
eid_scope_t tmp(0);
|
||||
// Any hits?
|
||||
if (newest_it == m_eid_map.begin())
|
||||
{
|
||||
std::lock_guard lock(m_eid_map_lock);
|
||||
m_eid_map.front().swap(tmp);
|
||||
m_eid_map.pop_front();
|
||||
return;
|
||||
}
|
||||
|
||||
// Take all of the entries in one sweep
|
||||
lock.upgrade();
|
||||
|
||||
// Post-upgrade iterators should be safe
|
||||
discarded_scopes.splice(
|
||||
discarded_scopes.end(),
|
||||
m_eid_map,
|
||||
m_eid_map.begin(),
|
||||
newest_it);
|
||||
}
|
||||
|
||||
// Cleanup runs here on the discard pile
|
||||
}
|
||||
|
||||
void trim();
|
||||
|
||||
std::vector<const gpu_debug_marker*> gather_debug_markers() const
|
||||
{
|
||||
reader_lock lock(m_eid_map_lock);
|
||||
|
||||
std::vector<const gpu_debug_marker*> result;
|
||||
for (const auto& scope : m_eid_map)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user