Unity Detect Compute 着色器完成

Pat*_*lin 5 shader unity-game-engine

由于我在其他地方没有找到太多关于计算着色器的信息,所以我会在这里问。

如何检测/查看计算着色器是否已完成工作?还是假设主线程等待着色器完成?

如果是这种情况,有没有办法让主线程不等待着色器而只在着色器中有一个标志?

And*_*tow 0

自从提出这个问题以来已经有一段时间了,但我会为将来寻找的人添加答案!

ComputeShader.Dispatch是同步的,并且会阻塞 CPU,直到计算着色器完成运行。这通常非常快,除非您的计算着色器正在执行大量工作,在这种情况下您可能需要使用不同的接口。

自从提出这个问题以来,Unity 已经通过CommandBuffer接口实现了“异步计算”支持,以及GraphicsFence用于 GPU 同步的接口。

  • Graphics.ExecuteCommandBufferAsync允许CommandBuffers在支持它的平台上异步执行,如果需要则回退到同步执行。

  • GraphicsFence提供一个在 GPU 上创建名为“fences”的接口。这些本质上是当 GPU 队列的执行进度超过它们添加点时触发的信号。通常,您会使用栅栏来指定不同 GPU 计算阶段之间的依赖关系,其中一个队列将创建栅栏,另一个队列将等待它 - 例如,一个异步计算队列可能依赖于较早队列的结果,并且可以等待栅栏,确保在执行依赖队列之前所需的数据已准备好。

GraphicsFence也可以使用 来在 CPU 上GraphicsFence.passed查询A。这是一个相当原始的界面,但它在这里完成了工作。结合使用这两者,可以像这样实现所需的行为。

class MyAsyncComputeTest: MonoBehaviour 
{
   private GraphicsFence graphicsFence;
   private CommandBuffer commandBuffer;
   private ComputeShader computeShader;
   
   private void Start()
   {
        // Create a new CommandBuffer.
        // The CommandBuffer acts as a queue of commands to run on the GPU.
        commandBuffer = new CommandBuffer();

        // Configure the CommandBuffer to run asynchronously.
        commandBuffer.SetExecutionFlags(CommandBufferExecutionFlags.AsyncCompute);

        // Enqueue a command to dispatch the compute shader.
        commandBuffer.DispatchCompute(computeShader, 0, 1, 1, 1);

        // Create a graphics fence. CommandBuffers are executed in order,
        // so this fence will be passed when the DispatchCompute has finished.
        graphicsFence = commandBuffer.CreateGraphicsFence(GraphicsFenceType.CPUSynchronization, SynchronisationStageFlags.ComputeProcessing);

        // Finally, execute the CommandBuffer asynchronously.
        Graphics.ExecuteCommandBufferAsync(commandBuffer, ComputeQueueType.Default);
   }

   private void Update()
   {
        // The CommandBuffer created in `Start` is running asynchronously.
        // Check if the GraphicsFence created within it has passed.
        if (graphicsFence.passed)
        {
            // The graphics fence has passed and the compute shader has finished running.
            commandBuffer.Dispose();
        }
   }
}
Run Code Online (Sandbox Code Playgroud)