Vulkan迷惑问题-交换链中获取图片vkAcquireNextImageKHR的ImageIndex 与 currentFrame之间的关系

奇林教育:Vulkan全系列教程,由浅入深,铸造职场不败神话! 课程链接:点击链接,跳转课程

vulkan当中,我们遇到了drawFrame函数,但是其中有inFlight的概念,那么如何理解这个概念,又如何理解在这个概念之下的同步控制(fence, semaphore)呢?

遇到的问题

在学习VulkanTutorial的时候,同学们一定会遇到drawFrame这个函数,在这个函数里面,绘制的过程是长得这样子的:

 	vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);

  	uint32_t imageIndex;
    vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);


    if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
        vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
    }
    imagesInFlight[imageIndex] = inFlightFences[currentFrame];

    VkSubmitInfo submitInfo{};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

    VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };
    VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
    submitInfo.waitSemaphoreCount = 1;
    submitInfo.pWaitSemaphores = waitSemaphores;
    submitInfo.pWaitDstStageMask = waitStages;

    submitInfo.commandBufferCount = 1;
    submitInfo.pCommandBuffers = &commandBuffers[imageIndex];

    VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };
    submitInfo.signalSemaphoreCount = 1;
    submitInfo.pSignalSemaphores = signalSemaphores;

    vkResetFences(device, 1, &inFlightFences[currentFrame]);

    if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) {
        throw std::runtime_error("failed to submit draw command buffer!");
    }

    VkPresentInfoKHR presentInfo{};
    presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;

    presentInfo.waitSemaphoreCount = 1;
    presentInfo.pWaitSemaphores = signalSemaphores;

    VkSwapchainKHR swapChains[] = { swapChain };
    presentInfo.swapchainCount = 1;
    presentInfo.pSwapchains = swapChains;

    presentInfo.pImageIndices = &imageIndex;

    vkQueuePresentKHR(presentQueue, &presentInfo);

    currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT

其中我们对代码进行一下简化,把其中的同步设置抽取出来看看:

  1. 进行了对于Fence的阻塞等待,用了currentFrame作为imageIndex来索引Fence
  2. 使用vkAcquireNextImageKHR来获取下一帧可以使用的图片,并且绑定一个Semaphore,用了currentFrame作为index来索引Semaphore
  3. 对提交信息等进行设置。
  4. currentFrame ++。

但是这个里面的ImageIndexcurrentFrame之间到底是什么关系呢?

同步控制

这段代码的大前提是,我们希望自己控制最多有多少张图片处于同时被渲染的状态。我们希望多少张,就做出来多少套Semaphore/Fence这种控制资源,然后用做出来的这N套资源,每一次选择一套,分配给第imageIndex张图片
我们可以先观察下所有的同步变量:

inFlightFences:这个数组的大小是MAX_FRAMES_IN_FLIGHT这么多,用来表示当前的Frame所对应的Fence
imagesInFlight:这个数组的大小是SwapChainImageCount这么多,用来表示当前某一个交换链当中图片所对应的Fence

这两个数组其实每一帧都会设置一次对应关系,imagesInFlight数组当中的每一个fence都对应了inFlightFences当中的某一个fence
接下来我们来分析下同步代码;

首先我们走到了当前第currentFrame个帧,那么,就要等待这一帧的命令队列执行完毕,为什么要等待呢?因为我们需要使用这个Fence,为接下即将获取的第imageIndex的图片进行过程控制,如下所示:
vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX);
只要这一句代码通过了,那么说明第currentFrame所对应的不管Fence也好、Semaphore也好,都已经使用完毕了,这一套资源对应的过程结束了。

然后我们获取到了一张当前可以用的交换链当中的图片ID

uint32_t **imageIndex**;
vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex);

那么接下来就要使用交换链当中的第imageIndex个图片进行渲染,所以我们需要给到这张图片一组同步对象,就是当前currentFrame对应的semaphorefence, 但是还有一个问题,我们必须等待imageIndex这一帧渲染完毕才能使用,那这一张图片对应的fence就必须执行完毕,除非这一帧没有被执行过,所以就判断一下**imagesInFlight[imageIndex]**是否被赋值过。

 if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
        vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
    }
    imagesInFlight[imageIndex] = inFlightFences[currentFrame];

如上所示,在判断imageIndex对应的一帧已经执行完毕之后,我们把currentFrame对应的fence分配过去了。
接下来我们可以看到:

VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores;
submitInfo.pWaitDstStageMask = waitStages;

submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &commandBuffers[imageIndex];

VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] };
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores;

因为我们之前等待了inFlightFences[currentFrame]完成,所以对应的那一次提交所使用的semaphore们也一定已经使用完毕,所以可以直接给这一帧使用,即给到了imageIndex对应的交换链图片。

结论

inFlightFencesimageAvailableSemaphores以及renderFinishedSemaphores都是我们提供的资源,数量就是MAX_FRAMES_IN_FLIGHT这么多,在每一次获取imageIndex的交换链图片的时候,会看看有没有闲置资源,如果有就分配给这一帧,否则就等待currentFrame所对应的资源组空闲。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
realesrgan-ncnn-vulkan-20211212-windows是一个基于ncnn框架和Vulkan图形API开发的图像超分辨率增强模型。它是由GitHub用户realsrgan开发的最新版本,最新发布日期为2021年12月12日,专为Windows操作系统而设计。 该模型的主要应用是图像超分辨率增强,通过提高图像的分辨率和细节,使图像看起来更加清晰和真实。它采用深度学习和卷积神经网络等先进的技术,能够将低分辨率的图像转换成高分辨率的图像,从而提升图像的质量和视觉效果。 realesrgan-ncnn-vulkan-20211212-windows的开发使用了ncnn框架和Vulkan图形API,这使得它能够在Windows系统上实现快速且高效的图像处理。ncnn是一个轻量级的深度学习框架,专注于在移动平台和嵌入式设备上实现高性能和低延迟的推理。而Vulkan图形API是一种跨平台的图形渲染和计算API,可以充分利用计算设备的性能,提供高效的图像处理和渲染能力。 realesrgan-ncnn-vulkan-20211212-windows的使用可以通过命令行或者图形界面进行,用户可以根据自己的需求和偏好选择适合的方式。该模型提供了训练好的权重参数,用户可以直接加载这些参数并进行图像超分辨率增强。此外,该模型还支持批量处理和视频处理,方便用户对多个图像进行处理。 总之,realesrgan-ncnn-vulkan-20211212-windows是一个高效、快速且易于使用的图像超分辨率增强模型,适用于Windows系统,并利用了ncnn框架和Vulkan图形API的优势,为用户提供了出色的图像处理效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赵新政

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值