diff options
| author | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2026-04-05 22:41:00 +1000 |
|---|---|---|
| committer | Nicolas James <Eele1Ephe7uZahRie@tutanota.com> | 2026-04-05 22:41:00 +1000 |
| commit | 53e52348b76b7b12b0f2356bc2112e5bf1a1be4f (patch) | |
| tree | 9e604498350d7e56e5ed1339f4d1dd647e8abf5e /src | |
| parent | cf0bced6cd86782e9706acda1b3b6ce6b4e98481 (diff) | |
Fix race in VkQueueSubmit and VkQueueSubmit2
Diffstat (limited to 'src')
| -rw-r--r-- | src/layer.cc | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/src/layer.cc b/src/layer.cc index 627fee2..1a91dd0 100644 --- a/src/layer.cc +++ b/src/layer.cc @@ -390,31 +390,24 @@ vkQueueSubmit(VkQueue queue, std::uint32_t submit_count, // pointers to our command buffer arrays - of which the position in memory // of can change on vector reallocation. So we use unique_ptrs here. auto next_cbs = std::vector<std::unique_ptr<cbs_t>>{}; + auto submissions = std::vector<std::unique_ptr<Submission>>{}; - // notify_submit() should take copies of these shared_ptrs and store - // them for the duration of our call, but saving them here is a bit - // more explicit + insurance if that changes. - auto handles = std::vector<std::shared_ptr<TimestampPool::Handle>>{}; - - [[maybe_unused]] const auto now = DeviceClock::now(); + const auto now = DeviceClock::now(); + const auto submit_span = std::span{submit_infos, submit_count}; std::ranges::transform( - std::span{submit_infos, submit_count}, std::back_inserter(next_submits), - [&](const auto& submit) { + submit_span, std::back_inserter(next_submits), [&](const auto& submit) { const auto head_handle = context->timestamp_pool->acquire(); head_handle->write_command(VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT); const auto tail_handle = context->timestamp_pool->acquire(); tail_handle->write_command(VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); - context->strategy->notify_submit( - submit, std::make_unique<Submission>(Submission{ - .start = head_handle, - .end = tail_handle, - .time = now, - })); + submissions.push_back(std::make_unique<Submission>(Submission{ + .start = head_handle, + .end = tail_handle, + .time = now, + })); - handles.emplace_back(head_handle); - handles.emplace_back(tail_handle); next_cbs.emplace_back([&]() -> auto { auto cbs = std::make_unique<cbs_t>(); cbs->push_back(head_handle->command_buffer); @@ -432,9 +425,19 @@ vkQueueSubmit(VkQueue queue, std::uint32_t submit_count, return next_submit; }); - return vtable.QueueSubmit( + const auto result = vtable.QueueSubmit( queue, static_cast<std::uint32_t>(std::size(next_submits)), std::data(next_submits), fence); + + // We have to notify after we submit - otherwise we have a race where we + // wait for work that wasn't submitted. + for (auto&& [submit, submission] : + std::views::zip(submit_span, submissions)) { + + context->strategy->notify_submit(submit, std::move(submission)); + } + + return result; } // The logic for this function is identical to vkSubmitInfo. @@ -452,27 +455,24 @@ vkQueueSubmit2(VkQueue queue, std::uint32_t submit_count, using cbs_t = std::vector<VkCommandBufferSubmitInfo>; auto next_submits = std::vector<VkSubmitInfo2>{}; auto next_cbs = std::vector<std::unique_ptr<cbs_t>>{}; - auto handles = std::vector<std::shared_ptr<TimestampPool::Handle>>{}; + auto submissions = std::vector<std::unique_ptr<Submission>>{}; const auto now = DeviceClock::now(); + const auto submit_span = std::span{submit_infos, submit_count}; std::ranges::transform( - std::span{submit_infos, submit_count}, std::back_inserter(next_submits), - [&](const auto& submit) { + submit_span, std::back_inserter(next_submits), [&](const auto& submit) { const auto head_handle = context->timestamp_pool->acquire(); head_handle->write_command(VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT); const auto tail_handle = context->timestamp_pool->acquire(); tail_handle->write_command(VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT); - context->strategy->notify_submit( - submit, std::make_unique<Submission>(Submission{ - .start = head_handle, - .end = tail_handle, - .time = now, - })); + submissions.push_back(std::make_unique<Submission>(Submission{ + .start = head_handle, + .end = tail_handle, + .time = now, + })); - handles.emplace_back(head_handle); - handles.emplace_back(tail_handle); next_cbs.emplace_back([&]() -> auto { auto cbs = std::make_unique<cbs_t>(); cbs->push_back(VkCommandBufferSubmitInfo{ @@ -496,9 +496,17 @@ vkQueueSubmit2(VkQueue queue, std::uint32_t submit_count, return next_submit; }); - return vtable.QueueSubmit2( + const auto result = vtable.QueueSubmit2( queue, static_cast<std::uint32_t>(std::size(next_submits)), std::data(next_submits), fence); + + for (auto&& [submit, submission] : + std::views::zip(submit_span, submissions)) { + + context->strategy->notify_submit(submit, std::move(submission)); + } + + return result; } static VKAPI_ATTR VkResult VKAPI_CALL |
