drawFrame 函数用于执行下面的操作:
• 从交换链获取一张图像
• 对帧缓冲附着执行指令缓冲中的渲染指令
• 返回渲染后的图像到交换链进行呈现操作
上面这些操作每一个都是通过一个函数调用设置的, 但每个操作的实际
执行却是异步进行的。
函数调用会在操作实际结束前返回,并且操作的实
际执行顺序也是不确定的。而我们需要操作的执行能按照一定的顺序,所
以就需要进行同步操作。
栅栏 (fence) 和信号量 (semaphore) 的不同之处是,我们可以通过调
用 vkWaitForFences 函数 查 询 栅 栏 (fence) 的状 态,但 不能 查 询 信号 量(semaphore) 的状态。
通常,我们使用栅栏 (fence) 来对应用程序本身和渲
染操作进行同步。使用信号量 (semaphore) 来对一个指令队列内的操作或
多个不同指令队列的操作进行同步。
我们需要两个信号量,一个信号量发出图像已经被获取,可
以开始渲染的信号;一个信号量发出渲染已经结果,可以开始呈现的信号。
VkSemaphore imageAvailableSemaphore ;
VkSemaphore renderFinishedSemaphore ;
信号量 (semaphore) 需要我们在应用程序结束前,所有它所同步的指
令执行结束后,对它进行清除:
vkDestroySemaphore ( d e v i c e , renderFinishedSemaphore ,nullptr ) ;
vkDestroySemaphore ( d e v i c e , imageAvailableSemaphore ,nullptr ) ;
VkSubmitInfo 结构体的 waitSemaphoreCount、pWaitSemaphores 和
pWaitDstStageMask 成员变量用于指定队列开始执行前需要等待的信号量,
以及需要等待的管线阶段。
commandBufferCount 和 pCommandBuffers 成员变量用于指定实际被
提交执行的指令缓冲对象。
signalSemaphoreCount 和 pSignalSemaphores 成员变量用于指定在指
令缓冲执行结束后发出信号的信号量对象。
在这里,我们使用 renderFin-
ishedSemaphore 信号量对象在指令缓冲执行结束后发出信号。
VkSemaphore sig nal Sem ap ho r es [ ] = { renderFinishedSemaphore } ;
s u b m i t I n f o . signalSemaphoreCount = 1 ;
s u b m i t I n f o . pSignalSemaphores = s ig na l S e m a p h o r e s ;
渲染操作执行后,我们需要将渲染的图像返回给交换链进行呈现操作。
我们在 drawFrame 函数的尾部通过 VkPresentInfoKHR 结构体来配置呈现
信息:
VkPresentInfoKHR p r e s e n t I n f o = { } ;
p r e s e n t I n f o . sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
p r e s e n t I n f o . waitSemaphoreCount = 1 ;
p r e s e n t I n f o . pWaitSemaphores = s i gn a l S e m a p h o r e s ;
waitSemaphoreCount 和 pWaitSemaphores 成员变量用于指定开始呈
现操作需要等待的信号量。
接着,我们指定了用于呈现图像的交换链,以及需要呈现的图像在交
换链中的索引。
VkSwapchainKHR swapChains [ ] = {swapChain } ;
p r e s e n t I n f o . swapchainCount = 1 ;
p r e s e n t I n f o . pSwapchains = swapChains ;
p r e s e n t I n f o . pImageIndic es = &imageIndex ;
我们可以通过 pResults 成员变量获取每个交换链的呈现操作是否成功
的信息。
调用 vkQueuePresentKHR 函数可以请求交换链进行图像呈现操作。