Search Unity

Question How to set a two pass shader blit in URP14? (in URP 12 it was kinda straightforward)

Discussion in 'Universal Render Pipeline' started by clabbe, Apr 13, 2023.

  1. clabbe

    clabbe

    Joined:
    Aug 9, 2013
    Posts:
    26
    Using unity 2022.2.6f1 and URP 14

    Hello again!
    I've been trying to upgrade my render features to URP 14 standards and i've hit a wall when i call the Blitter two times in a row.
    One pass works fine but as soon as i run a second the screen goes black.I can see in the frame debugger that both passes are rendered, but second goes black if i use my tempTexture RT. If I change the tempTexture RT to another render target like _CameraOpaqueTexture, for example, the second pass renders but it wont read any information from the first pass. I guess it has to do with the tempTexture RT that's not being allocated right.
    I followed the documentations upgrade guide to URP 14 and everything seems to work fine with just one Blit.
    My shader is updated so it uses the blit.hlsl-include.

    Does anyone have any thoughts or ideas?
    Did I miss something?

    Thanks in advance for any advice!


    Simple verison:


    Second blit gets a black tempTexture when it should contain the shaded sourceTexture.
    Code (CSharp):
    1.         Blitter.BlitCameraTexture(cmd, sourceTexture, tempTexture, material, 0);
    2.         Blitter.BlitCameraTexture(cmd, tempTexture, sourceTexture, material, 1);

    Full code:

    Render Pass

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityEngine.Rendering;
    4. using UnityEngine.Rendering.Universal;
    5.  
    6. public class TemplatePass : ScriptableRenderPass
    7. {
    8.     TemplateFeature.PassSettings passSettings;
    9.     RTHandle tempTexture, sourceTexture;
    10.     Material material;
    11.     static readonly int BlurStrengthProperty = Shader.PropertyToID("_BlurStrength");
    12.  
    13.     void Dispose()
    14.     {
    15.         tempTexture?.Release();
    16.     }
    17.  
    18.     public TemplatePass(TemplateFeature.PassSettings passSettings)
    19.     {
    20.         this.passSettings = passSettings;
    21.         renderPassEvent = passSettings.renderPassEvent;
    22.     if (material == null) material = CoreUtils.CreateEngineMaterial("Ludvigs/Box Blur 2");
    23.  
    24.         material.SetInt(BlurStrengthProperty, passSettings.blurStrength);
    25.     }
    26.  
    27.     public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    28.     {
    29.         RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
    30.         descriptor.width /= passSettings.downsample;
    31.         descriptor.height /= passSettings.downsample;
    32.  
    33.         descriptor.depthBufferBits = 0;
    34.         sourceTexture = renderingData.cameraData.renderer.cameraColorTargetHandle;
    35.         ConfigureTarget(sourceTexture);
    36.         RenderingUtils.ReAllocateIfNeeded(ref tempTexture, descriptor, FilterMode.Point, TextureWrapMode.Clamp, name: "_TempTex");
    37.     }
    38.  
    39.     public void Setup(RTHandle destinationColor)
    40.     {
    41.         sourceTexture = destinationColor;
    42.     }
    43.  
    44.     public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    45.     {
    46.  
    47.         if (renderingData.cameraData.cameraType != CameraType.Game)
    48.             return;
    49.  
    50.         if (material == null)
    51.             return;
    52.  
    53.         CommandBuffer cmd = CommandBufferPool.Get("Blur");
    54.         CoreUtils.SetRenderTarget(cmd, sourceTexture, tempTexture, clearFlag, clearColor);
    55.         //Blit(cmd, sourceTexture, temporaryBuffer, material, 0);
    56.         //Blit(cmd, temporaryBuffer, sourceTexture, material, 1);
    57.         Blitter.BlitCameraTexture(cmd, sourceTexture, tempTexture, material, 0);
    58.         //problemlies here somewhere...
    59.         Blitter.BlitCameraTexture(cmd, tempTexture, sourceTexture, material, 1);
    60.  
    61.         context.ExecuteCommandBuffer(cmd);
    62.         CommandBufferPool.Release(cmd);
    63.     }
    64.  
    65.     public override void OnCameraCleanup(CommandBuffer cmd)
    66.     {
    67.         if (cmd == null) throw new ArgumentNullException("cmd");
    68.         sourceTexture = null;
    69.     }
    70. }
    Render Feature
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering.Universal;
    3.  
    4. public class TemplateFeature : ScriptableRendererFeature
    5. {
    6.    
    7.     [System.Serializable]
    8.     public class PassSettings
    9.     {
    10.         public RenderPassEvent renderPassEvent = RenderPassEvent.AfterRenderingTransparents;
    11.  
    12.         [Range(1, 4)] public int downsample = 1;
    13.         [Range(0, 20)] public int blurStrength = 5;
    14.  
    15.     }
    16.  
    17.     TemplatePass pass;
    18.     public PassSettings passSettings = new();
    19.  
    20.     public override void Create()
    21.     {
    22.         pass = new TemplatePass(passSettings);
    23.     }
    24.  
    25.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    26.     {
    27.         renderer.EnqueuePass(pass);
    28.     }
    29.     public override void SetupRenderPasses(ScriptableRenderer renderer, in RenderingData renderingData)
    30.     {
    31.         pass.Setup(renderer.cameraColorTargetHandle);
    32.     }
    33. }
     
    Last edited: Apr 13, 2023
    Kabinet13 and saz_at_evenflow like this.
  2. saz_at_evenflow

    saz_at_evenflow

    Joined:
    Mar 13, 2018
    Posts:
    10
    I have the same problem. I've spent days trying to figure it out and it is driving me insane.

    Are you using a shader or shader graph?
     
    Last edited: Apr 14, 2023
  3. clabbe

    clabbe

    Joined:
    Aug 9, 2013
    Posts:
    26
    Trust me you are not the only having to keep check on one's emotions, my therapist will be getting a call soon. :p
    Thanks for checking up on me and I'll be sure to let you know if i come across anything.
    are you also bound to 2022.2 and urp 14?
    I based this on an article i found on gitHub so if you are using an earlier version it might help you:
    https://alexanderameye.github.io/notes/scriptable-render-passes/

    I'm using an hlsl-shader:

    Code (CSharp):
    1. // Two-pass box blur shader created for URP 12 and Unity 2021.2
    2. // Made by Alexander Ameye
    3. // https://alexanderameye.github.io/
    4. //
    5. //...And getting Butchered by Ludvig Aleman
    6.  
    7. Shader "Ludvigs/Box Blur 2"
    8. {
    9.         SubShader
    10.     {
    11.         Tags {  "RenderPipeline" = "UniversalPipeline"}
    12.         //LOD 100
    13.         //ZWrite Off Cull Off
    14.         Pass
    15.         {
    16.             Name "ColorBlurBlitPass"
    17.  
    18.             HLSLPROGRAM
    19.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    20.             #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
    21.  
    22.             #pragma vertex Vert
    23.             #pragma fragment frag
    24.  
    25.             TEXTURE2D_X(_CameraColorTexture);
    26.             SAMPLER(sampler_CameraColorTexture);
    27.             float4 _CameraColorTexture_TexelSize;
    28.             float4 _CameraColorTexture_ST;
    29.             int _BlurStrength;
    30.             int setBlur;
    31.             half4 frag (Varyings input) : SV_Target
    32.             {
    33.                 float2 res = _CameraColorTexture_TexelSize.xy;
    34.                 half4 sum = 0;
    35.                 int samples = 2 * _BlurStrength + 1;
    36.  
    37.                 for (float y = 0; y < samples; y++)
    38.                 {
    39.                     float2 offset = float2(0, y - _BlurStrength);
    40.                     sum += SAMPLE_TEXTURE2D(_CameraColorTexture, sampler_CameraColorTexture, input.texcoord + offset * res);
    41.  
    42.                 }
    43.                 return sum / samples;
    44.             }
    45.             ENDHLSL
    46.         }
    47.         Pass
    48.         {
    49.             Name "ColorBlurBlitPass 2"
    50.  
    51.             HLSLPROGRAM
    52.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    53.             #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl"
    54.  
    55.             #pragma vertex Vert
    56.             #pragma fragment frag
    57.  
    58.             TEXTURE2D_X(_CameraColorTexture);
    59.             SAMPLER(sampler_CameraColorTexture);
    60.             float4 _CameraColorTexture_TexelSize;
    61.             float4 _CameraColorTexture_ST;
    62.             int _BlurStrength;
    63.  
    64.             half4 frag (Varyings input) : SV_Target
    65.             {
    66.                 float2 res = _CameraColorTexture_TexelSize.xy;
    67.                 half4 sum = 0;
    68.                 int samples = 2 * _BlurStrength + 1;
    69.  
    70.                 for (float x = 0; x < samples; x++)
    71.                 {
    72.                     float2 offset2 = float2(x - _BlurStrength, 0);
    73.                     sum += SAMPLE_TEXTURE2D(_CameraColorTexture, sampler_CameraColorTexture, input.texcoord + offset2 * res);
    74.                 }
    75.                 return sum / samples;
    76.             }
    77.             ENDHLSL
    78.         }
    79.     }
    80. }
     
  4. KCFindstr

    KCFindstr

    Joined:
    Dec 2, 2019
    Posts:
    3
    Same problem, I was using cmd.Blit in URP 12 and it worked perfectly fine. Have not found a working solution in URP 14 yet.
     
  5. KCFindstr

    KCFindstr

    Joined:
    Dec 2, 2019
    Posts:
    3
    It turns out that my multipass blit worked after switching from renderingData.cameraData.cameraTargetDescriptor to
    cameraColorTarget.rt.descriptor when creating the tempTexture. Not sure if this helps in your case though.
     
    clabbe likes this.
  6. saz_at_evenflow

    saz_at_evenflow

    Joined:
    Mar 13, 2018
    Posts:
    10
    Not exactly bound, but I wanted to try out the fullscreen shader graph + render pass.
    Turned out I couldn't do what I wanted with just that functionality, but needed to have a custom pre-pass which filters / culls and writes the relevant meshes to a texture that I can then utilize in the final pass.

    I'm not done with my shader yet, but at least I managed to get the passes and "communication" between them working.

    In case it helps someone, here is a little bit of the troubleshooting I did:
    • RenderTextureDescriptor.depthBufferBits had to be set to zero / none when allocating the target RTHandle in order to get any colors.
    • Trying to target and render to a RTHandle doesn't mean you can refer to that handle automatically in the shader graph. Had to specifically expose that via Shader.SetGlobalTexture.
    • Similarly, the URP Sample Buffer node in the fullscreen shader graph requires that the "_BlitTexture" is set. This has to be specifically done on the material you are trying to blit / render with.
    • You have to use CoreUtils.SetRenderTarget in-between blits / renders. The following worked for me:
      Code (CSharp):
      1. var source = cameraData.renderer.cameraColorTargetHandle;
      2. Blitter.BlitCameraTexture(cmd, source, outlineBuffer);
      3. outlineMaterial.SetTexture(Shader.PropertyToID("_BlitTexture"), outlineBuffer);
      4. CoreUtils.SetRenderTarget(cmd, source);
      5. Blitter.BlitCameraTexture(cmd, outlineBuffer, source, outlineMaterial, 0); // or use CoreUtils.DrawFullScreen(cmd, outlineMaterial);
    • Calling ScriptableRendererContext.ExecuteCommandBuffer inside a ProfilingScope causes an infinite stack trace in the frame debugger and eventually crash of Unity.
    Just a few things I remember screwing up on.
     
    Kabinet13 and clabbe like this.
  7. Kabinet13

    Kabinet13

    Joined:
    Jun 13, 2019
    Posts:
    129
    I've also been having this problem. I am also, similarly, going insane. Is this a bug, and if it isn't, could we please get unity staff to chime in on what's going on here?

    I can't make progress on a project of mine until this is sorted out.
     
  8. wwWwwwW1

    wwWwwwW1

    Joined:
    Oct 31, 2021
    Posts:
    769
    It seems that your custom shader should use a vertex stage provided by Blitter, unless you use the default material to perform blit.

    You can follow the documentation to create a Blitter required shader. Or rewrite to a full screen shader graph instead.
     
  9. Kabinet13

    Kabinet13

    Joined:
    Jun 13, 2019
    Posts:
    129

    I'll try that, but considering our custom shaders work fine the first time around, I have no idea why a shader change should affect anything, right?
     
    wwWwwwW1 likes this.