mirror of https://github.com/PCSX2/pcsx2.git
GS/Vulkan: Fix potential race between submit and main thread
Backport of bcf7f55b93
This commit is contained in:
parent
63872e6b28
commit
9809265be4
|
@ -1058,6 +1058,13 @@ void GSDeviceVK::ScanForCommandBufferCompletion()
|
||||||
|
|
||||||
void GSDeviceVK::WaitForCommandBufferCompletion(u32 index)
|
void GSDeviceVK::WaitForCommandBufferCompletion(u32 index)
|
||||||
{
|
{
|
||||||
|
// We might be waiting for the buffer we just submitted to the worker thread.
|
||||||
|
if (m_queued_present.command_buffer_index == index && !m_present_done.load(std::memory_order_acquire))
|
||||||
|
{
|
||||||
|
Console.WarningFmt("Waiting for threaded submission of cmdbuffer {}", index);
|
||||||
|
WaitForPresentComplete();
|
||||||
|
}
|
||||||
|
|
||||||
// Wait for this command buffer to be completed.
|
// Wait for this command buffer to be completed.
|
||||||
const VkResult res = vkWaitForFences(m_device, 1, &m_frame_resources[index].fence, VK_TRUE, UINT64_MAX);
|
const VkResult res = vkWaitForFences(m_device, 1, &m_frame_resources[index].fence, VK_TRUE, UINT64_MAX);
|
||||||
if (res != VK_SUCCESS)
|
if (res != VK_SUCCESS)
|
||||||
|
@ -1174,7 +1181,7 @@ void GSDeviceVK::SubmitCommandBuffer(
|
||||||
m_queued_present.command_buffer_index = m_current_frame;
|
m_queued_present.command_buffer_index = m_current_frame;
|
||||||
m_queued_present.swap_chain = present_swap_chain;
|
m_queued_present.swap_chain = present_swap_chain;
|
||||||
m_queued_present.spin_cycles = spin_cycles;
|
m_queued_present.spin_cycles = spin_cycles;
|
||||||
m_present_done.store(false);
|
m_present_done.store(false, std::memory_order_release);
|
||||||
m_present_queued_cv.notify_one();
|
m_present_queued_cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1253,7 +1260,7 @@ void GSDeviceVK::DoPresent(VKSwapChain* present_swap_chain)
|
||||||
|
|
||||||
void GSDeviceVK::WaitForPresentComplete()
|
void GSDeviceVK::WaitForPresentComplete()
|
||||||
{
|
{
|
||||||
if (m_present_done.load())
|
if (m_present_done.load(std::memory_order_acquire))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(m_present_mutex);
|
std::unique_lock<std::mutex> lock(m_present_mutex);
|
||||||
|
@ -1262,27 +1269,30 @@ void GSDeviceVK::WaitForPresentComplete()
|
||||||
|
|
||||||
void GSDeviceVK::WaitForPresentComplete(std::unique_lock<std::mutex>& lock)
|
void GSDeviceVK::WaitForPresentComplete(std::unique_lock<std::mutex>& lock)
|
||||||
{
|
{
|
||||||
if (m_present_done.load())
|
if (m_present_done.load(std::memory_order_acquire))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_present_done_cv.wait(lock, [this]() { return m_present_done.load(); });
|
m_present_done_cv.wait(lock, [this]() { return m_present_done.load(std::memory_order_acquire); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDeviceVK::PresentThread()
|
void GSDeviceVK::PresentThread()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_present_mutex);
|
std::unique_lock<std::mutex> lock(m_present_mutex);
|
||||||
while (!m_present_thread_done.load())
|
while (!m_present_thread_done.load(std::memory_order_acquire))
|
||||||
{
|
{
|
||||||
m_present_queued_cv.wait(lock, [this]() { return !m_present_done.load() || m_present_thread_done.load(); });
|
m_present_queued_cv.wait(lock, [this]() {
|
||||||
|
return !m_present_done.load(std::memory_order_acquire) ||
|
||||||
|
m_present_thread_done.load(std::memory_order_acquire);
|
||||||
|
});
|
||||||
|
|
||||||
if (m_present_done.load())
|
if (m_present_done.load(std::memory_order_acquire))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
DoSubmitCommandBuffer(
|
DoSubmitCommandBuffer(
|
||||||
m_queued_present.command_buffer_index, m_queued_present.swap_chain, m_queued_present.spin_cycles);
|
m_queued_present.command_buffer_index, m_queued_present.swap_chain, m_queued_present.spin_cycles);
|
||||||
if (m_queued_present.swap_chain)
|
if (m_queued_present.swap_chain)
|
||||||
DoPresent(m_queued_present.swap_chain);
|
DoPresent(m_queued_present.swap_chain);
|
||||||
m_present_done.store(true);
|
m_present_done.store(true, std::memory_order_release);
|
||||||
m_present_done_cv.notify_one();
|
m_present_done_cv.notify_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1290,7 +1300,7 @@ void GSDeviceVK::PresentThread()
|
||||||
void GSDeviceVK::StartPresentThread()
|
void GSDeviceVK::StartPresentThread()
|
||||||
{
|
{
|
||||||
pxAssert(!m_present_thread.joinable());
|
pxAssert(!m_present_thread.joinable());
|
||||||
m_present_thread_done.store(false);
|
m_present_thread_done.store(false, std::memory_order_release);
|
||||||
m_present_thread = std::thread(&GSDeviceVK::PresentThread, this);
|
m_present_thread = std::thread(&GSDeviceVK::PresentThread, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1302,7 +1312,7 @@ void GSDeviceVK::StopPresentThread()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(m_present_mutex);
|
std::unique_lock<std::mutex> lock(m_present_mutex);
|
||||||
WaitForPresentComplete(lock);
|
WaitForPresentComplete(lock);
|
||||||
m_present_thread_done.store(true);
|
m_present_thread_done.store(true, std::memory_order_acquire);
|
||||||
m_present_queued_cv.notify_one();
|
m_present_queued_cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1367,9 +1377,6 @@ void GSDeviceVK::ActivateCommandBuffer(u32 index)
|
||||||
{
|
{
|
||||||
FrameResources& resources = m_frame_resources[index];
|
FrameResources& resources = m_frame_resources[index];
|
||||||
|
|
||||||
if (!m_present_done.load() && m_queued_present.command_buffer_index == index)
|
|
||||||
WaitForPresentComplete();
|
|
||||||
|
|
||||||
// Wait for the GPU to finish with all resources for this command buffer.
|
// Wait for the GPU to finish with all resources for this command buffer.
|
||||||
if (resources.fence_counter > m_completed_fence_counter)
|
if (resources.fence_counter > m_completed_fence_counter)
|
||||||
WaitForCommandBufferCompletion(index);
|
WaitForCommandBufferCompletion(index);
|
||||||
|
|
|
@ -303,7 +303,7 @@ private:
|
||||||
u32 spin_cycles;
|
u32 spin_cycles;
|
||||||
};
|
};
|
||||||
|
|
||||||
QueuedPresent m_queued_present = {};
|
QueuedPresent m_queued_present = {nullptr, 0xFFFFFFFFu, 0};
|
||||||
|
|
||||||
std::map<u32, VkRenderPass> m_render_pass_cache;
|
std::map<u32, VkRenderPass> m_render_pass_cache;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue