Lesson 111 +10 XP

Compute Shaders

Compute Shaders

Compute Shaders are program kernels that execute computations on the GPU, completely bypassing the rendering pipeline.

Shader HLSL Syntax

Create a compute shader (ComputeShader.compute):

#pragma kernel CSMain

// Read/Write Texture
RWTexture2D<float4> Result;

[numthreads(8, 8, 1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{
    Result[id.xy] = float4(id.x / 512.0, id.y / 512.0, 0.0, 1.0);
}
  • [numthreads(8,8,1)]: Defines the thread block size. Here, a block processes 64 pixels.

Dispatching from C#

Instantiate a RenderTexture with random write permissions, and launch the kernel:

using UnityEngine;

public class ComputeRunner : MonoBehaviour
{
    public ComputeShader computeShader;
    private RenderTexture _tex;

    void Start()
    {
        _tex = new RenderTexture(512, 512, 0);
        _tex.enableRandomWrite = true;
        _tex.Create();

        int kernelIndex = computeShader.FindKernel("CSMain");
        computeShader.SetTexture(kernelIndex, "Result", _tex);

        // Run shader: (512 / 8) groups = 64 groups in X and Y
        computeShader.Dispatch(kernelIndex, 64, 64, 1);
    }
}

ComputeBuffer

Use a ComputeBuffer to pass arrays of raw structures to and from a compute shader:

// Define and populate buffer
ComputeBuffer buffer = new ComputeBuffer(dataCount, stride);
buffer.SetData(myDataArray);

// Pass to shader
computeShader.SetBuffer(kernelIndex, "myBufferName", buffer);

// Release GPU memory when finished
buffer.Release();

TL;DR

  • Compute shaders execute code in parallel directly on the GPU.
  • Output results to a RenderTexture or read/write with a ComputeBuffer.
  • Always call Release() on ComputeBuffers to avoid GPU memory leaks.