Aqoole_Hateenaの技術日記

vulkan+raytraceで色々描いてます

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(3)


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(3)


vkWaitForFences - Wait for one or more fences to become signaled

とあるので、この例ではvkQueueSubmit()で送られたfenceに信号が送られるまで待つ。

vkQueuePresentKHR()

vkQueuePresentKHR(3)


vkQueuePresentKHR - Queue an image for presentation

command bufferで登録されたcommandがすべて実行完了していることからimageが出来上がっているので、準備が完了しているnext imageを描画する。