Vulkan异步模型加载

时间:2018-07-31 15:01:40

标签: c++ c vulkan

我不太确定我想做的是否正确,但是关于Vulkan的文档并不多,所以我想出了这一点。如果我在设计方式上完全不对,也请纠正我!

在我的Vulkan应用程序中,我有三个不同的队列

  • graphicsQueue:用于提交图形命令缓冲区
  • presentQueue:用于显示完成的图像
  • transferQueue:用于复制缓冲区,纹理等。

我正在尝试实现异步模型加载,这意味着所有顶点,纹理等均加载到单独的线程中。当模型完成加载后,绘制命令缓冲区将由主线程更新,以便呈现新加载的对象。

一切正常,因为应该期望我从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; 的呼叫?

1 个答案:

答案 0 :(得分:6)

您太想这个问题了。

您具有操作对象的功能。并且您希望能够从同一对象的多个线程中调用该函数。但是通过该函数 操作该对象不是线程安全的。因此,使线程安全是您的责任。

无论是Vulkan对象还是常规C / C ++类型,解决方案都是相同的:您使用互斥锁。如果两个队列是同一队列,则必须在每个线程调用vkQueueSubmit的站点周围锁定一个互斥锁。

别让Vulkan的复杂性分散您对简单解决方案的注意力;)

尽管如此,如果您的图形和传输队列相同,那么最好找到一种方法来重组代码,以便您尝试提交不同线程上的不同批次。也就是说,使您的代码更适应硬件。

如果GPU提供了不同的传输队列,那么您的传输线程将生成传输CB并将其提交(以及将适当的信号量传递给图形提交线程,以便它可以在正确的时间等待)。如果GPU没有不同的传输队列,那么您仍然可以在其他线程上生成传输CB。但是,您可以传递命令缓冲区而不是将信号量传递给图形线程。这些将与下一批图形一起提交;图形提交线程还可以在传输和图形操作之间插入适当的同步。