ドキュメント

Unity Engine

Unity Engine

Write to and read output data from a compute shader in URP

Create a render pass that writes to and reads output data from a compute shader.
読み終わるまでの所要時間 3 分最終更新 1ヶ月前

To create a render pass that writes to and reads output data from a compute shader, do the following:
  1. Set up the render pass to use a compute shader.
  2. Add an output buffer.
  3. Pass in and execute the compute shader.
  4. Get the output data from the output buffer.
To check if a platform supports compute shaders, use the
SystemInfo.supportsComputeShaders
API

Set up the render pass to use a compute shader

When you create a
ScriptableRenderPass
, do the following:
  1. Use
    AddComputePass
    instead of
    AddRasterRenderPass
    .
  2. Use
    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(static (PassData data, ComputeGraphContext context) => ExecutePass(data, context)); ... } }}

Add an output buffer

To create a buffer the compute shader outputs to, follow these steps:
  1. Inside
    RecordRenderGraph
    , create a graphics buffer using
    CreateBuffer
    and keep the handle. For example:
    public override void RecordRenderGraph(RenderGraph renderGraph, ContextContainer frameData){ // Create the output buffer as a structured buffer of 20 ints BufferDesc desc = new BufferDesc { name = "OutputBuffer", count = 20, stride = sizeof(int), target = GraphicsBuffer.Target.Structured }; m_OutputBufferHandle = renderGraph.CreateBuffer(desc); // Add the compute pass using (var builder = renderGraph.AddComputePass("ComputePass", out PassData passData)) { // Set the pass data passData.output = m_OutputBufferHandle; }}
  2. Use the
    UseBuffer
    method to declare the buffer as an output of this pass in the render graph system. For example:
    builder.UseBuffer(passData.output, AccessFlags.Write);

Pass in and execute the compute shader

Follow these steps:
  1. 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.
  2. Add a
    ComputeShader
    field to your pass data, and set it to the compute shader. For example:
    // Add a `ComputeShader` field to your pass dataclass PassData{ ... public ComputeShader computeShader;}// Set the `ComputeShader` field to the compute shaderpassData.computeShader = yourComputeShader;
  3. 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 buffercontext.commandBuffer.SetComputeBufferParam(passData.computeShader, passData.computeShader.FindKernel("Main"), "outputData", passData.output);
  4. Use the
    DispatchCompute
    API to execute the compute shader.
    context.commandBuffer.DispatchCompute(passData.computeShader, passData.computeShader.FindKernel("Main"), 1, 1, 1);

Get the output data from the output buffer

To fetch the data from the output buffer, add a pass to read the data back from the GPU to the CPU using the
RequestAsyncReadback
API.
You can only fetch the data after the render pass executes and the compute shader finishes running.
For example:
  1. Create data for the pass that will read the buffer back.
    // Data container for the pass that reads back from the GPUclass ReadbackPassData{ // The buffer to read back from public BufferHandle processedDataBuffer;}
  2. Provide the output buffer handle to the pass.
    passData.processedDataBuffer = m_OutputBufferHandle;
  3. Give the pass read access to the buffer.
    // Declare read access to the bufferbuilder.UseBuffer(passData.processedDataBuffer, AccessFlags.Read);
  4. Request asynchronous readback with the
    RequestAsyncReadback
    API.
    context.commandBuffer.RequestAsyncReadback(passData.processedDataBuffer, (AsyncGPUReadbackRequest request) =>{ // Get the data int result = request.GetData<int>();})

Example

For a full example, refer to the example called Compute in the render graph system URP package samples.

Additional resources