Vulkan:vkQueuePresentKHR做了什么?

问题描述 投票:-1回答:1
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将数据显示在新的内存中,因此将第二帧渲染到帧缓冲区不会影响第一帧的内容。

2:第一帧和第二帧占用相同的帧缓冲区,当第一帧的vkQueuePresentKHR和第二帧的vkQueueSubmit同时使用帧缓冲区时,会发生图像撕裂(我想)。 >

我认为第二种可能性会更高。

我想将结果呈现到我自己的内存中,而不是将其呈现在屏幕上。我想弄清楚vkQueuePresentKHR的作用。

这里是渲染到您自己的内存的示例:https://github.com/SaschaWillems/Vulkan/blob/master/examples/renderheadless/renderheadless.cpp

在此示例中,渲染的帧缓冲区数据被传输到新的内存。

在我设计的程序中,有一个辅助线程负责等待栅栏完成。传输完成后将使用此内存。类似于下面的示例:

主线程:

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

void drawFrame(){vkWaitForFences(device,1,&inFlightFences [currentFrame],VK_TRUE,std :: numeric_limits :: max()); ... VkSemaphore signalSemaphores [] = {...

vulkan
1个回答
0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.