【发布时间】:2021-10-09 21:00:06
【问题描述】:
我是 Vulkan API 中的 trying to synchronize frames,但我遇到了一些奇怪的问题。我实现了这样的同步:
void RenderSystem::OnUpdate(const float deltaTime)
{
uint32_t frameIndex{};
auto result = SwapChain->AcquireNextImageIndex(PresentationCompleteSemaphore.get(),
nullptr,
&frameIndex);
InFlightFences[frameIndex]->Wait();
InFlightFences[frameIndex]->Reset();
if (result == VK_ERROR_OUT_OF_DATE_KHR)
{
Recreate();
return;
}
else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
{
throw std::runtime_error("Error when acquiring next image...");
}
UpdateModelMatrix(deltaTime, frameIndex); // TODO: Remove this! For testing purposes only
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
GraphicsMainQueue.Submit({ TriangleCommandBuffers[frameIndex].get() },
{ PresentationCompleteSemaphore.get() },
{ RenderCompleteSemaphore.get() },
InFlightFences[frameIndex].get(),
waitStages);
result = PresentationQueue.Present({ RenderCompleteSemaphore.get() },
{ SwapChain.get() },
&frameIndex);
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || MainWindow->HasBeenResized())
Recreate();
else if (result != VK_SUCCESS)
throw std::runtime_error("Failed to present result!");
}
它可以在 Windows 10 上运行,就像一个魅力。不幸的是,在 Linux Mint 上,它在某些情况下不起作用。首先,在 Linux 上移动窗口非常滞后,有时会冻结整个操作系统一秒钟,但这不是最大的问题。关闭窗口调用vkDeviceWaitIdle 并且......它冻结了应用程序。它永远不会开始响应,因为它将永远等待设备。验证层没有报告我的代码有任何问题。
我通过在函数底部移动栅栏同步部分解决了这个问题,但在我看来,这是一个次优的解决方案,因为我等待帧完成渲染,而不是准备下一帧。
// ...
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || MainWindow->HasBeenResized())
Recreate();
else if (result != VK_SUCCESS)
throw std::runtime_error("Failed to present result!");
InFlightFences[frameIndex]->Wait();
InFlightFences[frameIndex]->Reset();
}
如何在 Windows 和 Linux 上正确同步帧?我究竟做错了什么?我错过了什么?
【问题讨论】: