由于我在其他地方没有找到太多有关计算着色器的信息,所以我会在这里询问。
如何检测/查看计算着色器是否已完成其工作? 或者假设主线程等待着色器完成?
如果是这种情况,有没有办法让主线程不等待着色器,而只在着色器中添加一个标志?
自从提出这个问题以来已经有一段时间了,但我会为将来寻找的人添加答案!
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();
}
}
}