vk: Implement multithreaded command submission

- A few nagging issues remain, specifically that partial command stream
  largely caused by poor synchronization structures for partial CS flush
  and also the fact that occlusion map entries wait on a command buffer
  and not an EID!
This commit is contained in:
kd-11 2019-12-07 16:28:35 +03:00 committed by kd-11
parent 5be7f08965
commit a51395370e
14 changed files with 283 additions and 196 deletions

View file

@ -385,6 +385,7 @@ target_sources(rpcs3_emu PRIVATE
if(TARGET 3rdparty_vulkan) if(TARGET 3rdparty_vulkan)
target_sources(rpcs3_emu PRIVATE target_sources(rpcs3_emu PRIVATE
RSX/VK/VKCommandStream.cpp
RSX/VK/VKCommonDecompiler.cpp RSX/VK/VKCommonDecompiler.cpp
RSX/VK/VKDMA.cpp RSX/VK/VKDMA.cpp
RSX/VK/VKFormats.cpp RSX/VK/VKFormats.cpp

View file

@ -57,6 +57,9 @@ namespace rsx
static_cast<rsx::primitive_type>(m_current_job->aux_param0), static_cast<rsx::primitive_type>(m_current_job->aux_param0),
m_current_job->length); m_current_job->length);
break; break;
case callback:
rsx::get_current_renderer()->renderctl(m_current_job->aux_param0, m_current_job->src);
break;
default: default:
ASSUME(0); ASSUME(0);
fmt::throw_exception("Unreachable" HERE); fmt::throw_exception("Unreachable" HERE);
@ -119,6 +122,15 @@ namespace rsx
} }
} }
// Backend callback
void dma_manager::backend_ctrl(u32 request_code, void* args)
{
verify(HERE), g_cfg.video.multithreaded_rsx;
++m_enqueued_count;
m_work_queue.push(request_code, args);
}
// Synchronization // Synchronization
bool dma_manager::is_current_thread() const bool dma_manager::is_current_thread() const
{ {

View file

@ -17,7 +17,8 @@ namespace rsx
{ {
raw_copy = 0, raw_copy = 0,
vector_copy = 1, vector_copy = 1,
index_emulate = 2 index_emulate = 2,
callback = 3
}; };
struct transport_packet struct transport_packet
@ -41,6 +42,10 @@ namespace rsx
transport_packet(void *_dst, rsx::primitive_type prim, u32 len) transport_packet(void *_dst, rsx::primitive_type prim, u32 len)
: dst(_dst), aux_param0(static_cast<u8>(prim)), length(len), type(op::index_emulate) : dst(_dst), aux_param0(static_cast<u8>(prim)), length(len), type(op::index_emulate)
{} {}
transport_packet(u32 command, void* args)
: aux_param0(command), src(args), type(op::callback)
{}
}; };
lf_queue<transport_packet> m_work_queue; lf_queue<transport_packet> m_work_queue;
@ -67,6 +72,9 @@ namespace rsx
// Vertex utilities // Vertex utilities
void emulate_as_indexed(void *dst, rsx::primitive_type primitive, u32 count); void emulate_as_indexed(void *dst, rsx::primitive_type primitive, u32 count);
// Renderer callback
void backend_ctrl(u32 request_code, void* args);
// Synchronization // Synchronization
bool is_current_thread() const; bool is_current_thread() const;
void sync(); void sync();

View file

@ -446,10 +446,10 @@ namespace rsx
rsx::overlays::reset_performance_overlay(); rsx::overlays::reset_performance_overlay();
g_dma_manager.init();
on_init_thread(); on_init_thread();
method_registers.init(); method_registers.init();
g_dma_manager.init();
m_profiler.enabled = !!g_cfg.video.overlay; m_profiler.enabled = !!g_cfg.video.overlay;
if (!zcull_ctrl) if (!zcull_ctrl)

View file

@ -753,6 +753,9 @@ namespace rsx
virtual void on_invalidate_memory_range(const address_range & /*range*/, rsx::invalidation_cause) {} virtual void on_invalidate_memory_range(const address_range & /*range*/, rsx::invalidation_cause) {}
virtual void notify_tile_unbound(u32 /*tile*/) {} virtual void notify_tile_unbound(u32 /*tile*/) {}
// control
virtual void renderctl(u32 request_code, void* args) {}
// zcull // zcull
void notify_zcull_info_changed(); void notify_zcull_info_changed();
void clear_zcull_stats(u32 type); void clear_zcull_stats(u32 type);

View file

@ -0,0 +1,36 @@
#include "stdafx.h"
#include "VKCommandStream.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();
}
void queue_submit(VkQueue queue, const VkSubmitInfo* info, fence* pfence, VkBool32 flush)
{
if (!flush && g_cfg.video.multithreaded_rsx)
{
auto packet = new submit_packet(queue, pfence, info);
rsx::g_dma_manager.backend_ctrl(rctrl_queue_submit, packet);
}
else
{
acquire_global_submit_lock();
vkQueueSubmit(queue, 1, info, pfence->handle);
release_global_submit_lock();
// Signal fence
pfence->flushed = true;
}
}
}

View file

@ -0,0 +1,42 @@
#pragma once
#include "VKHelpers.h"
namespace vk
{
struct submit_packet
{
// Core components
VkQueue queue;
fence* pfence;
VkSubmitInfo submit_info;
// Pointer redirection storage
VkSemaphore wait_semaphore;
VkSemaphore signal_semaphore;
VkFlags wait_flags;
submit_packet(VkQueue _q, fence* _f, const VkSubmitInfo* info) :
queue(_q), pfence(_f), submit_info(*info),
wait_semaphore(0), signal_semaphore(0), wait_flags(0)
{
if (info->waitSemaphoreCount)
{
wait_semaphore = *info->pWaitSemaphores;
submit_info.pWaitSemaphores = &wait_semaphore;
}
if (info->signalSemaphoreCount)
{
signal_semaphore = *info->pSignalSemaphores;
submit_info.pSignalSemaphores = &signal_semaphore;
}
if (info->pWaitDstStageMask)
{
wait_flags = *info->pWaitDstStageMask;
submit_info.pWaitDstStageMask = &wait_flags;
}
}
};
}

View file

@ -9,6 +9,7 @@
#include "VKCommonDecompiler.h" #include "VKCommonDecompiler.h"
#include "VKRenderPass.h" #include "VKRenderPass.h"
#include "VKResourceManager.h" #include "VKResourceManager.h"
#include "VKCommandStream.h"
namespace namespace
{ {
@ -2157,10 +2158,12 @@ void VKGSRender::flush_command_queue(bool hard_sync)
} }
else else
{ {
// Mark this queue as pending // Mark this queue as pending and proceed
m_current_command_buffer->pending = true; m_current_command_buffer->pending = true;
}
// Grab next cb in line and make it usable // Grab next cb in line and make it usable
// NOTE: Even in the case of a hard sync, this is required to free any waiters on the CB (ZCULL)
m_current_cb_index = (m_current_cb_index + 1) % VK_MAX_ASYNC_CB_COUNT; m_current_cb_index = (m_current_cb_index + 1) % VK_MAX_ASYNC_CB_COUNT;
m_current_command_buffer = &m_primary_cb_list[m_current_cb_index]; m_current_command_buffer = &m_primary_cb_list[m_current_cb_index];
@ -2173,7 +2176,6 @@ void VKGSRender::flush_command_queue(bool hard_sync)
// Just in case a queued frame holds a ref to this cb, drain the present queue // Just in case a queued frame holds a ref to this cb, drain the present queue
check_present_status(); check_present_status();
}
if (m_occlusion_query_active) if (m_occlusion_query_active)
{ {
@ -2278,6 +2280,9 @@ void VKGSRender::present(frame_context_t *ctx)
{ {
verify(HERE), ctx->present_image != UINT32_MAX; verify(HERE), ctx->present_image != UINT32_MAX;
// Partial CS flush
ctx->swap_command_buffer->flush();
if (!swapchain_unavailable) if (!swapchain_unavailable)
{ {
switch (VkResult error = m_swapchain->present(ctx->present_wait_semaphore, ctx->present_image)) switch (VkResult error = m_swapchain->present(ctx->present_wait_semaphore, ctx->present_image))
@ -2824,11 +2829,9 @@ void VKGSRender::init_buffers(rsx::framebuffer_creation_context context, bool)
prepare_rtts(context); prepare_rtts(context);
} }
void VKGSRender::close_and_submit_command_buffer(VkFence fence, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkPipelineStageFlags pipeline_stage_flags) void VKGSRender::close_and_submit_command_buffer(vk::fence* pFence, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkPipelineStageFlags pipeline_stage_flags)
{ {
// Wait before sync block below // NOTE: There is no need to wait for dma sync. When MTRSX is enabled, the commands are submitted in order anyway due to CSMT
rsx::g_dma_manager.sync();
if (vk::test_status_interrupt(vk::heap_dirty)) if (vk::test_status_interrupt(vk::heap_dirty))
{ {
if (m_attrib_ring_info.dirty() || if (m_attrib_ring_info.dirty() ||
@ -2881,7 +2884,7 @@ void VKGSRender::close_and_submit_command_buffer(VkFence fence, VkSemaphore wait
m_current_command_buffer->tag(); m_current_command_buffer->tag();
m_current_command_buffer->submit(m_swapchain->get_graphics_queue(), m_current_command_buffer->submit(m_swapchain->get_graphics_queue(),
wait_semaphore, signal_semaphore, fence, pipeline_stage_flags); wait_semaphore, signal_semaphore, pFence, pipeline_stage_flags);
} }
void VKGSRender::open_command_buffer() void VKGSRender::open_command_buffer()
@ -3155,16 +3158,11 @@ void VKGSRender::reinitialize_swapchain()
} }
//Will have to block until rendering is completed //Will have to block until rendering is completed
VkFence resize_fence = VK_NULL_HANDLE; vk::fence resize_fence(*m_device);
VkFenceCreateInfo infos = {};
infos.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
vkCreateFence((*m_device), &infos, nullptr, &resize_fence);
//Flush the command buffer //Flush the command buffer
close_and_submit_command_buffer(resize_fence); close_and_submit_command_buffer(&resize_fence);
vk::wait_for_fence(resize_fence); vk::wait_for_fence(&resize_fence);
vkDestroyFence((*m_device), resize_fence, nullptr);
m_current_command_buffer->reset(); m_current_command_buffer->reset();
open_command_buffer(); open_command_buffer();
@ -3581,6 +3579,22 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
rsx::thread::flip(info); rsx::thread::flip(info);
} }
void VKGSRender::renderctl(u32 request_code, void* args)
{
switch (request_code)
{
case vk::rctrl_queue_submit:
{
auto packet = reinterpret_cast<vk::submit_packet*>(args);
vk::queue_submit(packet->queue, &packet->submit_info, packet->pfence, VK_TRUE);
free(packet);
break;
}
default:
fmt::throw_exception("Unhandled request code 0x%x" HERE, request_code);
}
}
bool VKGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate) bool VKGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate)
{ {
if (swapchain_unavailable) if (swapchain_unavailable)
@ -3675,6 +3689,8 @@ void VKGSRender::get_occlusion_query_result(rsx::reports::occlusion_query_info*
busy_wait(); busy_wait();
} }
data.command_buffer_to_wait->wait();
// Gather data // Gather data
for (const auto occlusion_id : data.indices) for (const auto occlusion_id : data.indices)
{ {

View file

@ -67,7 +67,7 @@ enum
struct command_buffer_chunk: public vk::command_buffer struct command_buffer_chunk: public vk::command_buffer
{ {
VkFence submit_fence = VK_NULL_HANDLE; vk::fence* submit_fence = nullptr;
VkDevice m_device = VK_NULL_HANDLE; VkDevice m_device = VK_NULL_HANDLE;
std::atomic_bool pending = { false }; std::atomic_bool pending = { false };
@ -79,18 +79,13 @@ struct command_buffer_chunk: public vk::command_buffer
void init_fence(VkDevice dev) void init_fence(VkDevice dev)
{ {
m_device = dev; m_device = dev;
submit_fence = new vk::fence(dev);
VkFenceCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
CHECK_RESULT(vkCreateFence(m_device, &info, nullptr, &submit_fence));
} }
void destroy() void destroy()
{ {
vk::command_buffer::destroy(); vk::command_buffer::destroy();
delete submit_fence;
if (submit_fence != VK_NULL_HANDLE)
vkDestroyFence(m_device, submit_fence, nullptr);
} }
void tag() void tag()
@ -116,13 +111,16 @@ struct command_buffer_chunk: public vk::command_buffer
if (!pending) if (!pending)
return true; return true;
if (vkGetFenceStatus(m_device, submit_fence) == VK_SUCCESS) if (!submit_fence->flushed)
return false;
if (vkGetFenceStatus(m_device, submit_fence->handle) == VK_SUCCESS)
{ {
lock.upgrade(); lock.upgrade();
if (pending) if (pending)
{ {
vk::reset_fence(&submit_fence); vk::reset_fence(submit_fence);
vk::on_event_completed(eid_tag); vk::on_event_completed(eid_tag);
pending = false; pending = false;
@ -146,7 +144,7 @@ struct command_buffer_chunk: public vk::command_buffer
if (pending) if (pending)
{ {
vk::reset_fence(&submit_fence); vk::reset_fence(submit_fence);
vk::on_event_completed(eid_tag); vk::on_event_completed(eid_tag);
pending = false; pending = false;
@ -155,6 +153,11 @@ struct command_buffer_chunk: public vk::command_buffer
return ret; return ret;
} }
void flush() const
{
submit_fence->wait_flush();
}
}; };
struct occlusion_data struct occlusion_data
@ -430,7 +433,7 @@ private:
void open_command_buffer(); void open_command_buffer();
void close_and_submit_command_buffer( void close_and_submit_command_buffer(
VkFence fence = VK_NULL_HANDLE, vk::fence* fence = nullptr,
VkSemaphore wait_semaphore = VK_NULL_HANDLE, VkSemaphore wait_semaphore = VK_NULL_HANDLE,
VkSemaphore signal_semaphore = VK_NULL_HANDLE, VkSemaphore signal_semaphore = VK_NULL_HANDLE,
VkPipelineStageFlags pipeline_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT); VkPipelineStageFlags pipeline_stage_flags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
@ -486,6 +489,8 @@ protected:
void on_exit() override; void on_exit() override;
void flip(const rsx::display_flip_info_t& info) override; void flip(const rsx::display_flip_info_t& info) override;
void renderctl(u32 request_code, void* args) override;
void do_local_task(rsx::FIFO_state state) override; void do_local_task(rsx::FIFO_state state) override;
bool scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate) override; bool scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate) override;
void notify_tile_unbound(u32 tile) override; void notify_tile_unbound(u32 tile) override;

View file

@ -7,7 +7,10 @@
#include "VKResolveHelper.h" #include "VKResolveHelper.h"
#include "VKResourceManager.h" #include "VKResourceManager.h"
#include "VKDMA.h" #include "VKDMA.h"
#include "VKCommandStream.h"
#include "Utilities/mutex.h" #include "Utilities/mutex.h"
#include "Utilities/lockless.h"
namespace vk namespace vk
{ {
@ -91,9 +94,6 @@ namespace vk
u64 g_num_processed_frames = 0; u64 g_num_processed_frames = 0;
u64 g_num_total_frames = 0; u64 g_num_total_frames = 0;
// global submit guard to prevent race condition on queue submit
shared_mutex g_submit_mutex;
VKAPI_ATTR void* VKAPI_CALL mem_realloc(void* pUserData, void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope) VKAPI_ATTR void* VKAPI_CALL mem_realloc(void* pUserData, void* pOriginal, size_t size, size_t alignment, VkSystemAllocationScope allocationScope)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
@ -349,16 +349,6 @@ namespace vk
return &g_upload_heap; return &g_upload_heap;
} }
void acquire_global_submit_lock()
{
g_submit_mutex.lock();
}
void release_global_submit_lock()
{
g_submit_mutex.unlock();
}
void reset_compute_tasks() void reset_compute_tasks()
{ {
for (const auto &p : g_compute_tasks) for (const auto &p : g_compute_tasks)
@ -836,31 +826,30 @@ namespace vk
return (g_num_processed_frames > 0)? g_num_processed_frames - 1: 0; return (g_num_processed_frames > 0)? g_num_processed_frames - 1: 0;
} }
void reset_fence(VkFence *pFence) void reset_fence(fence *pFence)
{ {
if (g_drv_disable_fence_reset) if (g_drv_disable_fence_reset)
{ {
vkDestroyFence(*g_current_renderer, *pFence, nullptr); delete pFence;
pFence = new fence(*g_current_renderer);
VkFenceCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
CHECK_RESULT(vkCreateFence(*g_current_renderer, &info, nullptr, pFence));
} }
else else
{ {
CHECK_RESULT(vkResetFences(*g_current_renderer, 1, pFence)); pFence->reset();
} }
} }
VkResult wait_for_fence(VkFence fence, u64 timeout) VkResult wait_for_fence(fence* pFence, u64 timeout)
{ {
pFence->wait_flush();
if (timeout) if (timeout)
{ {
return vkWaitForFences(*g_current_renderer, 1, &fence, VK_FALSE, timeout * 1000ull); return vkWaitForFences(*g_current_renderer, 1, &pFence->handle, VK_FALSE, timeout * 1000ull);
} }
else else
{ {
while (auto status = vkGetFenceStatus(*g_current_renderer, fence)) while (auto status = vkGetFenceStatus(*g_current_renderer, pFence->handle))
{ {
switch (status) switch (status)
{ {

View file

@ -107,6 +107,11 @@ namespace vk
VK_REMAP_VIEW_MULTISAMPLED = 0xDEADBEEF // Special encoding for multisampled images; returns a multisampled image view VK_REMAP_VIEW_MULTISAMPLED = 0xDEADBEEF // Special encoding for multisampled images; returns a multisampled image view
}; };
enum // callback commands
{
rctrl_queue_submit = 0x80000000
};
class context; class context;
class render_device; class render_device;
class swap_chain_image; class swap_chain_image;
@ -119,6 +124,7 @@ namespace vk
class mem_allocator_base; class mem_allocator_base;
struct memory_type_mapping; struct memory_type_mapping;
struct gpu_formats_support; struct gpu_formats_support;
struct fence;
const vk::context *get_current_thread_ctx(); const vk::context *get_current_thread_ctx();
void set_current_thread_ctx(const vk::context &ctx); void set_current_thread_ctx(const vk::context &ctx);
@ -152,9 +158,10 @@ namespace vk
memory_type_mapping get_memory_mapping(const physical_device& dev); memory_type_mapping get_memory_mapping(const physical_device& dev);
gpu_formats_support get_optimal_tiling_supported_formats(const physical_device& dev); gpu_formats_support get_optimal_tiling_supported_formats(const physical_device& dev);
//Sync helpers around vkQueueSubmit // Sync helpers around vkQueueSubmit
void acquire_global_submit_lock(); void acquire_global_submit_lock();
void release_global_submit_lock(); void release_global_submit_lock();
void queue_submit(VkQueue queue, const VkSubmitInfo* info, fence* pfence, VkBool32 flush = VK_FALSE);
template<class T> template<class T>
T* get_compute_task(); T* get_compute_task();
@ -222,8 +229,8 @@ namespace vk
const u64 get_last_completed_frame_id(); const u64 get_last_completed_frame_id();
// Fence reset with driver workarounds in place // Fence reset with driver workarounds in place
void reset_fence(VkFence *pFence); void reset_fence(fence* pFence);
VkResult wait_for_fence(VkFence pFence, u64 timeout = 0ull); VkResult wait_for_fence(fence* pFence, u64 timeout = 0ull);
VkResult wait_for_event(VkEvent pEvent, u64 timeout = 0ull); VkResult wait_for_event(VkEvent pEvent, u64 timeout = 0ull);
// Handle unexpected submit with dangling occlusion query // Handle unexpected submit with dangling occlusion query
@ -1022,12 +1029,55 @@ private:
} }
}; };
struct fence
{
volatile bool flushed = false;
VkFence handle = VK_NULL_HANDLE;
VkDevice owner = VK_NULL_HANDLE;
fence(VkDevice dev)
{
owner = dev;
VkFenceCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
CHECK_RESULT(vkCreateFence(dev, &info, nullptr, &handle));
}
~fence()
{
if (handle)
{
vkDestroyFence(owner, handle, nullptr);
handle = VK_NULL_HANDLE;
}
}
void reset()
{
vkResetFences(owner, 1, &handle);
flushed = false;
}
void wait_flush()
{
while (!flushed)
{
_mm_pause();
}
}
operator bool() const
{
return (handle != VK_NULL_HANDLE);
}
};
class command_buffer class command_buffer
{ {
private: private:
bool is_open = false; bool is_open = false;
bool is_pending = false; bool is_pending = false;
VkFence m_submit_fence = VK_NULL_HANDLE; fence* m_submit_fence = nullptr;
protected: protected:
vk::command_pool *pool = nullptr; vk::command_pool *pool = nullptr;
@ -1066,9 +1116,7 @@ private:
if (auto_reset) if (auto_reset)
{ {
VkFenceCreateInfo info = {}; m_submit_fence = new fence(cmd_pool.get_owner());
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
CHECK_RESULT(vkCreateFence(cmd_pool.get_owner(), &info, nullptr, &m_submit_fence));
} }
pool = &cmd_pool; pool = &cmd_pool;
@ -1080,7 +1128,9 @@ private:
if (m_submit_fence) if (m_submit_fence)
{ {
vkDestroyFence(pool->get_owner(), m_submit_fence, nullptr); //vkDestroyFence(pool->get_owner(), m_submit_fence, nullptr);
delete m_submit_fence;
m_submit_fence = nullptr;
} }
} }
@ -1116,7 +1166,8 @@ private:
wait_for_fence(m_submit_fence); wait_for_fence(m_submit_fence);
is_pending = false; is_pending = false;
CHECK_RESULT(vkResetFences(pool->get_owner(), 1, &m_submit_fence)); //CHECK_RESULT(vkResetFences(pool->get_owner(), 1, &m_submit_fence));
reset_fence(m_submit_fence);
CHECK_RESULT(vkResetCommandBuffer(commands, 0)); CHECK_RESULT(vkResetCommandBuffer(commands, 0));
} }
@ -1146,7 +1197,7 @@ private:
is_open = false; is_open = false;
} }
void submit(VkQueue queue, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, VkFence fence, VkPipelineStageFlags pipeline_stage_flags) void submit(VkQueue queue, VkSemaphore wait_semaphore, VkSemaphore signal_semaphore, fence* pfence, VkPipelineStageFlags pipeline_stage_flags)
{ {
if (is_open) if (is_open)
{ {
@ -1157,10 +1208,10 @@ private:
// Check for hanging queries to avoid driver hang // Check for hanging queries to avoid driver hang
verify("close and submit of commandbuffer with a hanging query!" HERE), (flags & cb_has_open_query) == 0; verify("close and submit of commandbuffer with a hanging query!" HERE), (flags & cb_has_open_query) == 0;
if (!fence) if (!pfence)
{ {
fence = m_submit_fence; pfence = m_submit_fence;
is_pending = (fence != VK_NULL_HANDLE); is_pending = bool(pfence);
} }
VkSubmitInfo infos = {}; VkSubmitInfo infos = {};
@ -1181,10 +1232,7 @@ private:
infos.pSignalSemaphores = &signal_semaphore; infos.pSignalSemaphores = &signal_semaphore;
} }
acquire_global_submit_lock(); queue_submit(queue, &infos, pfence);
CHECK_RESULT(vkQueueSubmit(queue, 1, &infos, fence));
release_global_submit_lock();
clear_flags(); clear_flags();
} }
}; };

View file

@ -1336,15 +1336,10 @@ namespace vk
if (cmd.access_hint != vk::command_buffer::access_type_hint::all) if (cmd.access_hint != vk::command_buffer::access_type_hint::all)
{ {
// Primary access command queue, must restart it after // Primary access command queue, must restart it after
VkFence submit_fence; vk::fence submit_fence(*m_device);
VkFenceCreateInfo info{}; cmd.submit(m_submit_queue, VK_NULL_HANDLE, VK_NULL_HANDLE, &submit_fence, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
vkCreateFence(*m_device, &info, nullptr, &submit_fence);
cmd.submit(m_submit_queue, VK_NULL_HANDLE, VK_NULL_HANDLE, submit_fence, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); vk::wait_for_fence(&submit_fence, GENERAL_WAIT_TIMEOUT);
vk::wait_for_fence(submit_fence, GENERAL_WAIT_TIMEOUT);
vkDestroyFence(*m_device, submit_fence, nullptr);
CHECK_RESULT(vkResetCommandBuffer(cmd, 0)); CHECK_RESULT(vkResetCommandBuffer(cmd, 0));
cmd.begin(); cmd.begin();

View file

@ -23,6 +23,7 @@
</ProjectConfiguration> </ProjectConfiguration>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Emu\RSX\VK\VKCommandStream.h" />
<ClInclude Include="Emu\RSX\VK\VKCommonDecompiler.h" /> <ClInclude Include="Emu\RSX\VK\VKCommonDecompiler.h" />
<ClInclude Include="Emu\RSX\VK\VKCompute.h" /> <ClInclude Include="Emu\RSX\VK\VKCompute.h" />
<ClInclude Include="Emu\RSX\VK\VKDMA.h" /> <ClInclude Include="Emu\RSX\VK\VKDMA.h" />
@ -43,6 +44,7 @@
<ClInclude Include="Emu\RSX\VK\VulkanAPI.h" /> <ClInclude Include="Emu\RSX\VK\VulkanAPI.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Emu\RSX\VK\VKCommandStream.cpp" />
<ClCompile Include="Emu\RSX\VK\VKCommonDecompiler.cpp" /> <ClCompile Include="Emu\RSX\VK\VKCommonDecompiler.cpp" />
<ClCompile Include="Emu\RSX\VK\VKDMA.cpp" /> <ClCompile Include="Emu\RSX\VK\VKDMA.cpp" />
<ClCompile Include="Emu\RSX\VK\VKFormats.cpp" /> <ClCompile Include="Emu\RSX\VK\VKFormats.cpp" />

View file

@ -1,112 +1,42 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<Filter Include="Source Files"> <ClCompile Include="Emu\RSX\VK\VKCommonDecompiler.cpp" />
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> <ClCompile Include="Emu\RSX\VK\VKDMA.cpp" />
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> <ClCompile Include="Emu\RSX\VK\VKFormats.cpp" />
</Filter> <ClCompile Include="Emu\RSX\VK\VKFragmentProgram.cpp" />
<ClCompile Include="Emu\RSX\VK\VKFramebuffer.cpp" />
<ClCompile Include="Emu\RSX\VK\VKGSRender.cpp" />
<ClCompile Include="Emu\RSX\VK\VKHelpers.cpp" />
<ClCompile Include="Emu\RSX\VK\VKProgramPipeline.cpp" />
<ClCompile Include="Emu\RSX\VK\VKRenderPass.cpp" />
<ClCompile Include="Emu\RSX\VK\VKResolveHelper.cpp" />
<ClCompile Include="Emu\RSX\VK\VKResourceManager.cpp" />
<ClCompile Include="Emu\RSX\VK\VKTexture.cpp" />
<ClCompile Include="Emu\RSX\VK\VKVertexBuffers.cpp" />
<ClCompile Include="Emu\RSX\VK\VKVertexProgram.cpp" />
<ClCompile Include="Emu\RSX\VK\VKMemAlloc.cpp" />
<ClCompile Include="Emu\RSX\VK\VKCommandStream.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Emu\RSX\VK\VKGSRender.h"> <ClInclude Include="Emu\RSX\VK\VKCommonDecompiler.h" />
<Filter>Source Files</Filter> <ClInclude Include="Emu\RSX\VK\VKCompute.h" />
</ClInclude> <ClInclude Include="Emu\RSX\VK\VKDMA.h" />
<ClInclude Include="Emu\RSX\VK\VKCommonDecompiler.h"> <ClInclude Include="Emu\RSX\VK\VKFormats.h" />
<Filter>Source Files</Filter> <ClInclude Include="Emu\RSX\VK\VKFragmentProgram.h" />
</ClInclude> <ClInclude Include="Emu\RSX\VK\VKFramebuffer.h" />
<ClInclude Include="Emu\RSX\VK\VKFragmentProgram.h"> <ClInclude Include="Emu\RSX\VK\VKGSRender.h" />
<Filter>Source Files</Filter> <ClInclude Include="Emu\RSX\VK\VKHelpers.h" />
</ClInclude> <ClInclude Include="Emu\RSX\VK\VKOverlays.h" />
<ClInclude Include="Emu\RSX\VK\VKHelpers.h"> <ClInclude Include="Emu\RSX\VK\VKProgramBuffer.h" />
<Filter>Source Files</Filter> <ClInclude Include="Emu\RSX\VK\VKRenderPass.h" />
</ClInclude> <ClInclude Include="Emu\RSX\VK\VKRenderTargets.h" />
<ClInclude Include="Emu\RSX\VK\VKProgramBuffer.h"> <ClInclude Include="Emu\RSX\VK\VKResolveHelper.h" />
<Filter>Source Files</Filter> <ClInclude Include="Emu\RSX\VK\VKResourceManager.h" />
</ClInclude> <ClInclude Include="Emu\RSX\VK\VKTextOut.h" />
<ClInclude Include="Emu\RSX\VK\VKRenderTargets.h"> <ClInclude Include="Emu\RSX\VK\VKTextureCache.h" />
<Filter>Source Files</Filter> <ClInclude Include="Emu\RSX\VK\VKVertexProgram.h" />
</ClInclude> <ClInclude Include="Emu\RSX\VK\VulkanAPI.h" />
<ClInclude Include="Emu\RSX\VK\VKTextureCache.h"> <ClInclude Include="Emu\RSX\VK\VKCommandStream.h" />
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKVertexProgram.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VulkanAPI.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKFormats.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKTextOut.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKOverlays.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKCompute.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKRenderPass.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKResolveHelper.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKResourceManager.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKFramebuffer.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\VK\VKDMA.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Emu\RSX\VK\VKGSRender.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKCommonDecompiler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKFragmentProgram.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKHelpers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKProgramPipeline.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKTexture.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKVertexProgram.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKVertexBuffers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKFormats.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKMemAlloc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKRenderPass.cpp">
<Filter>Source Files</Filter>
</ClInclude>
<ClCompile Include="Emu\RSX\VK\VKResolveHelper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKResourceManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKFramebuffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\VK\VKDMA.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>