Skip to content

Commit ceb2674

Browse files
author
Jonah Williams
authored
[Impeller] presentKHR from background worker. (flutter#43976)
Testing with validation enabled shows no crashes or validation warnings on Pixel 6 or S10. I believe this is safe since we are correctly synchronized in the acquireNextImage via the presentation semaphore. The only loss is that we will finish the raster task before we know that presentation is failed. Having said that, we can end up waiting multiple ms for the layout transition and presentation, so that doesn't seem worth it.
1 parent 176457d commit ceb2674

File tree

1 file changed

+88
-79
lines changed

1 file changed

+88
-79
lines changed

impeller/renderer/backend/vulkan/swapchain_impl_vk.cc

Lines changed: 88 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -392,88 +392,97 @@ bool SwapchainImplVK::Present(const std::shared_ptr<SwapchainImageVK>& image,
392392
}
393393

394394
const auto& context = ContextVK::Cast(*context_strong);
395+
context.GetConcurrentWorkerTaskRunner()->PostTask(
396+
[&, index, image, current_frame = current_frame_] {
397+
auto context_strong = context_.lock();
398+
if (!context_strong) {
399+
return;
400+
}
401+
const auto& context = ContextVK::Cast(*context_strong);
402+
const auto& sync = synchronizers_[current_frame];
403+
404+
//----------------------------------------------------------------------------
405+
/// Transition the image to color-attachment-optimal.
406+
///
407+
sync->final_cmd_buffer = context.CreateCommandBuffer();
408+
if (!sync->final_cmd_buffer) {
409+
return;
410+
}
395411

396-
const auto& sync = synchronizers_[current_frame_];
397-
398-
//----------------------------------------------------------------------------
399-
/// Transition the image to color-attachment-optimal.
400-
///
401-
sync->final_cmd_buffer = context.CreateCommandBuffer();
402-
if (!sync->final_cmd_buffer) {
403-
return false;
404-
}
405-
406-
auto vk_final_cmd_buffer = CommandBufferVK::Cast(*sync->final_cmd_buffer)
407-
.GetEncoder()
408-
->GetCommandBuffer();
409-
{
410-
BarrierVK barrier;
411-
barrier.new_layout = vk::ImageLayout::ePresentSrcKHR;
412-
barrier.cmd_buffer = vk_final_cmd_buffer;
413-
barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite;
414-
barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
415-
barrier.dst_access = {};
416-
barrier.dst_stage = vk::PipelineStageFlagBits::eBottomOfPipe;
417-
418-
if (!image->SetLayout(barrier)) {
419-
return false;
420-
}
421-
422-
if (vk_final_cmd_buffer.end() != vk::Result::eSuccess) {
423-
return false;
424-
}
425-
}
412+
auto vk_final_cmd_buffer =
413+
CommandBufferVK::Cast(*sync->final_cmd_buffer)
414+
.GetEncoder()
415+
->GetCommandBuffer();
416+
{
417+
BarrierVK barrier;
418+
barrier.new_layout = vk::ImageLayout::ePresentSrcKHR;
419+
barrier.cmd_buffer = vk_final_cmd_buffer;
420+
barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite;
421+
barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput;
422+
barrier.dst_access = {};
423+
barrier.dst_stage = vk::PipelineStageFlagBits::eBottomOfPipe;
424+
425+
if (!image->SetLayout(barrier)) {
426+
return;
427+
}
428+
429+
if (vk_final_cmd_buffer.end() != vk::Result::eSuccess) {
430+
return;
431+
}
432+
}
426433

427-
//----------------------------------------------------------------------------
428-
/// Signal that the presentation semaphore is ready.
429-
///
430-
{
431-
vk::SubmitInfo submit_info;
432-
vk::PipelineStageFlags wait_stage =
433-
vk::PipelineStageFlagBits::eColorAttachmentOutput;
434-
submit_info.setWaitDstStageMask(wait_stage);
435-
submit_info.setWaitSemaphores(*sync->render_ready);
436-
submit_info.setSignalSemaphores(*sync->present_ready);
437-
submit_info.setCommandBuffers(vk_final_cmd_buffer);
438-
auto result =
439-
context.GetGraphicsQueue()->Submit(submit_info, *sync->acquire);
440-
if (result != vk::Result::eSuccess) {
441-
VALIDATION_LOG << "Could not wait on render semaphore: "
442-
<< vk::to_string(result);
443-
return false;
444-
}
445-
}
434+
//----------------------------------------------------------------------------
435+
/// Signal that the presentation semaphore is ready.
436+
///
437+
{
438+
vk::SubmitInfo submit_info;
439+
vk::PipelineStageFlags wait_stage =
440+
vk::PipelineStageFlagBits::eColorAttachmentOutput;
441+
submit_info.setWaitDstStageMask(wait_stage);
442+
submit_info.setWaitSemaphores(*sync->render_ready);
443+
submit_info.setSignalSemaphores(*sync->present_ready);
444+
submit_info.setCommandBuffers(vk_final_cmd_buffer);
445+
auto result =
446+
context.GetGraphicsQueue()->Submit(submit_info, *sync->acquire);
447+
if (result != vk::Result::eSuccess) {
448+
VALIDATION_LOG << "Could not wait on render semaphore: "
449+
<< vk::to_string(result);
450+
return;
451+
}
452+
}
446453

447-
//----------------------------------------------------------------------------
448-
/// Present the image.
449-
///
450-
uint32_t indices[] = {static_cast<uint32_t>(index)};
451-
452-
vk::PresentInfoKHR present_info;
453-
present_info.setSwapchains(*swapchain_);
454-
present_info.setImageIndices(indices);
455-
present_info.setWaitSemaphores(*sync->present_ready);
456-
457-
switch (auto result = present_queue_.presentKHR(present_info)) {
458-
case vk::Result::eErrorOutOfDateKHR:
459-
// Caller will recreate the impl on acquisition, not submission.
460-
[[fallthrough]];
461-
case vk::Result::eErrorSurfaceLostKHR:
462-
// Vulkan guarantees that the set of queue operations will still complete
463-
// successfully.
464-
[[fallthrough]];
465-
case vk::Result::eSuccess:
466-
is_rotated_ = false;
467-
return true;
468-
case vk::Result::eSuboptimalKHR:
469-
is_rotated_ = true;
470-
return true;
471-
default:
472-
VALIDATION_LOG << "Could not present queue: " << vk::to_string(result);
473-
return false;
474-
}
475-
FML_UNREACHABLE();
476-
return false;
454+
//----------------------------------------------------------------------------
455+
/// Present the image.
456+
///
457+
uint32_t indices[] = {static_cast<uint32_t>(index)};
458+
459+
vk::PresentInfoKHR present_info;
460+
present_info.setSwapchains(*swapchain_);
461+
present_info.setImageIndices(indices);
462+
present_info.setWaitSemaphores(*sync->present_ready);
463+
464+
switch (auto result = present_queue_.presentKHR(present_info)) {
465+
case vk::Result::eErrorOutOfDateKHR:
466+
// Caller will recreate the impl on acquisition, not submission.
467+
[[fallthrough]];
468+
case vk::Result::eErrorSurfaceLostKHR:
469+
// Vulkan guarantees that the set of queue operations will still
470+
// complete successfully.
471+
[[fallthrough]];
472+
case vk::Result::eSuccess:
473+
is_rotated_ = false;
474+
return;
475+
case vk::Result::eSuboptimalKHR:
476+
is_rotated_ = true;
477+
return;
478+
default:
479+
VALIDATION_LOG << "Could not present queue: "
480+
<< vk::to_string(result);
481+
return;
482+
}
483+
FML_UNREACHABLE();
484+
});
485+
return true;
477486
}
478487

479488
} // namespace impeller

0 commit comments

Comments
 (0)