Search Unity

Bug CommandBuffer.Blit will not set _MainTex and can cause memory leak

Discussion in 'General Graphics' started by RINNUXEI, May 1, 2023.

  1. RINNUXEI

    RINNUXEI

    Joined:
    Sep 3, 2015
    Posts:
    32
    Hey, we found a problem that using CommandBuffer.Blit to copy from BuiltinRenderTextureType.CameraTarget with a custom material will not set the _MainTex property of the destination render texture on Android devices (iOS not tested). In the Frame Debugger, the _MainTex property shows UnityDefault2D, which is a solid grey sqaure, instead of a capture of the screen. While in Unity Editor on PC, the same method just works perfectly.

    image3.png

    The code looks like below:
    Code (CSharp):
    1. cb.GetTemporaryRT(tmpRTId, camera.pixelWidth, camera.pixelHeight, 0, FilterMode.Bilinear);
    2. var tmpRT = new RenderTargetIdentifier(tmpRTId);
    3. cb.Blit(BuiltinRenderTextureType.CameraTarget, tmpRT, blitMaterial);
    We actually realized that this is a reported bug and seems to be fixed in Unity 2022.2. But since we are using Unity 2021 and are not currently considering upgrading, will this fix also be available with Unity 2021?

    By the way, we also found a memory leak issuse when using Blit without a material. The Frame Debugger shows that an addtional Grab Render Texture pass is added, and more badly, the Memory Profiler shows that a render texture called GrabRenderTexture is generated, which cannot be freed anyway since we have no reference to it. Is this a bug or we missed something?

    Any help will be appreciated ,thank you.

    image.png

    image2.png
     
    ontrigger likes this.
  2. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    675
    Maybe this works as a workaround:
    Code (CSharp):
    1. cb.GetTemporaryRT(tmpRTId, camera.pixelWidth, camera.pixelHeight, 0, FilterMode.Bilinear);
    2. var tmpRT = new RenderTargetIdentifier(tmpRTId);
    3. blitMaterial.mainTexture = camera.target;
    4. cb.Blit(BuiltinRenderTextureType.CameraTarget, tmpRT, blitMaterial);
    5.  
    If this doesn't work, you could also try creating a different shader parameter for the texture (but you need a custom shader in that case)
    Code (CSharp):
    1. cb.GetTemporaryRT(tmpRTId, camera.pixelWidth, camera.pixelHeight, 0, FilterMode.Bilinear);
    2. var tmpRT = new RenderTargetIdentifier(tmpRTId);
    3. blitMaterial.SetTexture("_SourceTex", camera.target);
    4. cb.Blit(BuiltinRenderTextureType.CameraTarget, tmpRT, blitMaterial);
    5.  
     
  3. RINNUXEI

    RINNUXEI

    Joined:
    Sep 3, 2015
    Posts:
    32
    Thank you for your reply, @c0d3_m0nk3y , I tried both methods, but neither of them worked. I believe the reason is that my camera.targetTexture is null, which means that neither mainTexture nor SetTexture will set any texture. As a result, the default Unity2DDefault texture is still being used.
     
  4. RINNUXEI

    RINNUXEI

    Joined:
    Sep 3, 2015
    Posts:
    32
  5. _geo__

    _geo__

    Joined:
    Feb 26, 2014
    Posts:
    1,344
    This resolved a similar issues I had on Android (not sure it applies to your particular problem but it might be worth a shot):
    Code (CSharp):
    1. // copy screen into temporary RT
    2. int screenCopyID = Shader.PropertyToID("_ScreenCopyTexture");
    3. buf.GetTemporaryRT(screenCopyID, -1, -1, 0, FilterMode.Bilinear);
    4. buf.Blit(BuiltinRenderTextureType.CameraTarget, screenCopyID);
    5. // Copy from tmp source to RT.
    6. buf.Blit(screenCopyID, myRenderTexture, blitMaterial);
    7. buf.ReleaseTemporaryRT(screenCopyID);
    Have you tried "BuiltinRenderTextureType.CurrentActive" as alternative? Maybe you have set
    cam.forceIntoRenderTexture = true;
    .
     
    RINNUXEI likes this.
  6. RINNUXEI

    RINNUXEI

    Joined:
    Sep 3, 2015
    Posts:
    32
    Hey, thank you for your reply. We had taken the exactly same approach as you mentioned as a temporary solution. However blitting to a intermediate render texture takes addtional cost, which we tried to avoid.

    For the
    BuiltinRenderTextureType.CurrentActive
    , though we did not set
    camera.forceIntoRenderTexture
    to true, we tried it again, and it did not work. So we think this is a bug of our current version of Unity (2021), and Untiy 2022 seems to have a fix for it. We will give it a try when it's time to upgrade our project.

    Anyway, thank you once agian for your information, it's greatly appreciated.