Modernize and fix frame sync in QVulkanWindow
Follow 24d62ffd720b5bec5d07b07b8d2c9dda7635f3c0 for QVulkanWindow. The Vulkan backend of QRhi has diverged from QVulkanWindow even before that recent fix, having many changes over the years that are not present in QVulkanWindow. Introduce some of these now, to make things work with the newer validation layer bundled with the Vulkan 1.4 SDKs. Task-number: QTBUG-135645 Change-Id: Ic630e9a57c344843c171871b5a0386ed18027b22 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
53756dcfbc
commit
8fc3bc67df
@ -1196,13 +1196,6 @@ void QVulkanWindowPrivate::recreateSwapChain()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = devFuncs->vkCreateFence(dev, &fenceInfo, nullptr, &image.cmdFence);
|
|
||||||
if (err != VK_SUCCESS) {
|
|
||||||
qWarning("QVulkanWindow: Failed to create command buffer fence: %d", err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
image.cmdFenceWaitable = true; // fence was created in signaled state
|
|
||||||
|
|
||||||
VkImageView views[3] = { image.imageView,
|
VkImageView views[3] = { image.imageView,
|
||||||
dsView,
|
dsView,
|
||||||
msaa ? image.msaaImageView : VK_NULL_HANDLE };
|
msaa ? image.msaaImageView : VK_NULL_HANDLE };
|
||||||
@ -1270,13 +1263,17 @@ void QVulkanWindowPrivate::recreateSwapChain()
|
|||||||
frame.imageAcquired = false;
|
frame.imageAcquired = false;
|
||||||
frame.imageSemWaitable = false;
|
frame.imageSemWaitable = false;
|
||||||
|
|
||||||
devFuncs->vkCreateFence(dev, &fenceInfo, nullptr, &frame.fence);
|
|
||||||
frame.fenceWaitable = true; // fence was created in signaled state
|
|
||||||
|
|
||||||
devFuncs->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.imageSem);
|
devFuncs->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.imageSem);
|
||||||
devFuncs->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.drawSem);
|
devFuncs->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.drawSem);
|
||||||
if (gfxQueueFamilyIdx != presQueueFamilyIdx)
|
if (gfxQueueFamilyIdx != presQueueFamilyIdx)
|
||||||
devFuncs->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.presTransSem);
|
devFuncs->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.presTransSem);
|
||||||
|
|
||||||
|
err = devFuncs->vkCreateFence(dev, &fenceInfo, nullptr, &frame.cmdFence);
|
||||||
|
if (err != VK_SUCCESS) {
|
||||||
|
qWarning("QVulkanWindow: Failed to create command buffer fence: %d", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
frame.cmdFenceWaitable = true; // fence was created in signaled state
|
||||||
}
|
}
|
||||||
|
|
||||||
currentFrame = 0;
|
currentFrame = 0;
|
||||||
@ -1432,12 +1429,9 @@ void QVulkanWindowPrivate::releaseSwapChain()
|
|||||||
|
|
||||||
for (int i = 0; i < frameLag; ++i) {
|
for (int i = 0; i < frameLag; ++i) {
|
||||||
FrameResources &frame(frameRes[i]);
|
FrameResources &frame(frameRes[i]);
|
||||||
if (frame.fence) {
|
if (frame.cmdBuf) {
|
||||||
if (frame.fenceWaitable)
|
devFuncs->vkFreeCommandBuffers(dev, cmdPool, 1, &frame.cmdBuf);
|
||||||
devFuncs->vkWaitForFences(dev, 1, &frame.fence, VK_TRUE, UINT64_MAX);
|
frame.cmdBuf = VK_NULL_HANDLE;
|
||||||
devFuncs->vkDestroyFence(dev, frame.fence, nullptr);
|
|
||||||
frame.fence = VK_NULL_HANDLE;
|
|
||||||
frame.fenceWaitable = false;
|
|
||||||
}
|
}
|
||||||
if (frame.imageSem) {
|
if (frame.imageSem) {
|
||||||
devFuncs->vkDestroySemaphore(dev, frame.imageSem, nullptr);
|
devFuncs->vkDestroySemaphore(dev, frame.imageSem, nullptr);
|
||||||
@ -1451,17 +1445,17 @@ void QVulkanWindowPrivate::releaseSwapChain()
|
|||||||
devFuncs->vkDestroySemaphore(dev, frame.presTransSem, nullptr);
|
devFuncs->vkDestroySemaphore(dev, frame.presTransSem, nullptr);
|
||||||
frame.presTransSem = VK_NULL_HANDLE;
|
frame.presTransSem = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
if (frame.cmdFence) {
|
||||||
|
if (frame.cmdFenceWaitable)
|
||||||
|
devFuncs->vkWaitForFences(dev, 1, &frame.cmdFence, VK_TRUE, UINT64_MAX);
|
||||||
|
devFuncs->vkDestroyFence(dev, frame.cmdFence, nullptr);
|
||||||
|
frame.cmdFence = VK_NULL_HANDLE;
|
||||||
|
frame.cmdFenceWaitable = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < swapChainBufferCount; ++i) {
|
for (int i = 0; i < swapChainBufferCount; ++i) {
|
||||||
ImageResources &image(imageRes[i]);
|
ImageResources &image(imageRes[i]);
|
||||||
if (image.cmdFence) {
|
|
||||||
if (image.cmdFenceWaitable)
|
|
||||||
devFuncs->vkWaitForFences(dev, 1, &image.cmdFence, VK_TRUE, UINT64_MAX);
|
|
||||||
devFuncs->vkDestroyFence(dev, image.cmdFence, nullptr);
|
|
||||||
image.cmdFence = VK_NULL_HANDLE;
|
|
||||||
image.cmdFenceWaitable = false;
|
|
||||||
}
|
|
||||||
if (image.fb) {
|
if (image.fb) {
|
||||||
devFuncs->vkDestroyFramebuffer(dev, image.fb, nullptr);
|
devFuncs->vkDestroyFramebuffer(dev, image.fb, nullptr);
|
||||||
image.fb = VK_NULL_HANDLE;
|
image.fb = VK_NULL_HANDLE;
|
||||||
@ -1470,10 +1464,6 @@ void QVulkanWindowPrivate::releaseSwapChain()
|
|||||||
devFuncs->vkDestroyImageView(dev, image.imageView, nullptr);
|
devFuncs->vkDestroyImageView(dev, image.imageView, nullptr);
|
||||||
image.imageView = VK_NULL_HANDLE;
|
image.imageView = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
if (image.cmdBuf) {
|
|
||||||
devFuncs->vkFreeCommandBuffers(dev, cmdPool, 1, &image.cmdBuf);
|
|
||||||
image.cmdBuf = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
if (image.presTransCmdBuf) {
|
if (image.presTransCmdBuf) {
|
||||||
devFuncs->vkFreeCommandBuffers(dev, presCmdPool, 1, &image.presTransCmdBuf);
|
devFuncs->vkFreeCommandBuffers(dev, presCmdPool, 1, &image.presTransCmdBuf);
|
||||||
image.presTransCmdBuf = VK_NULL_HANDLE;
|
image.presTransCmdBuf = VK_NULL_HANDLE;
|
||||||
@ -1920,24 +1910,21 @@ void QVulkanWindowPrivate::beginFrame()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait if we are too far ahead
|
||||||
FrameResources &frame(frameRes[currentFrame]);
|
FrameResources &frame(frameRes[currentFrame]);
|
||||||
|
if (frame.cmdFenceWaitable) {
|
||||||
if (!frame.imageAcquired) {
|
devFuncs->vkWaitForFences(dev, 1, &frame.cmdFence, VK_TRUE, UINT64_MAX);
|
||||||
// Wait if we are too far ahead, i.e. the thread gets throttled based on the presentation rate
|
devFuncs->vkResetFences(dev, 1, &frame.cmdFence);
|
||||||
// (note that we are using FIFO mode -> vsync)
|
frame.cmdFenceWaitable = false;
|
||||||
if (frame.fenceWaitable) {
|
|
||||||
devFuncs->vkWaitForFences(dev, 1, &frame.fence, VK_TRUE, UINT64_MAX);
|
|
||||||
devFuncs->vkResetFences(dev, 1, &frame.fence);
|
|
||||||
frame.fenceWaitable = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// move on to next swapchain image
|
// move on to next swapchain image
|
||||||
|
if (!frame.imageAcquired) {
|
||||||
VkResult err = vkAcquireNextImageKHR(dev, swapChain, UINT64_MAX,
|
VkResult err = vkAcquireNextImageKHR(dev, swapChain, UINT64_MAX,
|
||||||
frame.imageSem, frame.fence, ¤tImage);
|
frame.imageSem, VK_NULL_HANDLE, ¤tImage);
|
||||||
if (err == VK_SUCCESS || err == VK_SUBOPTIMAL_KHR) {
|
if (err == VK_SUCCESS || err == VK_SUBOPTIMAL_KHR) {
|
||||||
frame.imageSemWaitable = true;
|
frame.imageSemWaitable = true;
|
||||||
frame.imageAcquired = true;
|
frame.imageAcquired = true;
|
||||||
frame.fenceWaitable = true;
|
|
||||||
} else if (err == VK_ERROR_OUT_OF_DATE_KHR) {
|
} else if (err == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
recreateSwapChain();
|
recreateSwapChain();
|
||||||
q->requestUpdate();
|
q->requestUpdate();
|
||||||
@ -1950,23 +1937,15 @@ void QVulkanWindowPrivate::beginFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the previous draw for the same image has finished
|
|
||||||
ImageResources &image(imageRes[currentImage]);
|
|
||||||
if (image.cmdFenceWaitable) {
|
|
||||||
devFuncs->vkWaitForFences(dev, 1, &image.cmdFence, VK_TRUE, UINT64_MAX);
|
|
||||||
devFuncs->vkResetFences(dev, 1, &image.cmdFence);
|
|
||||||
image.cmdFenceWaitable = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// build new draw command buffer
|
// build new draw command buffer
|
||||||
if (image.cmdBuf) {
|
if (frame.cmdBuf) {
|
||||||
devFuncs->vkFreeCommandBuffers(dev, cmdPool, 1, &image.cmdBuf);
|
devFuncs->vkFreeCommandBuffers(dev, cmdPool, 1, &frame.cmdBuf);
|
||||||
image.cmdBuf = nullptr;
|
frame.cmdBuf = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkCommandBufferAllocateInfo cmdBufInfo = {
|
VkCommandBufferAllocateInfo cmdBufInfo = {
|
||||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1 };
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1 };
|
||||||
VkResult err = devFuncs->vkAllocateCommandBuffers(dev, &cmdBufInfo, &image.cmdBuf);
|
VkResult err = devFuncs->vkAllocateCommandBuffers(dev, &cmdBufInfo, &frame.cmdBuf);
|
||||||
if (err != VK_SUCCESS) {
|
if (err != VK_SUCCESS) {
|
||||||
if (!checkDeviceLost(err))
|
if (!checkDeviceLost(err))
|
||||||
qWarning("QVulkanWindow: Failed to allocate frame command buffer: %d", err);
|
qWarning("QVulkanWindow: Failed to allocate frame command buffer: %d", err);
|
||||||
@ -1975,7 +1954,7 @@ void QVulkanWindowPrivate::beginFrame()
|
|||||||
|
|
||||||
VkCommandBufferBeginInfo cmdBufBeginInfo = {
|
VkCommandBufferBeginInfo cmdBufBeginInfo = {
|
||||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, 0, nullptr };
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, 0, nullptr };
|
||||||
err = devFuncs->vkBeginCommandBuffer(image.cmdBuf, &cmdBufBeginInfo);
|
err = devFuncs->vkBeginCommandBuffer(frame.cmdBuf, &cmdBufBeginInfo);
|
||||||
if (err != VK_SUCCESS) {
|
if (err != VK_SUCCESS) {
|
||||||
if (!checkDeviceLost(err))
|
if (!checkDeviceLost(err))
|
||||||
qWarning("QVulkanWindow: Failed to begin frame command buffer: %d", err);
|
qWarning("QVulkanWindow: Failed to begin frame command buffer: %d", err);
|
||||||
@ -1985,6 +1964,7 @@ void QVulkanWindowPrivate::beginFrame()
|
|||||||
if (frameGrabbing)
|
if (frameGrabbing)
|
||||||
frameGrabTargetImage = QImage(swapChainImageSize, QImage::Format_RGBA8888); // the format is as documented
|
frameGrabTargetImage = QImage(swapChainImageSize, QImage::Format_RGBA8888); // the format is as documented
|
||||||
|
|
||||||
|
ImageResources &image(imageRes[currentImage]);
|
||||||
if (renderer) {
|
if (renderer) {
|
||||||
framePending = true;
|
framePending = true;
|
||||||
renderer->startNextFrame();
|
renderer->startNextFrame();
|
||||||
@ -2006,8 +1986,8 @@ void QVulkanWindowPrivate::beginFrame()
|
|||||||
rpBeginInfo.renderArea.extent.height = swapChainImageSize.height();
|
rpBeginInfo.renderArea.extent.height = swapChainImageSize.height();
|
||||||
rpBeginInfo.clearValueCount = sampleCount > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
|
rpBeginInfo.clearValueCount = sampleCount > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
|
||||||
rpBeginInfo.pClearValues = clearValues;
|
rpBeginInfo.pClearValues = clearValues;
|
||||||
devFuncs->vkCmdBeginRenderPass(image.cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
devFuncs->vkCmdBeginRenderPass(frame.cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
devFuncs->vkCmdEndRenderPass(image.cmdBuf);
|
devFuncs->vkCmdEndRenderPass(frame.cmdBuf);
|
||||||
|
|
||||||
endFrame();
|
endFrame();
|
||||||
}
|
}
|
||||||
@ -2033,7 +2013,7 @@ void QVulkanWindowPrivate::endFrame()
|
|||||||
presTrans.image = image.image;
|
presTrans.image = image.image;
|
||||||
presTrans.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
presTrans.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
presTrans.subresourceRange.levelCount = presTrans.subresourceRange.layerCount = 1;
|
presTrans.subresourceRange.levelCount = presTrans.subresourceRange.layerCount = 1;
|
||||||
devFuncs->vkCmdPipelineBarrier(image.cmdBuf,
|
devFuncs->vkCmdPipelineBarrier(frame.cmdBuf,
|
||||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||||
0, 0, nullptr, 0, nullptr,
|
0, 0, nullptr, 0, nullptr,
|
||||||
@ -2044,7 +2024,7 @@ void QVulkanWindowPrivate::endFrame()
|
|||||||
if (frameGrabbing)
|
if (frameGrabbing)
|
||||||
addReadback();
|
addReadback();
|
||||||
|
|
||||||
VkResult err = devFuncs->vkEndCommandBuffer(image.cmdBuf);
|
VkResult err = devFuncs->vkEndCommandBuffer(frame.cmdBuf);
|
||||||
if (err != VK_SUCCESS) {
|
if (err != VK_SUCCESS) {
|
||||||
if (!checkDeviceLost(err))
|
if (!checkDeviceLost(err))
|
||||||
qWarning("QVulkanWindow: Failed to end frame command buffer: %d", err);
|
qWarning("QVulkanWindow: Failed to end frame command buffer: %d", err);
|
||||||
@ -2056,7 +2036,7 @@ void QVulkanWindowPrivate::endFrame()
|
|||||||
memset(&submitInfo, 0, sizeof(submitInfo));
|
memset(&submitInfo, 0, sizeof(submitInfo));
|
||||||
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
submitInfo.commandBufferCount = 1;
|
submitInfo.commandBufferCount = 1;
|
||||||
submitInfo.pCommandBuffers = &image.cmdBuf;
|
submitInfo.pCommandBuffers = &frame.cmdBuf;
|
||||||
if (frame.imageSemWaitable) {
|
if (frame.imageSemWaitable) {
|
||||||
submitInfo.waitSemaphoreCount = 1;
|
submitInfo.waitSemaphoreCount = 1;
|
||||||
submitInfo.pWaitSemaphores = &frame.imageSem;
|
submitInfo.pWaitSemaphores = &frame.imageSem;
|
||||||
@ -2068,12 +2048,12 @@ void QVulkanWindowPrivate::endFrame()
|
|||||||
VkPipelineStageFlags psf = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
VkPipelineStageFlags psf = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
submitInfo.pWaitDstStageMask = &psf;
|
submitInfo.pWaitDstStageMask = &psf;
|
||||||
|
|
||||||
Q_ASSERT(!image.cmdFenceWaitable);
|
Q_ASSERT(!frame.cmdFenceWaitable);
|
||||||
|
|
||||||
err = devFuncs->vkQueueSubmit(gfxQueue, 1, &submitInfo, image.cmdFence);
|
err = devFuncs->vkQueueSubmit(gfxQueue, 1, &submitInfo, frame.cmdFence);
|
||||||
if (err == VK_SUCCESS) {
|
if (err == VK_SUCCESS) {
|
||||||
frame.imageSemWaitable = false;
|
frame.imageSemWaitable = false;
|
||||||
image.cmdFenceWaitable = true;
|
frame.cmdFenceWaitable = true;
|
||||||
} else {
|
} else {
|
||||||
if (!checkDeviceLost(err))
|
if (!checkDeviceLost(err))
|
||||||
qWarning("QVulkanWindow: Failed to submit to graphics queue: %d", err);
|
qWarning("QVulkanWindow: Failed to submit to graphics queue: %d", err);
|
||||||
@ -2228,6 +2208,7 @@ void QVulkanWindowPrivate::addReadback()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameResources &frame(frameRes[currentFrame]);
|
||||||
ImageResources &image(imageRes[currentImage]);
|
ImageResources &image(imageRes[currentImage]);
|
||||||
|
|
||||||
VkImageMemoryBarrier barrier;
|
VkImageMemoryBarrier barrier;
|
||||||
@ -2242,7 +2223,7 @@ void QVulkanWindowPrivate::addReadback()
|
|||||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
barrier.image = image.image;
|
barrier.image = image.image;
|
||||||
|
|
||||||
devFuncs->vkCmdPipelineBarrier(image.cmdBuf,
|
devFuncs->vkCmdPipelineBarrier(frame.cmdBuf,
|
||||||
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, 0, nullptr, 0, nullptr,
|
0, 0, nullptr, 0, nullptr,
|
||||||
@ -2254,7 +2235,7 @@ void QVulkanWindowPrivate::addReadback()
|
|||||||
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
barrier.image = frameGrabImage;
|
barrier.image = frameGrabImage;
|
||||||
|
|
||||||
devFuncs->vkCmdPipelineBarrier(image.cmdBuf,
|
devFuncs->vkCmdPipelineBarrier(frame.cmdBuf,
|
||||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
0, 0, nullptr, 0, nullptr,
|
0, 0, nullptr, 0, nullptr,
|
||||||
@ -2268,7 +2249,7 @@ void QVulkanWindowPrivate::addReadback()
|
|||||||
copyInfo.extent.height = frameGrabTargetImage.height();
|
copyInfo.extent.height = frameGrabTargetImage.height();
|
||||||
copyInfo.extent.depth = 1;
|
copyInfo.extent.depth = 1;
|
||||||
|
|
||||||
devFuncs->vkCmdCopyImage(image.cmdBuf, image.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
devFuncs->vkCmdCopyImage(frame.cmdBuf, image.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||||
frameGrabImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Info);
|
frameGrabImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©Info);
|
||||||
|
|
||||||
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
|
||||||
@ -2277,7 +2258,7 @@ void QVulkanWindowPrivate::addReadback()
|
|||||||
barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
|
barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
|
||||||
barrier.image = frameGrabImage;
|
barrier.image = frameGrabImage;
|
||||||
|
|
||||||
devFuncs->vkCmdPipelineBarrier(image.cmdBuf,
|
devFuncs->vkCmdPipelineBarrier(frame.cmdBuf,
|
||||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_PIPELINE_STAGE_HOST_BIT,
|
VK_PIPELINE_STAGE_HOST_BIT,
|
||||||
0, 0, nullptr, 0, nullptr,
|
0, 0, nullptr, 0, nullptr,
|
||||||
@ -2286,14 +2267,14 @@ void QVulkanWindowPrivate::addReadback()
|
|||||||
|
|
||||||
void QVulkanWindowPrivate::finishBlockingReadback()
|
void QVulkanWindowPrivate::finishBlockingReadback()
|
||||||
{
|
{
|
||||||
ImageResources &image(imageRes[currentImage]);
|
|
||||||
|
|
||||||
// Block until the current frame is done. Normally this wait would only be
|
// Block until the current frame is done. Normally this wait would only be
|
||||||
// done in current + concurrentFrameCount().
|
// done in current + concurrentFrameCount().
|
||||||
devFuncs->vkWaitForFences(dev, 1, &image.cmdFence, VK_TRUE, UINT64_MAX);
|
FrameResources &frame(frameRes[currentFrame]);
|
||||||
devFuncs->vkResetFences(dev, 1, &image.cmdFence);
|
if (frame.cmdFenceWaitable) {
|
||||||
// will reuse the same image for the next "real" frame, do not wait then
|
devFuncs->vkWaitForFences(dev, 1, &frame.cmdFence, VK_TRUE, UINT64_MAX);
|
||||||
image.cmdFenceWaitable = false;
|
devFuncs->vkResetFences(dev, 1, &frame.cmdFence);
|
||||||
|
frame.cmdFenceWaitable = false;
|
||||||
|
}
|
||||||
|
|
||||||
VkImageSubresource subres = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
|
VkImageSubresource subres = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
|
||||||
VkSubresourceLayout layout;
|
VkSubresourceLayout layout;
|
||||||
@ -2523,7 +2504,7 @@ QSize QVulkanWindow::swapChainImageSize() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns The active command buffer for the current swap chain image.
|
Returns The active command buffer for the current swap chain frame.
|
||||||
Implementations of QVulkanWindowRenderer::startNextFrame() are expected to
|
Implementations of QVulkanWindowRenderer::startNextFrame() are expected to
|
||||||
add commands to this command buffer.
|
add commands to this command buffer.
|
||||||
|
|
||||||
@ -2537,7 +2518,7 @@ VkCommandBuffer QVulkanWindow::currentCommandBuffer() const
|
|||||||
qWarning("QVulkanWindow: Attempted to call currentCommandBuffer() without an active frame");
|
qWarning("QVulkanWindow: Attempted to call currentCommandBuffer() without an active frame");
|
||||||
return VK_NULL_HANDLE;
|
return VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
return d->imageRes[d->currentImage].cmdBuf;
|
return d->frameRes[d->currentFrame].cmdBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -109,9 +109,6 @@ public:
|
|||||||
struct ImageResources {
|
struct ImageResources {
|
||||||
VkImage image = VK_NULL_HANDLE;
|
VkImage image = VK_NULL_HANDLE;
|
||||||
VkImageView imageView = VK_NULL_HANDLE;
|
VkImageView imageView = VK_NULL_HANDLE;
|
||||||
VkCommandBuffer cmdBuf = VK_NULL_HANDLE;
|
|
||||||
VkFence cmdFence = VK_NULL_HANDLE;
|
|
||||||
bool cmdFenceWaitable = false;
|
|
||||||
VkFramebuffer fb = VK_NULL_HANDLE;
|
VkFramebuffer fb = VK_NULL_HANDLE;
|
||||||
VkCommandBuffer presTransCmdBuf = VK_NULL_HANDLE;
|
VkCommandBuffer presTransCmdBuf = VK_NULL_HANDLE;
|
||||||
VkImage msaaImage = VK_NULL_HANDLE;
|
VkImage msaaImage = VK_NULL_HANDLE;
|
||||||
@ -123,13 +120,14 @@ public:
|
|||||||
uint32_t currentImage;
|
uint32_t currentImage;
|
||||||
|
|
||||||
struct FrameResources {
|
struct FrameResources {
|
||||||
VkFence fence = VK_NULL_HANDLE;
|
|
||||||
bool fenceWaitable = false;
|
|
||||||
VkSemaphore imageSem = VK_NULL_HANDLE;
|
VkSemaphore imageSem = VK_NULL_HANDLE;
|
||||||
VkSemaphore drawSem = VK_NULL_HANDLE;
|
VkSemaphore drawSem = VK_NULL_HANDLE;
|
||||||
VkSemaphore presTransSem = VK_NULL_HANDLE;
|
VkSemaphore presTransSem = VK_NULL_HANDLE;
|
||||||
|
VkFence cmdFence = VK_NULL_HANDLE;
|
||||||
|
VkCommandBuffer cmdBuf = VK_NULL_HANDLE;
|
||||||
bool imageAcquired = false;
|
bool imageAcquired = false;
|
||||||
bool imageSemWaitable = false;
|
bool imageSemWaitable = false;
|
||||||
|
bool cmdFenceWaitable = false;
|
||||||
} frameRes[MAX_FRAME_LAG];
|
} frameRes[MAX_FRAME_LAG];
|
||||||
|
|
||||||
uint32_t currentFrame;
|
uint32_t currentFrame;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user