Fix: Vulkan: Threading issue when waiting for submission

Usage of conditional to fix threading and performance delays when
waiting for the submission fence to become valid. The previous
(faulty) implementation didn't work well on WoA devices.
This commit is contained in:
Oscar Blumberg
2025-05-23 14:57:52 +02:00
committed by Jeroen Bakker
parent 98b888c163
commit aa413a05bf

View File

@@ -7,8 +7,11 @@
*/
#include <chrono>
#include <condition_variable>
#include <thread>
#include "BLI_mutex.hh"
#include "vk_device.hh"
namespace blender::gpu {
@@ -17,6 +20,12 @@ namespace blender::gpu {
/** \name Render graph
* \{ */
struct VKRenderGraphWait {
blender::Mutex is_submitted_mutex;
std::condition_variable_any is_submitted_condition;
bool is_submitted;
};
struct VKRenderGraphSubmitTask {
render_graph::VKRenderGraph *render_graph;
uint64_t timeline;
@@ -25,7 +34,7 @@ struct VKRenderGraphSubmitTask {
VkSemaphore wait_semaphore;
VkSemaphore signal_semaphore;
VkFence signal_fence;
bool *is_submitted_ptr;
VKRenderGraphWait *wait_for_submission;
};
TimelineValue VKDevice::render_graph_submit(render_graph::VKRenderGraph *render_graph,
@@ -50,13 +59,14 @@ TimelineValue VKDevice::render_graph_submit(render_graph::VKRenderGraph *render_
submit_task->wait_semaphore = wait_semaphore;
submit_task->signal_semaphore = signal_semaphore;
submit_task->signal_fence = signal_fence;
submit_task->is_submitted_ptr = nullptr;
submit_task->wait_for_submission = nullptr;
/* We need to wait for submission as otherwise the signal semaphore can still not be in an
* initial state. */
const bool wait_for_submission = signal_semaphore != VK_NULL_HANDLE && !wait_for_completion;
bool is_submitted = false;
VKRenderGraphWait wait_condition{};
if (wait_for_submission) {
submit_task->is_submitted_ptr = &is_submitted;
submit_task->wait_for_submission = &wait_condition;
}
TimelineValue timeline = submit_task->timeline = submit_to_device ? ++timeline_value_ :
timeline_value_ + 1;
@@ -67,10 +77,8 @@ TimelineValue VKDevice::render_graph_submit(render_graph::VKRenderGraph *render_
submit_task = nullptr;
if (wait_for_submission) {
while (!is_submitted) {
using namespace std::chrono_literals;
std::this_thread::sleep_for(1ns);
}
std::unique_lock<blender::Mutex> lock(wait_condition.is_submitted_mutex);
wait_condition.is_submitted_condition.wait(lock, [&] { return wait_condition.is_submitted; });
}
if (wait_for_completion) {
@@ -232,8 +240,11 @@ void VKDevice::submission_runner(TaskPool *__restrict pool, void *task_data)
submit_infos.data(),
submit_task->signal_fence);
}
if (submit_task->is_submitted_ptr != nullptr) {
*submit_task->is_submitted_ptr = true;
if (submit_task->wait_for_submission != nullptr) {
std::unique_lock<blender::Mutex> lock(
submit_task->wait_for_submission->is_submitted_mutex);
submit_task->wait_for_submission->is_submitted = true;
submit_task->wait_for_submission->is_submitted_condition.notify_one();
}
vk_command_buffer = VK_NULL_HANDLE;
for (VkCommandBuffer vk_command_buffer : unsubmitted_command_buffers) {