main loopのsynchronization考察
サンプルコード
git hubで公開されている、android + vulkanでのsynchronizationの部分について考察してみた。
android-vulkan-tutorials/tutorial05_triangle at master · googlesamples/android-vulkan-tutorials · GitHub
main loopの関数は以下
bool VulkanDrawFrame(void) { uint32_t nextIndex; // Get the framebuffer index we should draw in CALL_VK(vkAcquireNextImageKHR(device.device_, swapchain.swapchain_, UINT64_MAX, render.semaphore_, VK_NULL_HANDLE, &nextIndex)); CALL_VK(vkResetFences(device.device_, 1, &render.fence_)); VkPipelineStageFlags waitStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; VkSubmitInfo submit_info = {.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .pNext = nullptr, .waitSemaphoreCount = 1, .pWaitSemaphores = &render.semaphore_, .pWaitDstStageMask = &waitStageMask, .commandBufferCount = 1, .pCommandBuffers = &render.cmdBuffer_[nextIndex], .signalSemaphoreCount = 0, .pSignalSemaphores = nullptr}; CALL_VK(vkQueueSubmit(device.queues_[0], 1, &submit_info, render.fence_)); CALL_VK( vkWaitForFences(device.device_, 1, &render.fence_, VK_TRUE, 100000000)); LOGI("Drawing frames......"); VkResult result; VkPresentInfoKHR presentInfo{ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, .pNext = nullptr, .waitSemaphoreCount = 0, .pWaitSemaphores = nullptr, .swapchainCount = 1, .pSwapchains = &swapchain.swapchain_, .pImageIndices = &nextIndex, .pResults = &result, }; vkQueuePresentKHR(device.queues_[0], &presentInfo); return true; }
vkAcquireNextImageKHR()
次の描画可能なimageのindexを取得する関数。
vkAcquireNextImageKHR(3)
semaphore is VK_NULL_HANDLE or a semaphore to signal.
fence is VK_NULL_HANDLE or a fence to signal.
If semaphore is not VK_NULL_HANDLE it must be unsignaled
If semaphore is not VK_NULL_HANDLE it must not have any uncompleted signal or wait operations pending
空のsemaphoreを登録するべきで、すでに何かを待っているsemaphoreは登録できない。
vkResetFences()
vkResetFences(3)
fenceをリセットする。
何かを待っているfenceに対しては実行できない。
vkQueueSubmit()
vkQueueSubmit - Submits a sequence of semaphores or command buffers to a queue
とあるので、semaphoresと実行するcommand bufferを送る。
コマンドバッファーのindexの特定にnextimage indexが必要で、これは最初のvkAcquireNextImageKHR()で取得する。
fence is an optional handle to a fence to be signaled once all submitted command buffers have completed execution. If fence is not VK_NULL_HANDLE, it defines a fence signal operation.
とあるので、ここでfenceのパラメータを入力しておくと、ここで送ったcommand bufferがすべて実行された場合にfenceに信号が送られる。
vkWaitForFences()
vkWaitForFences - Wait for one or more fences to become signaled
とあるので、この例ではvkQueueSubmit()で送られたfenceに信号が送られるまで待つ。
vkQueuePresentKHR()
vkQueuePresentKHR - Queue an image for presentation
command bufferで登録されたcommandがすべて実行完了していることからimageが出来上がっているので、準備が完了しているnext imageを描画する。