首页 > 解决方案 > 使用栅栏清理命令缓冲区并同时同步交换链图像

问题描述

假设我有一个由n图像组成的交换链,并且我允许k“飞行中的帧”。我通过一组信号量和栅栏确保正确同步vkAcquireNextImageKHR,就像本教程中所做的那样:vkQueueSubmitvkQueuePresentKHRimageAvailableSemaphorerenderFinishedSemaphoreimageInFlight

imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
    renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
    inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);

需要栅栏来确保在 GPU 完成使用相应图像之前我们不会再次使用信号量。所以,这个栅栏需要在vkQueueSubmit.

另一方面,我正在创建独立于“飞行中的帧”的命令缓冲区。它们是“一次性提交”命令缓冲区。因此,一旦提交,我会将它们添加到“待删除”列表中。我需要知道 GPU 何时完成执行此列表中的命令缓冲区。

但我不能在vkQueueSubmit. 我怎么解决这个问题?

标签: graphicsvulkan

解决方案


我允许k“飞行中的帧”

嗯,这就是你的答案。将为“帧”提供命令缓冲区的每个线程都应该有多个k命令缓冲区。他们应该以环形缓冲区的方式使用它们。这些命令缓冲区应该从临时分配池中创建。当他们从环形缓冲区中选择最近最少使用的 CB 时,他们应该在记录之前将其重置。

您确保没有线程尝试重置仍在使用的 CB,方法是在过去的第 th 帧完成之前(使用栅栏)不开始下一帧的任何工作。k

如果由于某种原因你绝对不能告诉你的线程k前面是什么,你仍然必须告诉他们一些事情。当你开始处理线程时,你需要告诉他们还有多少帧还在战斗中。这允许他们根据这个帧数检查他们的环形缓冲区的大小。如果环形缓冲区中的元素数小于帧数,则环形缓冲区中最旧的 CB 未使用。否则,它将不得不从池中分配一个新的 CB 并将其推入环形缓冲区。


推荐阅读