void drawFrame() {
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
...
VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame])
...
VkSwapchainKHR swapChains[] = {swapChain};
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = signalSemaphores;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = swapChains;
presentInfo.pImageIndices = &imageIndex;
vkQueuePresentKHR(presentQueue, &presentInfo); // <- vkQueuePresentKHR
...
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
在提交第一帧vkQueueSubmit之后,将调用VkQueuePresentKHR作为先例,在第二帧中,调用vkWaitForFences等待前一帧的vkQueueSubmit结束,然后再次调用vkQueueSubmit进行提交,但是此时第一帧vkQueuePresentKHR可能在渲染中,它占据了第一帧的帧缓冲区。那么第二帧的vkQueueSubmit是否会与第一帧的vkQueuePresentKHR冲突?
我认为可能有两种情况:
1:第一帧和第二帧不占用相同的帧缓冲区,当第一帧vkQueueSubmit结束时,数据已被复制到新的内存中。 vkQueuePresentKHR将数据显示在新的内存中,因此将第二帧呈现到帧缓冲区不会影响第一帧的内容。
2:第一帧和第二帧占用相同的帧缓冲区,当第一帧的vkQueuePresentKHR和第二帧的vkQueueSubmit同时使用帧缓冲区时,会发生图像撕裂(我想)。
我认为第二种可能性会更高。
我想将结果渲染到我自己的内存中,而不是将其渲染到屏幕上。我想弄清楚vkQueuePresentKHR的作用。
以下是渲染到您自己的内存中的示例:https://github.com/SaschaWillems/Vulkan/blob/master/examples/renderheadless/renderheadless.cpp
在此示例中,渲染的帧缓冲区数据被传输到新的内存中。
在我设计的程序中,有一个辅助线程负责等待Fence完成。传输完成后将使用此内存。类似于以下示例:
主线程:
void drawFrame() {
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max());
...
VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;
// VkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) cannot be executed before the execution of
// vkQueueSubmit(graphicsQueue, 1, &transferSubmitInfo, transferCompleteFences[currentFrame]) in the previous frame. Otherwise,
// they will occupy the same FrameBuffer. I think it is not possible.
transferCompleteMutexs[currentFrame].lock(); // <- lock transferCompleteMutexs
vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame])
...
VkSubmitInfo transferSubmitInfo = {};
transferSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
transferSubmitInfo.commandBufferCount = 1;
transferSubmitInfo.pCommandBuffers = &commandBuffer;
transferSubmitInfo.waitSemaphoreCount = 1;
transferSubmitInfo.pWaitSemaphores = signalSemaphores;
vkQueueSubmit(graphicsQueue, 1, &transferSubmitInfo, transferCompleteFences[currentFrame]) // Signal <- transferCompleteFences
...
}
辅助线程:
while(true) {
// Waiting for transfer to complete
vkWaitForFences(logicalDevice_->vkLogicalDevice(),
1,
&transferCompleteFences[currentFrame], // Wait <- transferCompleteFences
VK_TRUE,
std::numeric_limits<uint64_t>::max());
// using transfer completed data
...
// Secondary thread knows that the current frame is transmitted. The next Primary thread can be submitted.
transferCompleteMutexs[currentFrame].unlock(); // <- unlock transferCompleteMutexs
}
上面的代码使用 transferCompleteMutexs 保护FrameBuffer,我认为这是必要的。但是显然vkQueuePresentKHR不会这样做。我是否有更好的方法来模拟vkQueuePresentKHR以将数据呈现到我自己的内存中,或者我现在正在做是否正确?
答案 0 :(得分:0)
第二帧的vkQueueSubmit
不能与第一帧的vkQueuePresent
“冲突”。
在第二帧中,您还将执行一个vkAcquireNextImage
,它给出了一个信号量。只要发出信号量,Presentation Engine就不再使用该Image(无论它是否与前一帧相同)。
vkQueueSubmit
可能与之冲突的是先前的vkQueueSubmit
和所使用的各种资源。
vkQueuePresent
的作用是在队列返回之前提交您的信号量,等待队列中的执行。在信号量发出信号之前,它将无法访问图像。它将图片从Vulkan队列中以非同步方式在外部图像中显示。没有其他规定。可以复制图像,即时复制图像或直接使用图像,也可以使用其他符合上述API合同的图像。