Vulkan之Semaphore

semaphore用于 同步不同的queue之间,或者同一个queue不同的submission之间的执行顺序。

一般来说semaphore解决的是队列中的渲染和呈现两个任务的同步的,渲染和呈现都是以命令的形式提交到队列中的,由于vulkan的多线程特性,这两者不一定谁先执行,但是我们的逻辑又得要求先要渲染完才能去呈现,所以引入了信号量来解决这个问题。

类似于fence,semaphore也有signaled和unsignaled的状态之分,但是semaphore,我们没有办法显式的设置,重置和等待它。

在GPU的draw任务中,主要做下面的三件事:
• 从交换链获取一张图像
• 对帧缓冲附着执行指令缓冲中的渲染指令
• 返回渲染后的图像到交换链进行呈现操作

所以我们需要两个semaphore,一个信号量发出图像已经被获取,可以开始渲染的信号;一个信号量发出渲染已经结束,可以开始呈现的信号。

首先创建两个信号量

1
2
3
4
5
VkSemaphore imageAvailableSemaphore;
VkSemaphore renderFinishedSemaphore;

vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphore);
vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore);

然后在获取图像时,当图像能够获取到后, 会设置imageAvailableSemaphore

1
VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);

然后我们在vkQueueSubmit的时候,会设置需要等待的semaphore,以及vkQueueSubmit完成后需要设置的semaphore

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
VkSubmitInfo submitInfo{};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;

VkSemaphore waitSemaphores[] = { imageAvailableSemaphore };
VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = waitSemaphores; // 需要等待的semaphore
submitInfo.pWaitDstStageMask = waitStages;

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

VkSemaphore signalSemaphores[] = { renderFinishedSemaphore};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = signalSemaphores; // 需要设置的semaphore

vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]);

同样在prensent的时候,也有需要等待的semaphore,就是上面渲染命令完成后设置的信号量renderFinishedSemaphore

1
2
3
4
5
6
7
8
9
10
11
12
13
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;

result = vkQueuePresentKHR(presentQueue, &presentInfo);

显示 Gitment 评论