VulkanTutorial(11·Rendering,Frame synchronization)

Rendering and presentation

Outline of a frame

渲染每一帧的基本步骤:

  • 等待上一帧完成(fence)
  • 从swapchain获取图像
  • 开始录制到命令缓冲区,BeginRenderPass->bindPipeline->SetViewport->draw,绘制场景到取出的图像上
  • 录制结束的命令缓冲区·提交到queue
  • 展示交换链图像

Synchronization

Vulkan的核心设计理念是GPU上的执行同步,

事件执行顺序取决于Semaphores和Fences,这意味着调用是Asynchronization异步的,但是每个操作都依赖于前一个操作的完成,因此需要显式地对许多事件进行排序,让它们同步执行,而非异步

Semaphores 信号量

Semaphores用于在队列操作之间添加顺序,有两种信号量,二进制和时间轴

Semaphores在一个队列作为信号,当队列执行完发出信号,在另一个队列等待这个信号发生时执行,当这个新队列开始执行,Semaphores会自动重置为未发送的状态,从而允许再次使用它

VkSemaphore S
vkQueueSubmit(work: A, signal: S, wait: None)
vkQueueSubmit(work: B, signal: None, wait: S)
Fences围栏

上述Semaphores仅能控制GPU的运行,但是CPU通过Fences控制的,被告知GPU什么时候完成了某件事

每当开始新的任务,都可以附加VkFence围栏,当工作完成时,围栏将发出信号。然后,我们可以让CPU等待栅栏发出信号,保证在CPU继续之前工作已经完成

vkResetFences必须手动重置栅栏,使其回到无信号状态,这是因为围栏用于控制CPU的执行,因此CPU可以决定何时重置围栏,而Semaphores则自动等待

VkFence F 
vkQueueSubmit(work: A, fence: F)//完成后发出fence
vkWaitForFence(F)//阻止之后的CPU指令操作
vkResetFences();//重置围栏

实例

Fence

inFlightFence确保一次只渲染一帧,

vkWaitForFences接收fence数组,VK_TRUE在返回前需要等待数组的 所有fence发出信号后,超时参数,我们将其设置为64位无符号整数的最大值UINT64_MAX,这有效地禁用了超时

但是这里vkWaitForFences由于放在函数的最开始的指令位置,它在执行时将等待fence的信号,但是,fence信号是在此帧渲染完成后才发出,因此它会无限期的阻止CPU执行,

有一个内置于API中的巧妙的变通方法,fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;

标志表示在信号状态下创建围栏,以便对vkWaitForFences()的第一次调用立即返回,因为围栏已经发出信号

vkResetFence我们需要手动将栅栏重置为未发送信号的状态

Acquiring image

vkAcquireNextImageKHR交换链是一个扩展特性,所以我们必须使用vk*KHR命名约定的函数

第3 4个参数表示信号量,栅栏(都可选)

最后一个参数指定一个变量,用于输出已变为可用的交换链映像的索引

commandbuffer

vkResetCommandBuffer确保它能够被记录

recordCommandBuffer来记录我们想要的命令

SubmitInfo

有了完整记录的命令缓冲区,我们现在可以提交它了

VkSubmitInfo结构:队列提交和Synchronization同步

waitSemaphores指明需要等待的信号量,和pSignalSemaphores执行结束后发出的 信号量

waitStages在什么阶段等待,VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT等待写入颜色附件的图形管道后

imageAvailableSemaphore表示图像已经从交换链中获取并准备好进行渲染,renderFinishedSemaphore表示渲染已经完成并可以进行呈现

vkQueueSubmit将命令缓冲区提交到图形队列,需要指明fence(可选)

SubpassDependency

VkSubpassDependency指定子过程之间的内存和执行依赖性,有两个内置依赖项负责渲染过程开始和渲染过程结束时的过渡

指定依赖项和依赖子通道的索引,dstSubpass必须始终高于srcSubpass

接下来的两个字段指定要等待的操作以及这些操作发生的阶段,我们需要等待交换链完成对图像的阅读,然后才能访问它

VkSubpassDependency dependency{};//子通道依赖
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;

可以将VkSubmitInfok   的PipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };更改为VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT以确保渲染通道在图像可用之前不会开始

Presentation

VkPresentInfoKHR

前两个参数指定在呈现发生之前要等待哪些信号量,就像刚才的VkSubmitInfo中指定的一样

接下来的两个参数指定要向其呈现图像的交换链以及每个交换链的图像索引

最后一个可选参数称为pResults。它允许您指定一个VkResult值数组,以检查每个单独的交换链是否成功呈现

通过vkquePresentKHR(presentQueue,&presentInfo);将请求提交到交换链以呈现图像

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;

在900多行代码之后,我们终于看到了三角形

Frame synchronization

帧同步

现在我们的渲染循环需要等待上一帧完成,然后才能开始渲染下一帧(同步),这导致CPU不必要的空闲,我们应该允许一个帧的渲染(GPU)不干扰下一个帧的记录(CPU),

因此,我们需要多个commandBuffer、Semaphores和Fence,从而达到并发的目的,提高CPU的使用率

首先定义应该并发处理多少帧,CPU和GPU可以同时处理自己的任务,定义为2,但是并不是并发任务越多越好,如果有3帧或更多帧在运行中,CPU可能因为多个线程争夺而变大运行缓慢

实例

每个帧都应该有自己的commandBuffer、Semaphores和Fence,然后将它们改为vectors

需要修改createCommandBuffer,createSyncObjects,并且需要改为for去清理它们,注意当我们释放命令池时,命令缓冲区已为我们释放,所以命令缓冲区无需额外清理操作

我们还要记录currentFrame索引,修改drawFrame使用这三个数组的currentFrame索引的对象

我们还应该每次都前进到下一帧

currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;

多帧渲染是一种计算机图形渲染技术,通过同时渲染多个图像帧来提高渲染速度和图像质量。 传统的单帧渲染方式是依次渲染每个图像帧,而多帧渲染则同时处理多个帧。这是通过同时使用多个处理器核心或者显卡的多个计算单元来实现的。 在多帧渲染中,每个帧会被分成多个小部分,每部分由一个独立的计算单元渲染。这些计算单元可以并行地工作,同时渲染不同的部分图像帧。通过充分利用硬件并行计算的优势,多帧渲染大大加快了整个渲染过程。 除了加快渲染速度,多帧渲染还可以提高图像质量。通过使用多个计算单元同时渲染不同的帧,可以在渲染过程中应用更复杂的算法和效果。例如,可以通过在多个帧中采样不同的光线路径来实现更真实的全局光照效果,或者通过从多个帧中合成不同的抗锯齿样本来减少图像锯齿。 尽管多帧渲染可以提供更快的渲染速度和更高的图像质量,但也存在一些挑战。首先,多帧渲染需要强大的硬件支持,例如具有多个计算单元或者核心的处理器或显卡。此外,多帧渲染还需要高效的任务调度和数据同步机制,以确保各个计算单元之间的协调和合作。 总之,多帧渲染是一种利用并行计算来提高渲染速度和图像质量的技术。通过同时渲染多个图像帧并应用复杂的算法和效果,多帧渲染为计算机图形渲染带来了更高的性能和逼真度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值