vk: Add automatic heap management

This commit is contained in:
kd-11 2025-03-31 12:36:29 +03:00
parent 275f7e15c0
commit 35bca9ed8a
9 changed files with 119 additions and 87 deletions

View file

@ -632,6 +632,7 @@ if(TARGET 3rdparty_vulkan)
RSX/VK/VKFormats.cpp
RSX/VK/VKFragmentProgram.cpp
RSX/VK/VKFramebuffer.cpp
RSX/VK/VKFrameContextManager.cpp
RSX/VK/VKGSRender.cpp
RSX/VK/VKHelpers.cpp
RSX/VK/VKMemAlloc.cpp

View file

@ -0,0 +1,58 @@
#include "stdafx.h"
#include "VKFrameContextManager.h"
#include "vkutils/data_heap.h"
#include <unordered_set>
namespace vk::frame_context_manager
{
std::unordered_set<vk::data_heap*> g_managed_heaps;
void register_ring_buffer(vk::data_heap& heap)
{
g_managed_heaps.insert(&heap);
}
void register_ring_buffers(std::initializer_list<std::reference_wrapper<vk::data_heap>> heaps)
{
for (auto&& heap : heaps)
{
register_ring_buffer(heap);
}
}
managed_heap_snapshot_t get_heap_snapshot()
{
managed_heap_snapshot_t result{};
for (auto& heap : g_managed_heaps)
{
result[heap] = heap->get_current_put_pos_minus_one();
}
return result;
}
void restore_snapshot(const managed_heap_snapshot_t& snapshot)
{
for (auto& heap : g_managed_heaps)
{
const auto found = snapshot.find(heap);
if (found == snapshot.end())
{
continue;
}
heap->m_get_pos = found->second;
heap->notify();
}
}
void reset()
{
for (auto& heap : g_managed_heaps)
{
heap->destroy();
}
g_managed_heaps.clear();
}
}

View file

@ -0,0 +1,30 @@
#pragma once
#include <util/types.hpp>
#include <unordered_map>
namespace vk
{
class data_heap;
namespace frame_context_manager
{
using managed_heap_snapshot_t = std::unordered_map<const vk::data_heap*, s64>;
// Submit ring buffer for management
void register_ring_buffer(vk::data_heap& heap);
// Bulk registration
void register_ring_buffers(std::initializer_list<std::reference_wrapper<vk::data_heap>> heaps);
// Capture managed ring buffers snapshot at current time
managed_heap_snapshot_t get_heap_snapshot();
// Synchronize heap with snapshot
void restore_snapshot(const managed_heap_snapshot_t& snapshot);
// Cleanup
void reset();
}
}

View file

@ -527,6 +527,23 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar)
m_raster_env_ring_info.create(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_UBO_RING_BUFFER_SIZE_M * 0x100000, "raster env buffer");
m_instancing_buffer_ring_info.create(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_TRANSFORM_CONSTANTS_BUFFER_SIZE_M * 0x100000, "instancing data buffer");
vk::frame_context_manager::register_ring_buffers
({
std::ref(m_attrib_ring_info),
std::ref(m_fragment_env_ring_info),
std::ref(m_vertex_env_ring_info),
std::ref(m_fragment_texture_params_ring_info),
std::ref(m_vertex_layout_ring_info),
std::ref(m_fragment_constants_ring_info),
std::ref(m_transform_constants_ring_info),
std::ref(m_index_buffer_ring_info),
std::ref(m_texture_upload_buffer_ring_info),
std::ref(m_vertex_instructions_buffer),
std::ref(m_fragment_instructions_buffer),
std::ref(m_raster_env_ring_info),
std::ref(m_instancing_buffer_ring_info)
});
const auto shadermode = g_cfg.video.shadermode.get();
if (shadermode == shader_mode::async_with_interpreter || shadermode == shader_mode::interpreter_only)
@ -803,19 +820,7 @@ VKGSRender::~VKGSRender()
m_upscaler.reset();
// Heaps
m_attrib_ring_info.destroy();
m_fragment_env_ring_info.destroy();
m_vertex_env_ring_info.destroy();
m_fragment_texture_params_ring_info.destroy();
m_vertex_layout_ring_info.destroy();
m_fragment_constants_ring_info.destroy();
m_transform_constants_ring_info.destroy();
m_index_buffer_ring_info.destroy();
m_texture_upload_buffer_ring_info.destroy();
m_vertex_instructions_buffer.destroy();
m_fragment_instructions_buffer.destroy();
m_raster_env_ring_info.destroy();
m_instancing_buffer_ring_info.destroy();
vk::frame_context_manager::reset();
// Fallback bindables
null_buffer.reset();

View file

@ -143,6 +143,7 @@ private:
vk::data_heap m_texture_upload_buffer_ring_info; // Texture upload heap
vk::data_heap m_raster_env_ring_info; // Raster control such as polygon and line stipple
vk::data_heap m_instancing_buffer_ring_info; // Instanced rendering data (constants indirection table + instanced constants)
vk::data_heap m_draw_indirect_count_ring_info; // Buffer holding first-count data for multidraw support
vk::data_heap m_fragment_instructions_buffer;
vk::data_heap m_vertex_instructions_buffer;

View file

@ -2,6 +2,7 @@
#include "vkutils/commands.h"
#include "vkutils/descriptors.h"
#include "VKFrameContextManager.h"
#include "VKResourceManager.h"
#include "Emu/RSX/Common/simple_array.hpp"
@ -186,19 +187,7 @@ namespace vk
u32 present_image = -1;
command_buffer_chunk* swap_command_buffer = nullptr;
// Heap pointers
s64 attrib_heap_ptr = 0;
s64 vtx_env_heap_ptr = 0;
s64 frag_env_heap_ptr = 0;
s64 frag_const_heap_ptr = 0;
s64 vtx_const_heap_ptr = 0;
s64 vtx_layout_heap_ptr = 0;
s64 frag_texparam_heap_ptr = 0;
s64 index_heap_ptr = 0;
s64 texture_upload_heap_ptr = 0;
s64 rasterizer_env_heap_ptr = 0;
s64 instancing_heap_ptr = 0;
frame_context_manager::managed_heap_snapshot_t heap_snapshot;
u64 last_frame_sync_time = 0;
// Copy shareable information
@ -209,17 +198,7 @@ namespace vk
descriptor_set.swap(other.descriptor_set);
flags = other.flags;
attrib_heap_ptr = other.attrib_heap_ptr;
vtx_env_heap_ptr = other.vtx_env_heap_ptr;
frag_env_heap_ptr = other.frag_env_heap_ptr;
vtx_layout_heap_ptr = other.vtx_layout_heap_ptr;
frag_texparam_heap_ptr = other.frag_texparam_heap_ptr;
frag_const_heap_ptr = other.frag_const_heap_ptr;
vtx_const_heap_ptr = other.vtx_const_heap_ptr;
index_heap_ptr = other.index_heap_ptr;
texture_upload_heap_ptr = other.texture_upload_heap_ptr;
rasterizer_env_heap_ptr = other.rasterizer_env_heap_ptr;
instancing_heap_ptr = other.instancing_heap_ptr;
heap_snapshot = other.heap_snapshot;
}
// Exchange storage (non-copyable)
@ -228,23 +207,9 @@ namespace vk
std::swap(buffer_views_to_clean, other.buffer_views_to_clean);
}
void tag_frame_end(
s64 attrib_loc, s64 vtxenv_loc, s64 fragenv_loc, s64 vtxlayout_loc,
s64 fragtex_loc, s64 fragconst_loc, s64 vtxconst_loc, s64 index_loc,
s64 texture_loc, s64 rasterizer_loc, s64 instancing_loc)
void tag_frame_end()
{
attrib_heap_ptr = attrib_loc;
vtx_env_heap_ptr = vtxenv_loc;
frag_env_heap_ptr = fragenv_loc;
vtx_layout_heap_ptr = vtxlayout_loc;
frag_texparam_heap_ptr = fragtex_loc;
frag_const_heap_ptr = fragconst_loc;
vtx_const_heap_ptr = vtxconst_loc;
index_heap_ptr = index_loc;
texture_upload_heap_ptr = texture_loc;
rasterizer_env_heap_ptr = rasterizer_loc;
instancing_heap_ptr = instancing_loc;
heap_snapshot = frame_context_manager::get_heap_snapshot();
last_frame_sync_time = rsx::get_shared_tag();
}

View file

@ -155,17 +155,7 @@ void VKGSRender::advance_queued_frames()
vk::remove_unused_framebuffers();
m_vertex_cache->purge();
m_current_frame->tag_frame_end(m_attrib_ring_info.get_current_put_pos_minus_one(),
m_vertex_env_ring_info.get_current_put_pos_minus_one(),
m_fragment_env_ring_info.get_current_put_pos_minus_one(),
m_vertex_layout_ring_info.get_current_put_pos_minus_one(),
m_fragment_texture_params_ring_info.get_current_put_pos_minus_one(),
m_fragment_constants_ring_info.get_current_put_pos_minus_one(),
m_transform_constants_ring_info.get_current_put_pos_minus_one(),
m_index_buffer_ring_info.get_current_put_pos_minus_one(),
m_texture_upload_buffer_ring_info.get_current_put_pos_minus_one(),
m_raster_env_ring_info.get_current_put_pos_minus_one(),
m_instancing_buffer_ring_info.get_current_put_pos_minus_one());
m_current_frame->tag_frame_end();
m_queued_frames.push_back(m_current_frame);
ensure(m_queued_frames.size() <= VK_MAX_ASYNC_FRAMES);
@ -259,29 +249,7 @@ void VKGSRender::frame_context_cleanup(vk::frame_context_t *ctx)
m_last_heap_sync_time = ctx->last_frame_sync_time;
// Heap cleanup; deallocates memory consumed by the frame if it is still held
m_attrib_ring_info.m_get_pos = ctx->attrib_heap_ptr;
m_vertex_env_ring_info.m_get_pos = ctx->vtx_env_heap_ptr;
m_fragment_env_ring_info.m_get_pos = ctx->frag_env_heap_ptr;
m_fragment_constants_ring_info.m_get_pos = ctx->frag_const_heap_ptr;
m_transform_constants_ring_info.m_get_pos = ctx->vtx_const_heap_ptr;
m_vertex_layout_ring_info.m_get_pos = ctx->vtx_layout_heap_ptr;
m_fragment_texture_params_ring_info.m_get_pos = ctx->frag_texparam_heap_ptr;
m_index_buffer_ring_info.m_get_pos = ctx->index_heap_ptr;
m_texture_upload_buffer_ring_info.m_get_pos = ctx->texture_upload_heap_ptr;
m_raster_env_ring_info.m_get_pos = ctx->rasterizer_env_heap_ptr;
m_instancing_buffer_ring_info.m_get_pos = ctx->instancing_heap_ptr;
m_attrib_ring_info.notify();
m_vertex_env_ring_info.notify();
m_fragment_env_ring_info.notify();
m_fragment_constants_ring_info.notify();
m_transform_constants_ring_info.notify();
m_vertex_layout_ring_info.notify();
m_fragment_texture_params_ring_info.notify();
m_index_buffer_ring_info.notify();
m_texture_upload_buffer_ring_info.notify();
m_raster_env_ring_info.notify();
m_instancing_buffer_ring_info.notify();
vk::frame_context_manager::restore_snapshot(ctx->heap_snapshot);
}
}

View file

@ -23,6 +23,7 @@
<ClInclude Include="Emu\RSX\VK\VKFormats.h" />
<ClInclude Include="Emu\RSX\VK\VKFragmentProgram.h" />
<ClInclude Include="Emu\RSX\VK\VKFramebuffer.h" />
<ClInclude Include="Emu\RSX\VK\VKFrameContextManager.h" />
<ClInclude Include="Emu\RSX\VK\VKGSRender.h" />
<ClInclude Include="Emu\RSX\VK\VKGSRenderTypes.hpp" />
<ClInclude Include="Emu\RSX\VK\VKHelpers.h" />
@ -78,6 +79,7 @@
<ClCompile Include="Emu\RSX\VK\VKFormats.cpp" />
<ClCompile Include="Emu\RSX\VK\VKFragmentProgram.cpp" />
<ClCompile Include="Emu\RSX\VK\VKFramebuffer.cpp" />
<ClCompile Include="Emu\RSX\VK\VKFrameContextManager.cpp" />
<ClCompile Include="Emu\RSX\VK\VKGSRender.cpp" />
<ClCompile Include="Emu\RSX\VK\VKHelpers.cpp" />
<ClCompile Include="Emu\RSX\VK\VKOverlays.cpp" />

View file

@ -7,6 +7,7 @@
<ClCompile Include="Emu\RSX\VK\VKFormats.cpp" />
<ClCompile Include="Emu\RSX\VK\VKFragmentProgram.cpp" />
<ClCompile Include="Emu\RSX\VK\VKFramebuffer.cpp" />
<ClCompile Include="Emu\RSX\VK\VKFrameContextManager.cpp" />
<ClCompile Include="Emu\RSX\VK\VKGSRender.cpp" />
<ClCompile Include="Emu\RSX\VK\VKHelpers.cpp" />
<ClCompile Include="Emu\RSX\VK\VKPresent.cpp" />
@ -87,6 +88,7 @@
<ClInclude Include="Emu\RSX\VK\VKFormats.h" />
<ClInclude Include="Emu\RSX\VK\VKFragmentProgram.h" />
<ClInclude Include="Emu\RSX\VK\VKFramebuffer.h" />
<ClInclude Include="Emu\RSX\VK\VKFrameContextManager.h" />
<ClInclude Include="Emu\RSX\VK\VKGSRender.h" />
<ClInclude Include="Emu\RSX\VK\VKHelpers.h" />
<ClInclude Include="Emu\RSX\VK\VKOverlays.h" />