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;
}
在提交第一帧VkQueuePresentKHR后调用vkQueueSubmit,在第二帧中,调用vkWaitForFences等待前一帧的vkQueueSubmit结束,然后再次调用vkQueueSubmit提交,但此时vkQueuePresentKHR的第一帧可能在呈现中,它占据了第一帧的帧缓冲区。那么,第二帧的vkQueueSubmit会与第一帧的vkQueuePresentKHR冲突吗?
我想可能有两种情况:
1:第一帧和第二帧不占用相同的帧缓冲区,当第一帧vkQueueSubmit结束时,数据被复制到新的内存中。vkQueuePresentKHR在新内存中显示数据,因此将第二帧呈现给Framebuffer不会影响第一帧的内容。
2:第一帧和第二帧占用相同的帧缓冲区,当第一帧的vkQueuePresentKHR和第二帧的vkQueueSubmit同时使用帧缓冲区时,图像发生撕裂(我猜)。
我认为第二种可能性会更高。
我希望将结果呈现到我自己的内存中,而不是显示在屏幕上。我想弄清楚vkQueuePresentKHR是做什么的。
下面是一个向您自己的内存呈现的示例:https://github.com/SaschaWillems/Vulkan/blob/master/examples/renderheadless/renderheadless.cpp
在本例中,呈现的Framebuffer数据被传输到新内存。
在我设计的程序中,有一个二级线程负责等待栅栏的完成。一旦传输完成,就会使用这个内存。类似于下面的例子:
主线程:
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,将数据呈现到我自己的内存中,还是我现在所做的是正确的?
发布于 2019-10-31 01:07:26
第二帧的vkQueueSubmit
不能与第一帧的vkQueuePresent
“冲突”。
在第二个框架中,您还将执行一个vkAcquireNextImage
,它提供一个信号量。如果信号是信号,则表示引擎不再使用该图像(不管它是否与上一帧相同)。
vkQueueSubmit
可以与之冲突的是以前的vkQueueSubmit
和使用的各种资源。
vkQueuePresent
所做的是提交您的信号量,等待它返回之前执行。在信号量发出信号之前,它不会访问该图像。它将从Vulkan队列异步地在Image外部显示图片。其他任何事情都没有具体说明。图像可以被复制、复制,或者直接使用,或者其他任何符合上述API协议的内容。
https://stackoverflow.com/questions/58630028
复制相似问题