Command buffer in Single Pass Instanced

I’m trying to do an outline render feature in URP with SPI. I’ve set up a custom pass rendering to a buffer and have everything working with Multi Pass, but Single Pass Instanced completely confuses me.
I’m rendering specific layer with overrideMaterial which is unlit white. Works well when I render to camera target, one sphere is rendered to both eyes once, as it should be.

But if I configure a render target and check in frame debugger, my sphere is duplicated with a small offset.

class CustomRenderPass : ScriptableRenderPass
    {
        private RenderTargetHandle _destination;
        private List<ShaderTagId> _shaderTagIdList = new List<ShaderTagId>() { new ShaderTagId("UniversalForward") };
        private FilteringSettings _filteringSettings;
        private RenderStateBlock _renderStateBlock;
        private Material _overrideMaterial;

        public CustomRenderPass(RenderTargetHandle destination, int layerMask, Material overrideMaterial)
        {
            _destination = destination;
          
            _filteringSettings = new FilteringSettings(RenderQueueRange.opaque, layerMask);
            _renderStateBlock = new RenderStateBlock(RenderStateMask.Nothing);
            _overrideMaterial = overrideMaterial;
        }

        public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
        { 
            cmd.GetTemporaryRT(_destination.id, cameraTextureDescriptor);
            //ConfigureTarget(_destination.Identifier());
            ConfigureClear(ClearFlag.All, Color.clear);
        }

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
        {
            SortingCriteria sortingCriteria = renderingData.cameraData.defaultOpaqueSortFlags;
            DrawingSettings drawingSettings = CreateDrawingSettings(_shaderTagIdList, ref renderingData, sortingCriteria);
            drawingSettings.overrideMaterial = _overrideMaterial;

            context.DrawRenderers(renderingData.cullResults, ref drawingSettings, ref _filteringSettings, ref _renderStateBlock);
        }

    }

If I then perform full screen blit like in this guide, I get two spheres in both eyes.
https://docs.unity3d.com/Packages/com.unity.render-pipelines.universal@12.1/manual/renderer-features/how-to-fullscreen-blit-in-xr-spi.html

Can you help me understand what I’m doing wrong here?

Also it seems like it’s rendered only into first slice of array texture, so only in the left eye. I’ve tried to do everything possible to make it render into both eyes:

public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
        {
            cameraTextureDescriptor.dimension = TextureDimension.Tex2DArray;
            cameraTextureDescriptor.volumeDepth = 2;
            cameraTextureDescriptor.vrUsage = VRTextureUsage.TwoEyes;

            cmd.GetTemporaryRTArray(_destination.id, cameraTextureDescriptor.width, cameraTextureDescriptor.height, 2, 0);
            cmd.SetSinglePassStereo(SinglePassStereoMode.Instancing);
            ConfigureTarget(_destination.Identifier());
            //cmd.SetRenderTarget(_destination.Identifier(), 0, CubemapFace.Unknown, -1);
            ConfigureClear(ClearFlag.All, Color.clear);
        }

cmd.SetRenderTarget instead of ConfigureTarget doesn’t work at all.

Hi Genebris,
From the screenshot, looks like the issue is that only the first slice of the RT is bound.
Could you try to create RenderTargetIdentifier and set its depthSlices to all slices?

1 Like

Thanks Thomas! Yeah, I think that solved it:

    ConfigureTarget(new RenderTargetIdentifier(_destination.Identifier(), 0, CubemapFace.Unknown,  RenderTargetIdentifier.AllDepthSlices));

Really confusing that it’s called depthSlices, I thought this parameter is only for depth buffer which I don’t use. I really wish documentation especially URP one would explain how to use these methods.

4 Likes