Unity Detect 计算着色器完成

问题描述 投票:0回答:1

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

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

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

unity-game-engine shader
1个回答
0
投票

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

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

自从提出这个问题以来,Unity 已通过

CommandBuffer
接口实现了“异步计算”支持,以及用于 GPU 同步的
GraphicsFence
接口。

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

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

A

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

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();
        }
   }
}
© www.soinside.com 2019 - 2024. All rights reserved.