毕竟,能够并行构建命令缓冲区是Vulkan的卖点之一.
规范(5.1命令池)(强调我的):
命令池是应用程序同步的,这意味着不能在多个线程中同时使用命令池.这包括通过记录命令在从池分配的任何命令缓冲区上使用,以及分配,释放和重置命令缓冲区或池本身的操作.
当涉及到并行录制时,这种命令池的全部目的是不是就这样了?如果你打算并行记录,那么你最好为每个线程都有一个单独的池,不是吗?
如果你预先记录从同一个池(在一个线程中)分配的命令缓冲区然后并行执行它们,我会理解它.这具有摊销资源创建成本以及并行执行的优势.但是,并行记录和命令池似乎不太匹配.
我个人不知道为什么你不会只是预先录制一切.那么为什么需要并行构建命令缓冲区呢?那么你是否真的必须为每个线程使用一个池?
如果你打算并行记录,那么你最好为每个线程都有一个单独的池,不是吗?
我没有看到每个线程有一个单独的池"在并行记录时会杀死命令池的全部目的".实际上,它有很大帮助,因为每个线程都可以根据需要管理自己的命令池.
考虑描述符池和命令池之间的结构差异.使用描述符池,您基本上可以准确地告诉它将从中分配什么.VkDescriptorPoolCreateInfo提供详细信息,允许实现预先分配您将为每个池使用多少内存.而且你不能从描述符池中分配更多.
相比之下,VkCommandPoolCreateInfo包含......没有.哦,你告诉它命令缓冲区是主要的还是辅助的.你说是命令缓冲区是经常重置还是持久化.还有其他一些事情.但除此之外,你对命令缓冲区的内容一无所知.您甚至不会提供有关您将分配多少缓冲区的信息.
描述符池旨在被修复:根据需要分配,但最多为在施工时设置的数量.命令缓冲区旨在非常动态:根据您的特定用例需要进行分配.
可以把它想象成每个池都有自己的malloc/free.由于用户被迫同步对池及其缓冲区的访问,这意味着vkCmd*在分配内存时,不需要每个函数都这样做.这使得命令构建更快.这有助于线程化.当线程决定重置其命令池时,它不必锁定任何互斥锁或任何其他此类东西来执行此操作.
每个线程有一个命令池在概念上没有任何错误.实际上,每个线程有两个(双缓冲)更有意义.
我个人不知道为什么你不会只是预先录制一切.
因为你没有制作静态技术演示.
我想这来自缺乏经验,但我想象并行记录看起来像"线程2-N记录辅助命令缓冲区,线程1在一个主命令缓冲区中调用所有这些",在这种情况下只有一个命令每个线程缓冲区.这就是为什么我说它杀死命令池的目的,因为你只为每个池进行一次分配.
这当然是并行记录命令缓冲区的可行形式.但是有两件事你错过了.
虽然这肯定是平行录音的一种形式,但它并不是唯一的一种.如果你正在进行延迟渲染,那么构建光照通道的CB的线程将比其中一个负责(几部分)几何传递的线程更快完成其工作.因此,设计良好的多线程系统必须根据需要将工作分配给线程,而不是基于某些固定的东西排列.因此,单个线程通常最终会构建多个命令缓冲区.
即使不是这种情况,你也会忘记缓冲.当需要为下一帧构建CB时,您不能只覆盖现有的CB.毕竟,他们可能还在排队做工作.所以每个线程至少需要两个 CB; 当前正在执行的那个和当前正在构建的那个.
即使不是这种情况,命令池也会分配与CB关联的所有内存.有一个原因,我将它们类比化malloc/free.即使您只使用具有特定池的单个CB,这个CB的分配(可能由于任何vkCmd*功能而发生)永远不必与另一个线程同步这一事实是一件好事.
所以不,这不会以任何方式抑制使用多个线程来构建CB的能力.