#include "stdafx.h" #include "VKCommandStream.h" #include "vkutils/descriptors.h" #include "vkutils/sync.h" #include "Emu/IdManager.h" #include "Emu/RSX/RSXOffload.h" #include "Emu/RSX/RSXThread.h" #include "Emu/system_config.h" namespace vk { // global submit guard to prevent race condition on queue submit shared_mutex g_submit_mutex; void acquire_global_submit_lock() { g_submit_mutex.lock(); } void release_global_submit_lock() { g_submit_mutex.unlock(); } FORCE_INLINE static void queue_submit_impl(const queue_submit_t& submit_info) { ensure(submit_info.pfence); acquire_global_submit_lock(); VkSubmitInfo info { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, .waitSemaphoreCount = submit_info.wait_semaphores_count, .pWaitSemaphores = submit_info.wait_semaphores.data(), .pWaitDstStageMask = submit_info.wait_stages.data(), .commandBufferCount = 1, .pCommandBuffers = &submit_info.commands, .signalSemaphoreCount = submit_info.signal_semaphores_count, .pSignalSemaphores = submit_info.signal_semaphores.data() }; vkQueueSubmit(submit_info.queue, 1, &info, submit_info.pfence->handle); release_global_submit_lock(); // Signal fence submit_info.pfence->signal_flushed(); } void queue_submit(const queue_submit_t& submit_info, VkBool32 flush) { rsx::get_current_renderer()->get_stats().submit_count++; // 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) { auto packet = new queue_submit_t(submit_info); g_fxo->get().backend_ctrl(rctrl_queue_submit, packet); } else { queue_submit_impl(submit_info); } } void queue_submit(const queue_submit_t* packet) { // Flush-only version used by asynchronous submit processing (MTRSX) queue_submit_impl(*packet); } }