From 28ab9913020f88912c3f381b261407d9780361c7 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sat, 25 Apr 2026 21:09:59 +0300 Subject: [PATCH] vk: Support more heap types - Support for GPU shadow heap (manual flush) - Support for Fixed-Length data heaps --- rpcs3/Emu/RSX/VK/vkutils/data_heap.cpp | 29 ++++++++++++++++++++++---- rpcs3/Emu/RSX/VK/vkutils/data_heap.h | 9 ++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/RSX/VK/vkutils/data_heap.cpp b/rpcs3/Emu/RSX/VK/vkutils/data_heap.cpp index e3207875f8..f92532ccf7 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/data_heap.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/data_heap.cpp @@ -19,6 +19,9 @@ namespace vk const auto& memory_map = g_render_device->get_memory_mapping(); + ensure(std::popcount(flags & (heap_pool_force_vram_shadow | heap_pool_low_latency)) <= 1, + "Invalid data heap flag combination detected"); + if ((flags & heap_pool_low_latency) && g_cfg.video.vk.use_rebar_upload_heap) { // Prefer uploading to BAR if low latency is desired. @@ -39,9 +42,15 @@ namespace vk VkFlags memory_flags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; auto memory_index = m_prefer_writethrough ? memory_map.device_bar : memory_map.host_visible_coherent; - if (!(get_heap_compatible_buffer_types() & usage)) + const bool vram_shadow_requested = !!(flags & heap_pool_force_vram_shadow); + const bool use_shadow = vram_shadow_requested || !(get_heap_compatible_buffer_types() & usage); + + if (use_shadow) { - rsx_log.warning("Buffer usage %u is not heap-compatible using this driver, explicit staging buffer in use", usage); + if (!vram_shadow_requested) + { + rsx_log.warning("Buffer usage %u is not heap-compatible using this driver, explicit staging buffer in use", usage); + } shadow = std::make_unique(*g_render_device, size, memory_index, memory_flags, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, 0, VMM_ALLOCATION_POOL_SYSTEM); usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; @@ -70,6 +79,7 @@ namespace vk heap = std::make_unique(*g_render_device, size, memory_map.host_visible_coherent, memory_flags, usage, 0, VMM_ALLOCATION_POOL_SYSTEM); } + m_flags = flags; initial_size = size; notify_on_grow = bool(notify); } @@ -88,7 +98,7 @@ namespace vk bool data_heap::grow(usz size) { // Create new heap. All sizes are aligned up by 64M, upto 1GiB - const usz size_limit = 1024 * 0x100000; + const usz size_limit = (m_flags & heap_pool_fixed_size) ? initial_size : 1024 * 0x100000; usz aligned_new_size = utils::align(m_size + size, 64 * 0x100000); if (aligned_new_size >= size_limit) @@ -192,7 +202,18 @@ namespace vk if (shadow) { - dirty_ranges.push_back({ offset, offset, size }); + bool insert = true; + if (!dirty_ranges.empty() && (dirty_ranges.back().dstOffset + dirty_ranges.back().size) == offset) [[ likely ]] + { + dirty_ranges.back().size += size; + insert = false; + } + + if (insert) + { + dirty_ranges.push_back({ offset, offset, size }); + } + raise_status_interrupt(runtime_state::heap_dirty); } diff --git a/rpcs3/Emu/RSX/VK/vkutils/data_heap.h b/rpcs3/Emu/RSX/VK/vkutils/data_heap.h index 6732f639dc..13ec2a5fdc 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/data_heap.h +++ b/rpcs3/Emu/RSX/VK/vkutils/data_heap.h @@ -13,8 +13,10 @@ namespace vk { enum data_heap_pool_flags { - heap_pool_default = 0, - heap_pool_low_latency = 1, + heap_pool_default = 0, + heap_pool_low_latency = (1 << 0), + heap_pool_fixed_size = (1 << 1), + heap_pool_force_vram_shadow = (1 << 2), }; class data_heap : public ::data_heap @@ -24,6 +26,8 @@ namespace vk bool mapped = false; void* _ptr = nullptr; + rsx::flags32_t m_flags = heap_pool_default; + bool notify_on_grow = false; bool m_prefer_writethrough = false; @@ -60,6 +64,7 @@ namespace vk // Properties bool is_dirty() const; + bool has_shadow() const { return !!shadow; } }; extern data_heap* get_upload_heap();