Search Unity

Bug Render Textures are currently broken in SRP

Discussion in 'Universal Render Pipeline' started by SgerbwdGwyn, Mar 4, 2021.

  1. SgerbwdGwyn

    SgerbwdGwyn

    Joined:
    Dec 2, 2013
    Posts:
    25
    Essentially what I've been trying to do is pass a framebuffer into a shader, so the shader can sample from _MainTex (the data buffer I've set up, works correctly with Blit) and another sampler called _FrameBufferTex.
    This is all done in the SRP, chiefly following this guide: https://samdriver.xyz/article/scriptable-render

    The problem is that no matter how I do it, it's impossible to actually assign a render texture to any shader's respective property of the same name. This should be possible, according to the documentation, simply by creating a RenderTargetHandle and initialising it with Init("_FrameBufferTex"), which can then be assigned a temporary RT with commandBuffer.GetTemporaryRT(<handle>.id, <some RenderTextureDescriptor here>).
    Once that's set up, any shader with the property _FrameBufferTex should then be able to access whatever image gets put in the corresponding handle, right?
    If you then call commandBuffer.Blit(<camera colour buffer identifier>, <handle>.Identifier()), you would expect the contents of the camera's colour buffer to be copied to the render texture, which can then be accessed in a subsequent blit, except you can't - it's unwritten to, blank, white. Not just blank but according to the frame debugger the, texture property hasn't been assigned at all! It's the default 1px white texture that texture properties have by default.

    I've tried using the static Shader.PropertyToID method, <material>.shader.FindPropertyIndex on the specific material to get the ID, I've tried calling SetGlobalTexture and passing the name of the property and the render texture, I've tried calling SetGlobalTexture and just straight up passing in the camera's colour rendertexture identity, but nothing has worked. The only thing that works is when Blit automatically assigns _MainTex, it seems that nothing else based on temporary RTs can be assigned at the moment in SRP
     
    Last edited: Mar 4, 2021
  2. kripto289

    kripto289

    Joined:
    Feb 21, 2013
    Posts:
    505
    It's not srp problem.
    In the 2018.4 version in standard rendering, I see the same problems. Unity in some times used random temporary textures with the same resolution/format as blit source.
    The only solution which works it's create "new RenderTexture" and use it instead of buffer.GetTemporary.
     
    SgerbwdGwyn likes this.
  3. SgerbwdGwyn

    SgerbwdGwyn

    Joined:
    Dec 2, 2013
    Posts:
    25
    I managed to fix this in my case by REMOVING THE TEXTURE FROM THE PROpERTIES BLOCK...??? why does having a shader property exposed make it unusable in SRP? Shouldn't the properties block be the thing that identifies the property and allows it to be set globally? This is makes no sense.
     
  4. D1234567890

    D1234567890

    Joined:
    Aug 11, 2019
    Posts:
    65
    I think I am having the same problem. Is it where the wrong temporary RT is bound? I looked in the Frame Debugger and see that the names do not match. Have you tried reporting the bug to Unity and what was their response?
     
  5. kripto289

    kripto289

    Joined:
    Feb 21, 2013
    Posts:
    505
    No I have not reported this bug, I'm lazy :)
    In any case I prefer to use
    Code (CSharp):
    1. RenderTexture.GetTemporary(rt);
    2. rt.Create();
    In this case I can use 100500 individual textures which I can use in the next frame. (command buffer will release render texture when command will be executed)
     
  6. D1234567890

    D1234567890

    Joined:
    Aug 11, 2019
    Posts:
    65
    Thanks. I have reported it to them and will be changing to RenderTexture.GetTemporary for the time being too. I also found that CommandBuffer.GetTemporaryRT is leaking as I have 16 instances of the same texture in the memory profiler despite releasing them o_O
     
  7. kripto289

    kripto289

    Joined:
    Feb 21, 2013
    Posts:
    505
    I found that it is necessary to release temporary buffer before the next frame to avoid memory leak.
    It's works perfect:
    [/code]
    Code (CSharp):
    1.  
    2. RenderTexture rt;
    3. private void OnEnable()
    4.     {
    5.         Camera.onPreCull += MyPreCull;
    6.         Camera.onPostRender += MyPostRender;
    7.     }
    8.  
    9.     void OnDisable()
    10.     {
    11.         Camera.onPreCull -= MyPreCull;
    12.         Camera.onPostRender -= MyPostRender;
    13.     }
    14.  
    15. public void MyPreCull(Camera cam)
    16.     {
    17.         if(rt == null) rt = RenderTexture.GetTemporary(512, 512, 24);
    18.     }
    19.  
    20.     public void MyPostRender(Camera cam)
    21.     {
    22.       if(rt != null) RenderTexture.ReleaseTemporary(rt);
    23.     }
    24.  
    But this doesn't work and I have memory leak.
    Code (CSharp):
    1.  
    2. RenderTexture rt;
    3. private void OnEnable()
    4.     {
    5.         Camera.onPreCull += MyPreCull;
    6.         Camera.onPostRender += MyPostRender;
    7.     }
    8.  
    9.     void OnDisable()
    10.     {
    11.         Camera.onPreCull -= MyPreCull;
    12.         Camera.onPostRender -= MyPostRender;
    13.  
    14.        if(rt != null) RenderTexture.ReleaseTemporary(rt);
    15.     }
    16.  
    17. public void MyPreCull(Camera cam)
    18.     {
    19.         if(rt == null) rt = RenderTexture.GetTemporary(512, 512, 24);
    20.     }
    21.  
    I do not know how it works inside. In the profiler I have this message.
    upload_2021-11-12_14-28-0.png
    Maybe unity set the flags "HideAndDontSave" if the texture has not cleared in the same frame?
    documentation:
    But command buffers must be cleaned anyway.
    Did you use cmd.Clear before the next frame rendering? Try to clear command buffer after postRender?
     
  8. D1234567890

    D1234567890

    Joined:
    Aug 11, 2019
    Posts:
    65
    Apologies. I forgot to reply... I was advised by Unity to never use a temporary RT outside the pass it is requested from, even if it is within the same frame, as this is undefined behaviour which make sense.