From dc8fc9fc798e24ccf9933d80db2b6242abf62be6 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 28 Sep 2021 20:42:38 +0300 Subject: [PATCH] vk: Clean up around vkQueueSubmit handling - Explicitly declare one version for CB flush and the other for Async flush - Always flush descriptors on CB flush in case of page fault handling. Other threads other than offloader can also enter the method and require normal flow. - Fix overlapping interrupt IDs. - Minor formatting fixes --- rpcs3/Emu/RSX/Common/bitfield.hpp | 2 +- rpcs3/Emu/RSX/VK/VKCommandStream.cpp | 31 ++++++++++++++++++--------- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 14 ++++++------ rpcs3/Emu/RSX/VK/VKHelpers.h | 18 ++++++++-------- rpcs3/Emu/RSX/VK/vkutils/commands.cpp | 2 +- rpcs3/Emu/RSX/VK/vkutils/commands.h | 4 ++-- 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/bitfield.hpp b/rpcs3/Emu/RSX/Common/bitfield.hpp index ee67d415e8..c1b8af5f8e 100644 --- a/rpcs3/Emu/RSX/Common/bitfield.hpp +++ b/rpcs3/Emu/RSX/Common/bitfield.hpp @@ -87,7 +87,7 @@ namespace rsx void clear() { - m_data.store(0); + m_data.release(0); } }; } diff --git a/rpcs3/Emu/RSX/VK/VKCommandStream.cpp b/rpcs3/Emu/RSX/VK/VKCommandStream.cpp index b9a442a4f1..fc2bdd7a4a 100644 --- a/rpcs3/Emu/RSX/VK/VKCommandStream.cpp +++ b/rpcs3/Emu/RSX/VK/VKCommandStream.cpp @@ -23,12 +23,22 @@ namespace vk g_submit_mutex.unlock(); } + FORCE_INLINE + static void queue_submit_impl(VkQueue queue, const VkSubmitInfo* info, fence* pfence) + { + acquire_global_submit_lock(); + vkQueueSubmit(queue, 1, info, pfence->handle); + release_global_submit_lock(); + + // Signal fence + pfence->signal_flushed(); + } + void queue_submit(VkQueue queue, const VkSubmitInfo* info, fence* pfence, VkBool32 flush) { - if (rsx::get_current_renderer()->is_current_thread()) - { - vk::descriptors::flush(); - } + // Access to this method must be externally synchronized. + // Offloader is guaranteed to never call this for async flushes. + vk::descriptors::flush(); if (!flush && g_cfg.video.multithreaded_rsx) { @@ -37,12 +47,13 @@ namespace vk } else { - acquire_global_submit_lock(); - vkQueueSubmit(queue, 1, info, pfence->handle); - release_global_submit_lock(); - - // Signal fence - pfence->signal_flushed(); + queue_submit_impl(queue, info, pfence); } } + + void queue_submit(const vk::submit_packet* packet) + { + // Flush-only version used by asynchronous submit processing (MTRSX) + queue_submit_impl(packet->queue, &packet->submit_info, packet->pfence); + } } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index fc2bc537f3..6f2b182833 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -760,9 +760,9 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing) } bool has_queue_ref = false; - if (!is_current_thread()) + if (!is_current_thread()) [[likely]] { - //Always submit primary cb to ensure state consistency (flush pending changes such as image transitions) + // Always submit primary cb to ensure state consistency (flush pending changes such as image transitions) vm::temporary_unlock(); std::lock_guard lock(m_flush_queue_mutex); @@ -777,13 +777,13 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing) rsx_log.error("Fault in uninterruptible code!"); } - //Flush primary cb queue to sync pending changes (e.g image transitions!) + // Flush primary cb queue to sync pending changes (e.g image transitions!) flush_command_queue(); } if (has_queue_ref) { - //Wait for the RSX thread to process request if it hasn't already + // Wait for the RSX thread to process request if it hasn't already m_flush_requests.producer_wait(); } @@ -791,7 +791,7 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing) if (has_queue_ref) { - //Release RSX thread + // Release RSX thread m_flush_requests.remove_one(); } } @@ -2340,8 +2340,8 @@ void VKGSRender::renderctl(u32 request_code, void* args) { case vk::rctrl_queue_submit: { - auto packet = reinterpret_cast(args); - vk::queue_submit(packet->queue, &packet->submit_info, packet->pfence, VK_TRUE); + const auto packet = reinterpret_cast(args); + vk::queue_submit(packet); free(packet); break; } diff --git a/rpcs3/Emu/RSX/VK/VKHelpers.h b/rpcs3/Emu/RSX/VK/VKHelpers.h index 742467775a..58019eaae7 100644 --- a/rpcs3/Emu/RSX/VK/VKHelpers.h +++ b/rpcs3/Emu/RSX/VK/VKHelpers.h @@ -32,19 +32,19 @@ namespace vk class image; class instance; class render_device; + struct submit_packet; - //VkAllocationCallbacks default_callbacks(); enum runtime_state { uninterruptible = 1, - heap_dirty = 2, - heap_changed = 3 + heap_dirty = 2, + heap_changed = 4, }; const vk::render_device *get_current_renderer(); void set_current_renderer(const vk::render_device &device); - //Compatibility workarounds + // Compatibility workarounds bool emulate_primitive_restart(rsx::primitive_type type); bool sanitize_fp_values(); bool fence_reset_disabled(); @@ -54,7 +54,7 @@ namespace vk // Sync helpers around vkQueueSubmit void acquire_global_submit_lock(); void release_global_submit_lock(); - void queue_submit(VkQueue queue, const VkSubmitInfo* info, fence* pfence, VkBool32 flush = VK_FALSE); + void queue_submit(const vk::submit_packet* packet); template T* get_compute_task(); @@ -64,12 +64,12 @@ namespace vk enum image_upload_options { - upload_contents_async = 1, + upload_contents_async = 1, initialize_image_layout = 2, - preserve_image_layout = 4, + preserve_image_layout = 4, // meta-flags - upload_contents_inline = 0, + upload_contents_inline = 0, upload_heap_align_default = 0 }; @@ -77,7 +77,7 @@ namespace vk const std::vector& subresource_layout, int format, bool is_swizzled, u16 layer_count, VkImageAspectFlags flags, vk::data_heap &upload_heap, u32 heap_align, rsx::flags32_t image_setup_flags); - //Other texture management helpers + // Other texture management helpers void copy_image_to_buffer(VkCommandBuffer cmd, const vk::image* src, const vk::buffer* dst, const VkBufferImageCopy& region, bool swap_bytes = false); void copy_buffer_to_image(VkCommandBuffer cmd, const vk::buffer* src, const vk::image* dst, const VkBufferImageCopy& region); u64 calculate_working_buffer_size(u64 base_size, VkImageAspectFlags aspect); diff --git a/rpcs3/Emu/RSX/VK/vkutils/commands.cpp b/rpcs3/Emu/RSX/VK/vkutils/commands.cpp index 162cf3c9a4..44a89315ab 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/commands.cpp +++ b/rpcs3/Emu/RSX/VK/vkutils/commands.cpp @@ -6,7 +6,7 @@ namespace vk { // This queue flushing method to be implemented by the backend as behavior depends on config - void queue_submit(VkQueue queue, const VkSubmitInfo* info, fence* pfence, VkBool32 flush = VK_FALSE); + void queue_submit(VkQueue queue, const VkSubmitInfo* info, fence* pfence, VkBool32 flush); void command_pool::create(vk::render_device& dev, u32 queue_family_id) { diff --git a/rpcs3/Emu/RSX/VK/vkutils/commands.h b/rpcs3/Emu/RSX/VK/vkutils/commands.h index 39db239872..e70f1ef8cd 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/commands.h +++ b/rpcs3/Emu/RSX/VK/vkutils/commands.h @@ -39,8 +39,8 @@ namespace vk public: enum access_type_hint { - flush_only, //Only to be submitted/opened/closed via command flush - all //Auxiliary, can be submitted/opened/closed at any time + flush_only, // Only to be submitted/opened/closed via command flush + all // Auxiliary, can be submitted/opened/closed at any time } access_hint = flush_only;