我不太确定我想做的是否正确,但是关于Vulkan的文档并不多,所以我想出了这一点。如果我在设计方式上完全不对,也请纠正我!
在我的Vulkan应用程序中,我有三个不同的队列
我正在尝试实现异步模型加载,这意味着所有顶点,纹理等均加载到单独的线程中。当模型完成加载后,绘制命令缓冲区将由主线程更新,以便呈现新加载的对象。
一切正常,因为应该期望我从Vulkan验证层收到警告:
读取错误:线程...中同时使用了VkQueue类型的对象。
如果我逐步执行调试器,则可以看到以下几行受到影响:
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
和
//main Loop
vkQueueSubmit(graphicsQueue, ...) //draw command buffer
我打印了//Background loading thread
vkQueueSubmit(transferQueue, ...)//copy vertex command buffer
和graphicsQueue
的地址,发现它们是相同的(相同的地址),因此看来我的图形卡仅支持单个队列。因此,现在我尝试使用信号量将对transferQueue
的调用同步:
vkQueueSubmit
不幸的是,错误仍然相同。
所以我的问题是:如何正确同步对submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &queueSemaphore;
的呼叫?
答案 0 :(得分:6)
您太想这个问题了。
您具有操作对象的功能。并且您希望能够从同一对象的多个线程中调用该函数。但是通过该函数 操作该对象不是线程安全的。因此,使线程安全是您的责任。
无论是Vulkan对象还是常规C / C ++类型,解决方案都是相同的:您使用互斥锁。如果两个队列是同一队列,则必须在每个线程调用vkQueueSubmit
的站点周围锁定一个互斥锁。
别让Vulkan的复杂性分散您对简单解决方案的注意力;)
尽管如此,如果您的图形和传输队列相同,那么最好找到一种方法来重组代码,以便您不尝试提交不同线程上的不同批次。也就是说,使您的代码更适应硬件。
如果GPU提供了不同的传输队列,那么您的传输线程将生成传输CB并将其提交(以及将适当的信号量传递给图形提交线程,以便它可以在正确的时间等待)。如果GPU没有不同的传输队列,那么您仍然可以在其他线程上生成传输CB。但是,您可以传递命令缓冲区而不是将信号量传递给图形线程。这些将与下一批图形一起提交;图形提交线程还可以在传输和图形操作之间插入适当的同步。