首页 > 解决方案 > 来自子 CPU 线程的 Vulkan Compute 调度

问题描述

Vulkan Compute 可以从子 CPU 线程分派,还是必须从主线程分派?我认为这不可能在 Unity 中从子线程调度计算着色器,我想知道它是否可以在虚幻引擎中完成。

标签: multithreadingunreal-engine4vulkancompute-shader

解决方案


这取决于您所说的“调度”和“主线程”是什么意思。

vkCmdDispatch,正如 " Cmd" 前缀所暗示的,将命令放入命令缓冲区。这可以在任何线程上调用,只要VkCommandBuffer对象不会同时vkCmd调用其他函数(通常,您为单个线程保留特定的命令缓冲区)。因此,根据一个定义,您可以从其他线程“分派”计算操作。

当然,在命令缓冲区中记录命令实际上并没有做任何事情。只有当您通过vkQueueSubmit. 就像vkCmdDispatch,您在哪个线程上调用该函数并不重要。但是,就像 一样vkCmdDispatch,阻止多个线程同时访问同一个对象确实很重要。VkQueue

现在,您不必为此使用单个线程VkQueue;您可以锁定VkQueue某种互斥锁,以便一次只有一个线程可以拥有它。因此,创建 CB 的线程可以提交自己的工作。

但是,忽略任务通常需要按顺序插入队列的事实(一个任务可能会生成一些图形任务需要等待的计算数据,因此图形任务 CB必须在计算 CB 之后),有一个更大的问题。vkQueueSubmit需要很长时间。如果你看一下这个函数,它可以插入任意数量的 CB,并且它具有多个批次的能力,每个批次都由信号量和栅栏保护以进行同步。因此,强烈建议您尽可能少vkQueueSubmit地调用,因为每次调用都会产生一定数量的开销,这与您排队的 CB 数量无关。

规范本身甚至对此有警告。

因此,构建应用程序的典型方式是将任务分配给可用的 CPU 线程,然后这些任务构建命令缓冲区。一个特定的线程将被指定为队列的所有者。该线程可能会执行一些 CB 构建,但一旦完成,它将等待其他任务完成并从其他线程收集所有 CB。收集后,该线程会将vkQueueSubmit它们分成适当的批次。

您可以将该线程称为“主线程”,但 Vulkan 本身并不真正关心哪个线程“拥有”队列。它当然不必是您进程的初始线程。


推荐阅读