Vulkan:vkQueuePresentKHR做什么?

时间:2019-10-30 16:37:40

标签: vulkan

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以将数据呈现到我自己的内存中,或者我现在正在做是否正确?

1 个答案:

答案 0 :(得分:0)

第二帧的vkQueueSubmit不能与第一帧的vkQueuePresent“冲突”。

在第二帧中,您还将执行一个vkAcquireNextImage,它给出了一个信号量。只要发出信号量,Presentation Engine就不再使用该Image(无论它是否与前一帧相同)。

vkQueueSubmit可能与之冲突的是先前的vkQueueSubmit和所使用的各种资源。

vkQueuePresent的作用是在队列返回之前提交您的信号量,等待队列中的执行。在信号量发出信号之前,它将无法访问图像。它将图片从Vulkan队列中以非同步方式在外部图像中显示。没有其他规定。可以复制图像,即时复制图像或直接使用图像,也可以使用其他符合上述API合同的图像。