To create a render pass that runs a compute shaderA program that runs on the GPU. More info
See in Glossary, do the following:
To check if a platform supports compute shaders, use the SystemInfo.supportsComputeShaders
API
When you create a ScriptableRenderPass
, do the following:
AddComputePass
instead of AddRasterRenderPass
.ComputeGraphContext
instead of RasterGraphContext
.For example:
class ComputePass : ScriptableRenderPass
{
...
public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer contextData)
{
...
// Use AddComputePass instead of AddRasterRenderPass.
using (var builder = renderGraph.AddComputePass("MyComputePass", out PassData data))
{
...
// Use ComputeGraphContext instead of RasterGraphContext.
builder.SetRenderFunc((PassData data, ComputeGraphContext context) => ExecutePass(data, context));
...
}
}
}
To create a buffer the compute shader outputs to, follow these steps:
Create a graphics buffer, then add a handle to it in your pass data.
// Declare an output buffer
public GraphicsBuffer outputBuffer;
// Add a handle to the output buffer in your pass data
class PassData
{
public BufferHandle output;
}
// Create the buffer in the render pass constructor
public ComputePass(ComputeShader computeShader)
{
// Create the output buffer as a structured buffer
// Create the buffer with a length of 5 integers, so the compute shader can output 5 values.
outputBuffer = new GraphicsBuffer(GraphicsBuffer.Target.Structured, 5, sizeof(int));
}
Use the ImportBuffer
render graph API to convert the buffer to a handle the render graph system can use, then set the BufferHandle
field in the pass data. For example:
BufferHandle outputHandleRG = renderGraph.ImportBuffer(outputBuffer);
passData.output = outputHandleRG;
Use the UseBuffer
method to set the buffer as a writeable buffer in the render graph system.
builder.UseBuffer(passData.output, AccessFlags.Write);
Follow these steps:
Pass the compute shader to the render pass. For example, in a ScriptableRendererFeature
class, expose a ComputeShader
property, then pass the compute shader into the render pass class.
Add a ComputeShader
field to your pass data, and set it to the compute shader. For example:
// Add a `ComputeShader` field to your pass data
class PassData
{
...
public ComputeShader computeShader;
}
// Set the `ComputeShader` field to the compute shader
passData.computeShader = yourComputeShader;
In your SetRenderFunc
method, use the SetComputeBufferParam
API to attach the buffer to the compute shader. For example:
// The first parameter is the compute shader
// The second parameter is the function that uses the buffer
// The third parameter is the StructuredBuffer output variable to attach the buffer to
// The fourth parameter is the handle to the output buffer
context.cmd.SetComputeBufferParam(passData.computeShader, passData.computeShader.FindKernel("Main"), "outputData", passData.output);
Use the DispatchCompute
API to execute the compute shader.
context.cmd.DispatchCompute(passData.computeShader, passData.computeShader.FindKernel("CSMain"), 1, 1, 1);
To fetch the data from the output buffer, use the GraphicsBuffer.GetData
API.
You can only fetch the data after the render pass executes and the compute shader finishes running.
For example:
// Create an array to store the output data
outputData = new int[5];
// Copy the output data from the output buffer to the array
outputBuffer.GetData(outputData);
For a full example, refer to the example called Compute in the render graph system URP package samples.