Unity Version: 2021

Building a custom renderer for Unity - Command Buffers

Command Buffers are a concept that once you understand what they are and what they can do, you have more or less figured out what the SRP is all about. You create a Command Buffer that lets you queue up instructions for the GPU . An example of this is in the following code which is creating a RenderTexture and getting it ready to be used for the directional Shadow Atlas.

CommandBuffer commandBuffer = new CommandBuffer();

commandBuffer.GetTemporaryRT(dirShadowAtlasId, atlasSize, atlasSize, 32,
    FilterMode.Bilinear, RenderTextureFormat.Shadowmap);

commandBuffer.SetRenderTarget(dirShadowAtlasId,
    RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);

commandBuffer.ClearRenderTarget(true, false, Color.clear);
context.ExecuteCommandBuffer(commandBuffer);
commandBuffer.Clear();

The actual behind the scenes contents of the code is a series of GPU instructions that are then copied and scheduled in the ScriptableRenderContext by the line context.ExecuteCommandBuffer(commandBuffer);. The buffer then needs to be manually cleared so it can be reused, typically you would create the buffer at a higher level than demonstrated here I just wanted to add it here for clarity.

The ScriptableRenderContext will execute all instructions when context.Submit() is called however it is possible to immediately execute a Command Buffer by calling Graphics.ExecuteCommandBuffer but this will take place outside of the rendering pipeline.

You can also use Command Buffers to pass variables from your C# scripts to your Shaders. The code block from earlier was creating a render texture but in order to render shadows there are lots of configuration options we might want to pass down to the shader level such as, the amount of cascades that should be used, the size of the atlas, how far should shadows be rendered, etc. Command Buffers allow you to pass this information down with a call like buffer.SetGlobalInt(Shader.PropertyToID("_CascadeCount"), 2)!

A cool feature of Command Buffers is that you can add in handy debugging markers so that in the Frame Debugger and Profiler you can more easily understand what is going on when the frame is in progress of being drawn. I had an issue at one point where I was drawing my directional shadow atlas and then it was being immediately cleared by a different buffer which meant there were no shadows rendered. Because of these markers it was easier to see and I could follow the logic of the how the frame was executing to see where the issue was.

custom shadow buffer marker reading 'My custom shadow buffer'

If you want to learn more about Command Buffers and how they fit into the SRPs then I recommend the Scriptable Render Pipeline Fundamentals chapter of the Unity Docs.

Next time

Batching in the SRP!

Related Posts/Links