这三种同步机制在 Vulkan 中有着不同的用途和特点:

VkSemaphore - GPU 与 GPU 之间的同步

  • 主要用于队列操作之间的同步(GPU 工作同步)
  • 典型用例:渲染完成后再进行显示
// 示例:等待渲染完成后再显示
VkSubmitInfo submitInfo = {};
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &renderFinishedSemaphore;
 
VkPresentInfoKHR presentInfo = {};
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &renderFinishedSemaphore;

VkFence - CPU 与 GPU 之间的同步

  • 用于让 CPU 等待 GPU 操作完成
  • 可以在 CPU 端被查询和等待
  • 典型用例:确保资源不会在 GPU 使用时被 CPU 修改
// 示例:等待命令缓冲执行完成
vkQueueSubmit(queue, 1, &submitInfo, fence);
vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &fence);

VkEvent - GPU 内部的细粒度同步

  • 用于命令缓冲内部或命令缓冲之间的精确同步
  • 可以在 CPU 端设置和重置
  • 典型用例:在管线中的特定点同步操作
// 在命令缓冲中使用Event
vkCmdSetEvent(commandBuffer, event, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
vkCmdWaitEvents(commandBuffer, 1, &event,
    VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,  // srcStageMask
    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,     // dstStageMask
    0, nullptr,    // memoryBarriers
    0, nullptr,    // bufferMemoryBarriers
    0, nullptr);   // imageMemoryBarriers

选择建议

  1. 需要 GPU 队列间同步时,用 Semaphore
  2. 需要 CPU 等待 GPU 时,用 Fence
  3. 需要精细的 GPU 命令同步时,用 Event