diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index d68ab8c795..0f531f9825 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -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 diff --git a/rpcs3/Emu/RSX/VK/VKFrameContextManager.cpp b/rpcs3/Emu/RSX/VK/VKFrameContextManager.cpp new file mode 100644 index 0000000000..c163525b16 --- /dev/null +++ b/rpcs3/Emu/RSX/VK/VKFrameContextManager.cpp @@ -0,0 +1,58 @@ +#include "stdafx.h" +#include "VKFrameContextManager.h" + +#include "vkutils/data_heap.h" +#include + +namespace vk::frame_context_manager +{ + std::unordered_set g_managed_heaps; + + void register_ring_buffer(vk::data_heap& heap) + { + g_managed_heaps.insert(&heap); + } + + void register_ring_buffers(std::initializer_list> 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(); + } +} diff --git a/rpcs3/Emu/RSX/VK/VKFrameContextManager.h b/rpcs3/Emu/RSX/VK/VKFrameContextManager.h new file mode 100644 index 0000000000..d612b829f9 --- /dev/null +++ b/rpcs3/Emu/RSX/VK/VKFrameContextManager.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +#include + +namespace vk +{ + class data_heap; + + namespace frame_context_manager + { + using managed_heap_snapshot_t = std::unordered_map; + + // Submit ring buffer for management + void register_ring_buffer(vk::data_heap& heap); + + // Bulk registration + void register_ring_buffers(std::initializer_list> 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(); + } +} diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 430f4a7563..fb30b04662 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -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(); diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.h b/rpcs3/Emu/RSX/VK/VKGSRender.h index 5c72528ecc..19702ce314 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.h +++ b/rpcs3/Emu/RSX/VK/VKGSRender.h @@ -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; diff --git a/rpcs3/Emu/RSX/VK/VKGSRenderTypes.hpp b/rpcs3/Emu/RSX/VK/VKGSRenderTypes.hpp index 21997508e1..2aa62c858c 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRenderTypes.hpp +++ b/rpcs3/Emu/RSX/VK/VKGSRenderTypes.hpp @@ -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(); } diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index 6bc09588d4..1d743f170a 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -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); } } diff --git a/rpcs3/VKGSRender.vcxproj b/rpcs3/VKGSRender.vcxproj index fb5c517adc..c70985ddd1 100644 --- a/rpcs3/VKGSRender.vcxproj +++ b/rpcs3/VKGSRender.vcxproj @@ -23,6 +23,7 @@ + @@ -78,6 +79,7 @@ + diff --git a/rpcs3/VKGSRender.vcxproj.filters b/rpcs3/VKGSRender.vcxproj.filters index d9adc1939e..0edd3d0416 100644 --- a/rpcs3/VKGSRender.vcxproj.filters +++ b/rpcs3/VKGSRender.vcxproj.filters @@ -7,6 +7,7 @@ + @@ -87,6 +88,7 @@ +