Custom SRP with Multiple Render Targets in Unity 2022

Hi,

I’ve upgraded from Unity 2021.3.40f1 to 2022.3.38f1. Everything works the same except for the frame debugger. When I select a drawcall in the frame debugger that is rendering to the MRT the details do not appear and I get the following errors -

GUI Error: Invalid GUILayout state in FrameDebuggerWindow view. Verify that all layout Begin/End calls match
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

IndexOutOfRangeException: Index was outside the bounds of the array.
UnityEditorInternal.FrameDebuggerInternal.FrameDebuggerEventDetailsView.DrawRenderTargetToolbar () (at <043e10ec4a0f4999a2729072194b9cfe>:0)
UnityEditorInternal.FrameDebuggerInternal.FrameDebuggerEventDetailsView.DrawEventDetails (UnityEngine.Rect rect, UnityEditorInternal.FrameDebuggerInternal.FrameDebuggerEvent descs, System.Boolean isDebuggingEditor) (at <043e10ec4a0f4999a2729072194b9cfe>:0)
UnityEditor.FrameDebuggerWindow.DrawEnabledFrameDebugger (System.Boolean repaint) (at <043e10ec4a0f4999a2729072194b9cfe>:0)
UnityEditor.FrameDebuggerWindow.OnGUI () (at <043e10ec4a0f4999a2729072194b9cfe>:0)
UnityEditor.HostView.InvokeOnGUI (UnityEngine.Rect onGUIPosition) (at <043e10ec4a0f4999a2729072194b9cfe>:0)
UnityEditor.DockArea.DrawView (UnityEngine.Rect dockAreaRect) (at <043e10ec4a0f4999a2729072194b9cfe>:0)
UnityEditor.DockArea.OldOnGUI () (at <043e10ec4a0f4999a2729072194b9cfe>:0)
UnityEngine.UIElements.IMGUIContainer.DoOnGUI (UnityEngine.Event evt, UnityEngine.Matrix4x4 parentTransform, UnityEngine.Rect clippingRect, System.Boolean isComputingLayout, UnityEngine.Rect layoutSize, System.Action onGUIHandler, System.Boolean canAffectFocus) (at <02b90f1c0dfb49a1adfd6da071d5b611>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

GUI Error: You are pushing more GUIClips than you are popping. Make sure they are balanced.
UnityEngine.GUIUtility:ProcessEvent (int,intptr,bool&)

I’ve found that the source of this seems to be something to do with the render target being a MRT, since when I change the MRT to a single render texture, it works fine with errors. The way I’ve implemented the MRT is as follows:


static RenderTargetIdentifier[] mrt = new RenderTargetIdentifier[8];

.........

buffer.GetTemporaryRT(litBufferId, bufferSize.x, bufferSize.y, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
        RenderTargetIdentifier litBufferID = new RenderTargetIdentifier(litBufferId);

        buffer.GetTemporaryRT(normalBufferId, bufferSize.x, bufferSize.y, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
        RenderTargetIdentifier normalBufferID = new RenderTargetIdentifier(normalBufferId);

        buffer.GetTemporaryRT(outlineParamBufferId, bufferSize.x, bufferSize.y, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
        RenderTargetIdentifier outlineParam0BufferID = new RenderTargetIdentifier(outlineParamBufferId);

        buffer.GetTemporaryRT(idBufferId, bufferSize.x, bufferSize.y, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
        RenderTargetIdentifier outlineParam1BufferID = new RenderTargetIdentifier(idBufferId);

        buffer.GetTemporaryRT(freeBufferId, bufferSize.x, bufferSize.y, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
        RenderTargetIdentifier outlineParam2BufferID = new RenderTargetIdentifier(freeBufferId);

        buffer.GetTemporaryRT(waterBufferId, bufferSize.x, bufferSize.y, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
        RenderTargetIdentifier outlineParam3BufferID = new RenderTargetIdentifier(waterBufferId);

        buffer.GetTemporaryRT(smoothnessBufferId, bufferSize.x, bufferSize.y, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
        RenderTargetIdentifier smoothnessBufferID = new RenderTargetIdentifier(smoothnessBufferId);

        buffer.GetTemporaryRT(particleBufferId, bufferSize.x, bufferSize.y, 0, FilterMode.Point, RenderTextureFormat.ARGBFloat, RenderTextureReadWrite.Linear);
        RenderTargetIdentifier particleBufferID = new RenderTargetIdentifier(particleBufferId);

        buffer.SetGlobalTexture(litBufferId, litBufferID);
        buffer.SetGlobalTexture(normalBufferId, normalBufferID);
        buffer.SetGlobalTexture(outlineParamBufferId, outlineParam0BufferID);
        buffer.SetGlobalTexture(idBufferId, outlineParam1BufferID);
        buffer.SetGlobalTexture(freeBufferId, outlineParam2BufferID);
        buffer.SetGlobalTexture(waterBufferId, outlineParam3BufferID);
        buffer.SetGlobalTexture(smoothnessBufferId, smoothnessBufferID);
        buffer.SetGlobalTexture(depthBufferTempId, depthBufferTempID);
        buffer.SetGlobalTexture(particleBufferId, particleBufferID);
    
        mrt[0] = litBufferID;
        mrt[1] = normalBufferID;
        mrt[2] = outlineParam0BufferID;
        mrt[3] = outlineParam1BufferID;
        mrt[4] = outlineParam2BufferID;
        mrt[5] = outlineParam3BufferID;
        mrt[6] = smoothnessBufferID;
        mrt[7] = particleBufferID;

        buffer.SetRenderTarget(mrt, depthBufferTempId);
        buffer.ClearRenderTarget(true, true, Color.clear);
        ExecuteBuffer();

So when I change mrt to something like litBufferID, I get those error messages when using the frame debugger. Could someone give me some pointers on how to fix this issue please?

TIA

I figured out that the code is fine, everything works normally when I reduced the MRT size/buffer count from 8 to 7. Is there a way to get the frame debugger it to work with 8 buffers in Unity 2022 like it does in Unity 2021? Also, does the depth buffer add to the number of render targets I’m using, so I might actually be trying to do 9 render targets?

Sorry, this is not a direct solution to your problem. However, it might still be related to your issue. Since this has been troubling me for a long time, I came to this discussion to seek help. My issue is that multi-targeting does not work in HDRP either.

My question and all the related code can be found on this page. Failed to Create a Custom Render Pass in HDRP: MRT Not Working.

Below is a brief summary of my issue.

My render pass is defined as follows,

using (var builder = renderGraph.AddRenderPass<RSMGIPassData>(debugDisplay ? "RSM Forward (+ Emissive) Opaque  Debug" : "RSM Forward (+ Emissive) Opaque ",
                out var passData,
                debugDisplay ? ProfilingSampler.Get(HDProfileId.RSMDebug) : ProfilingSampler.Get(HDProfileId.RSM)))
            {
                var rendererList = renderGraph.CreateRendererList(RSMBufferRendererList(cullResults, hdCamera));
                builder.UseRendererList(rendererList);
            
                int index = 0;
                passData.rsmGIPassData_rsmgiBuffers.rsmPositionBuffer = builder.UseColorBuffer(rendergraph_rsmgiBuffers.rsmPositionBuffer, index++);
                passData.rsmGIPassData_rsmgiBuffers.rsmNormalBuffer = builder.UseColorBuffer(rendergraph_rsmgiBuffers.rsmNormalBuffer, index++);
                passData.rsmGIPassData_rsmgiBuffers.rsmFluxBuffer= builder.UseColorBuffer(rendergraph_rsmgiBuffers.rsmFluxBuffer, index++);
                passData.noUseDepthBuffer = builder.UseDepthBuffer(CreateDepthBuffer(renderGraph, true, MSAASamples.None), DepthAccess.Write);

                builder.AllowRendererListCulling(false);
                
                builder.SetRenderFunc(
                    (RSMGIPassData data, RenderGraphContext context) =>
                    {
                        BindGlobalRSMPassBuffers(data, context.cmd);

                        CoreUtils.DrawRendererList(context.renderContext, context.cmd, rendererList);
DecalSystem.instance.RenderForwardEmissive(context.cmd);
                    });
            }

My shader content is as follows,

PackedVaryingsType Vert(AttributesMesh inputMesh)
{
    VaryingsType varyingsType;
    varyingsType.vmesh = VertMesh(inputMesh);
    return PackVaryingsType(varyingsType);
}

void Frag(  PackedVaryingsToPS packedInput, 
	out float4 outPositionWS : SV_Target0, 
	out float4 outNormalWS : SV_Target1,
	out float4 outColor : SV_Target2)
{
	outPositionWS = float4(1.0, 0.0, 0.0, 1.0); //red
	outNormalWS = float4(0.0, 1.0, 0.0, 1.0);  // green
	outColor = float4(0.0, 0.0, 1.0, 1.0);     // blue
}

I found that when I don’t use the vertex shader, one of the textures gets rendered, although incorrectly.

However, if I use the vertex shader, none of the textures are rendered in the Frame Debugger. I also used RenderDoc for debugging, but from the Texture Viewer, there doesn’t seem to be any additional information.

That’s awesome! You truly brought me luck. I just discovered that the issue was a small bug—adding ColorMask 0 in Lit.shader caused no color output.