繁体   English   中英

Vulkan - 飞行中的多个帧

[英]Vulkan - Multiple frames in flight

我正在从事一个 Vulkan 项目,并且已经完成了绘制立方体的进程。 我是 Vulkan 的新手,必须重新学习所有内容。 我遇到了一些麻烦。

我想要多帧进行中(1 个录制,1 个执行)。 我的渲染循环基于https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Rendering_and_presentation ,因为当我有第二帧在飞行中时,我无法理解发生了什么。 现在,它没有崩溃,但它似乎也不能正常工作,因为 'currentFrame' 和 'imageIndex' 是相同的。 如果我将 currentFrame 或 imageIndex 更改为不同,则没有任何效果。 我应该注意,如果重要的话,我现在为每个池创建 N VkCommandPools 和 1 个命令缓冲区。

在里面:

VkFenceCreateInfo fence_info;
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_info.pNext = NULL;
fence_info.flags = 0;

VkFence *inFlightFences = malloc(sizeof *inFlightFences * NUM_SWAPCHAIN_IMAGES);

for(i = 0; i < NUM_SWAPCHAIN_IMAGES; i++) {
    result = vkCreateFence(device.logical, &fence_info, NULL, &inFlightFences[i]);
    assert(result == VK_SUCCESS && "vkCreateFence");
}
VkFence imagesInFlight[2] = {NULL, NULL};
unsigned int imageIndex, currentFrame = 0;

主循环:

    vkAcquireNextImageKHR(device.logical, swapchain.handle, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);

    printf("%u %u\n", currentFrame, imageIndex); // both equal always
    
    if(imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
        vkWaitForFences(device.logical, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
    }
    
    imagesInFlight[imageIndex] = inFlightFences[currentFrame];
    
    VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]};
    VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]};

    /* begin rendering */
    
    VkCommandBufferBeginInfo begin_info = {0};
    begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    
    vkBeginCommandBuffer(main_cmdbuffs[imageIndex], &begin_info);
    
    VkImageMemoryBarrier acquire_barrier;
    acquire_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    acquire_barrier.pNext = NULL;
    acquire_barrier.srcAccessMask = 0;
    acquire_barrier.dstAccessMask = VK_ACCESS_MEMORY_WRITE_BIT;
    acquire_barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    acquire_barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
    acquire_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    acquire_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    acquire_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    acquire_barrier.subresourceRange.baseMipLevel = 0;
    acquire_barrier.subresourceRange.levelCount = 1;
    acquire_barrier.subresourceRange.baseArrayLayer = 0;
    acquire_barrier.subresourceRange.layerCount = 1;
    acquire_barrier.image = swapchain.images[imageIndex];
    
    vkCmdPipelineBarrier(main_cmdbuffs[imageIndex],
                         VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
                         VK_PIPELINE_STAGE_TRANSFER_BIT,
                         0, 0, NULL, 0, NULL, 1, &acquire_barrier);        

    VkImageMemoryBarrier present_barrier = {};
    present_barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    present_barrier.pNext = NULL;
    present_barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
    present_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
    present_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
    present_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
    present_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    present_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    present_barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    present_barrier.subresourceRange.baseMipLevel = 0;
    present_barrier.subresourceRange.levelCount = 1;
    present_barrier.subresourceRange.baseArrayLayer = 0;
    present_barrier.subresourceRange.layerCount = 1;
    present_barrier.image = swapchain.images[imageIndex];
    
    vkCmdPipelineBarrier(main_cmdbuffs[imageIndex], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, NULL,
                        0, NULL, 1, &present_barrier);
    vkEndCommandBuffer(main_cmdbuffs[imageIndex]);

    VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    VkSubmitInfo submit_info = {0};
    
    submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submit_info.pWaitDstStageMask = &wait_dst_stage_mask;
    submit_info.commandBufferCount = 1;
    submit_info.pCommandBuffers = &main_cmdbuffs[imageIndex];
    submit_info.waitSemaphoreCount = 1;
    submit_info.signalSemaphoreCount = 1;
    submit_info.pWaitSemaphores = waitSemaphores;
    submit_info.pSignalSemaphores = signalSemaphores;
    
    vkResetFences(device.logical, 1, &inFlightFences[currentFrame]);
    
    vkQueueSubmit(device.graphics_queue, 1, &submit_info, inFlightFences[imageIndex]);
    
    VkPresentInfoKHR present_info = {0};
    present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    present_info.waitSemaphoreCount = 1;
    present_info.pWaitSemaphores = &renderFinishedSemaphores[currentFrame];
    present_info.swapchainCount = 1;
    present_info.pSwapchains = &swapchain.handle;
    present_info.pImageIndices = &currentFrame;
    
    vkQueuePresentKHR(device.graphics_queue, &present_info);

这可能会失败有几个原因 - 无法通过提供的信息量来判断。 要做的最重要的事情是激活验证层,尝试理解错误消息并摆脱它(在此处发布验证层错误也将有所帮助。)。

您可以进一步调查的一些要点:

从给出的源代码来看,您似乎每帧都在重新记录命令缓冲区。 如果您这样做,那么您必须确保:

commandBuffer 必须是从使用 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT 创建的池中分配的

(引用规范)。 并且必须在某处调用vkResetCommandBuffer Vulkan Tutorial正在做的是:记录一次命令缓冲区(飞行中的每一帧一个)并在每一帧重用那些预先记录的命令缓冲区。

关于currentFrameimageIndex :在最佳情况下,它们将是同步的,因为那时

vkWaitForFences(device.logical, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);

永远不必等待——也就是说,如果您之前等待过inFlightFences[currentFrame] ,这正是 Vulkan 教程所做的,但您是否也这样做并不明显。

您无法真正控制获得的imageIndex ,因为它是从vkAcquireNextImageKHR返回的。 但是,您必须推进currentFrame ,如果您从您发布的代码中这样做,这 - 再一次 - 并不明显。

为您正在创建的每个VkCommandBuffer创建一个VkCommandPool (或者换一种说法:从命令池中仅分配一个命令缓冲区)是一种次优策略。 我认为,如果您只有一种类型的命令缓冲区(即设置了VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT位的命令缓冲区,如果您真的要重置命令缓冲区),则没有什么可以反对仅使用一个VkCommandPool 如果您要创建不同类型的命令缓冲区(例如可重置的和不可重置的),那么不同的池可能有意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM