Search Unity

CommandBuffer.Blit's parameter "Vector2 scale" and "Vector2 offset" have no effect

Discussion in 'Universal Render Pipeline' started by LB_Chris, Apr 14, 2021.

  1. LB_Chris

    LB_Chris

    Joined:
    Jan 29, 2020
    Posts:
    33
    Hey folks,

    I want to use a CustomRenderPass to perform a blit from the current camera render texture to a custom render texture after all rendering is done. I then want to encode the custom texture data into a jpeg and send it over network. That happens on the cpu of course, after getting the custom render textures pixel data from the gpu to the cup by calling RenderTexture.GetPixels or by utilizing a AsyncGUPReadback. All of that must work on a mobile VR device (Oculus Quest or Pico Neo 2/3), so it has to be as performant as possible.

    The current cameras render texture has a resulution of 1440x1600 but the image data sent over the network should not exceed a resultion of 400x500 (or something like that) and I thought the best point in that whole process was somewhere on the graphics card. The CommandBuffer has a blit operation function and you can specify the scale and offset to the function call (https://docs.unity3d.com/ScriptReference/Rendering.CommandBuffer.Blit.html) but no matter what I set them to, it does not have any effect on the result. When setting the dst's render textures resolution smaller than the src's, the dst will only contain the top left corner of the src's original texture. So there is no scaling done automatically, yet the Vector2 scale in the blit functions parameter doesn't change anything either.

    Can anyone elaborate what the Vector2 scale and Vector2 offset is supposed to do in the blit function and if there are any conditions to take in account when using the blit operation? Also if you have any suggestions on how to rescale a render texture or Texture2D are welcome.



    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering;
    3. using UnityEngine.Rendering.Universal;
    4.  
    5. public class ScreenShotRenderPass : ScriptableRendererFeature
    6. {
    7.     class CustomRenderPass : ScriptableRenderPass
    8.     {
    9.         private RenderTargetIdentifier _customRenderTargetIdentifier;
    10.         private Vector2 _srcScale;
    11.         private Vector2 _srcOffset;
    12.         // This method is called before executing the render pass.
    13.         // It can be used to configure render targets and their clear state. Also to create temporary render target textures.
    14.         // When empty this render pass will render to the active camera render target.
    15.         // You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
    16.         // The render pipeline will ensure target setup and clearing happens in an performance manner.
    17.         public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
    18.         {
    19.             bool takeScreenShot = StreamingManager.Instance != null &&
    20.                                   StreamingManager.Instance._renderType == StreamingManager.RenderType.RenderPassBlit &&
    21.                                   StreamingManager.Instance.TakeScreenshotThisFrame();
    22.  
    23.             if (takeScreenShot)
    24.             {
    25.                 _srcScale = StreamingManager.Instance.blitScale;
    26.                 _srcOffset = StreamingManager.Instance.blitOffset;
    27.                 _customRenderTargetIdentifier = StreamingManager.Instance._customRenderTextureIdentifier;
    28.             }
    29.         }
    30.  
    31.         // Here you can implement the rendering logic.
    32.         // Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
    33.         // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
    34.         // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
    35.         public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    36.         {
    37.             CommandBuffer cmd = CommandBufferPool.Get();
    38.  
    39.             bool takeScreenShot = Application.isPlaying &&
    40.                                   StreamingManager.Instance != null &&
    41.                                   StreamingManager.Instance._renderType == StreamingManager.RenderType.RenderPassBlit &&
    42.                                   StreamingManager.Instance.TakeScreenshotThisFrame();
    43.  
    44.             if (takeScreenShot)
    45.             {
    46.                 RenderTargetIdentifier src = BuiltinRenderTextureType.CameraTarget;
    47.                 RenderTargetIdentifier dst = _customRenderTargetIdentifier;
    48.  
    49.                 RenderTargetIdentifier prev = BuiltinRenderTextureType.CameraTarget;
    50.                 // Here the _srcScale and _srcOffset doesn't do anything at all. I can give them any values and the result is always the same.
    51.                 cmd.Blit(src, dst, _srcScale, _srcOffset);
    52.                 cmd.SetRenderTarget(prev);
    53.             }
    54.  
    55.             // execution
    56.             context.ExecuteCommandBuffer(cmd);
    57.             CommandBufferPool.Release(cmd);
    58.         }
    59.  
    60.         /// Cleanup any allocated resources that were created during the execution of this render pass.
    61.         public override void FrameCleanup(CommandBuffer cmd)
    62.         {
    63.         }
    64.     }
    65.  
    66.     CustomRenderPass m_ScriptablePass;
    67.  
    68.     public override void Create()
    69.     {
    70.         m_ScriptablePass = new CustomRenderPass();
    71.  
    72.         // Configures where the render pass should be injected.
    73.         m_ScriptablePass.renderPassEvent = RenderPassEvent.AfterRendering;
    74.     }
    75.  
    76.     // Here you can inject one or multiple render passes in the renderer.
    77.     // This method is called when setting up the renderer once per-camera.
    78.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    79.     {
    80.         renderer.EnqueuePass(m_ScriptablePass);
    81.     }
    82. }

    Notes: In OpenGLes3 the code doesn't work at all. It only shows a black texture. For this reason and because I want to utilize AsyncGPUReadback I am using Vulkan.
     
    hadardasim_isi likes this.
  2. hadardasim_isi

    hadardasim_isi

    Joined:
    Feb 5, 2021
    Posts:
    2
    I have the same issue running on windows with HDRP
    Unity version 2021.2.10f1
     
  3. vizgl

    vizgl

    Joined:
    Nov 4, 2014
    Posts:
    61
    Same
     
  4. Genies_Dom

    Genies_Dom

    Joined:
    Oct 5, 2022
    Posts:
    2
  5. amollis_unity

    amollis_unity

    Joined:
    Feb 2, 2018
    Posts:
    1
    Ditto

    Hitting in Unity 2021.3.15