Search Unity

Question Help me optimize shader. OpenGL ES

Discussion in 'Universal Render Pipeline' started by blablaalb, Apr 23, 2021.

  1. blablaalb

    blablaalb

    Joined:
    Oct 28, 2015
    Posts:
    53
    I'm trying to do a bit of shader development. I found this optimized version of gaussian blur (shadertoy demo), rewrote it in ShaderLab::
    Code (CSharp):
    1. Shader "Custom/Effects/Blur"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Texture", 2D) = "white" {}
    6.         _Offset ("Offset", Range(1, 100)) = 10
    7.     }
    8.     SubShader
    9.     {
    10.         Pass
    11.         {
    12.             CGPROGRAM
    13.             #pragma vertex vert
    14.             #pragma fragment frag
    15.  
    16.             #include "UnityCG.cginc"
    17.  
    18.             struct appdata
    19.             {
    20.                 float4 vertex : POSITION;
    21.                 fixed2 uv : TEXCOORD0;
    22.             };
    23.  
    24.             struct v2f
    25.             {
    26.                 fixed2 uv : TEXCOORD0;
    27.                 float4 vertex : SV_POSITION;
    28.                 half2 uv1 : TEXCOORD6;
    29.                 half2 uv2 : TEXCOORD7;
    30.             };
    31.  
    32.             half _Offset;
    33.             sampler2D _MainTex;
    34.             float4 _MainTex_ST;
    35.  
    36.             v2f vert (appdata v)
    37.             {
    38.                 v2f o;
    39.                 o.vertex = UnityObjectToClipPos(v.vertex);
    40.                 o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    41.  
    42.                 float direction = o.uv * _Offset;
    43.                 half2 off =  half2(1.3333333333333333, 1.3333333333333333)* direction;
    44.                 half2 resolution = _ScreenParams.xy;
    45.                 o.uv1 = o.uv + (off / resolution);
    46.                 o.uv2 = o.uv - (off / resolution);
    47.                 return o;
    48.             }
    49.  
    50.             fixed4 frag (v2f i) : SV_Target
    51.             {
    52.                 fixed4 color = tex2D(_MainTex, i.uv) * 0.29411764705882354;
    53.                 color += tex2Dlod(_MainTex,float4(i.uv1, 0, 3)) * 0.35294117647058826;
    54.                 color += tex2Dlod(_MainTex, float4(i.uv2, 0, 3)) * 0.35294117647058826;
    55.  
    56.                 return color;
    57.             }
    58.             ENDCG
    59.         }
    60.     }
    61. }
    62.  
    and added it as a ScriptableRenderFeature:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering;
    3. using UnityEngine.Rendering.Universal;
    4. using System;
    5.  
    6. public class BlurFeature : ScriptableRendererFeature
    7. {
    8.     class BlurPass : ScriptableRenderPass
    9.     {
    10.         private string profilerTag;
    11.         private Material materialToBlit;
    12.         private RenderTargetIdentifier cameraColorTargetIdent;
    13.         private RenderTargetHandle tempTexture;
    14.  
    15.         public BlurPass(string profilerTag, RenderPassEvent renderPassEvent, Material material) : base()
    16.         {
    17.             this.profilerTag = profilerTag;
    18.             this.renderPassEvent = renderPassEvent;
    19.             this.materialToBlit = material;
    20.         }
    21.  
    22.         public void Setup(RenderTargetIdentifier cameraColorTargetIdent)
    23.         {
    24.             this.cameraColorTargetIdent = cameraColorTargetIdent;
    25.         }
    26.  
    27.         // called each frame before Execute, use it to set up things the pass will need
    28.         public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
    29.         {
    30.             // create a temporary render texture that matches the camera
    31.             cmd.GetTemporaryRT(tempTexture.id, cameraTextureDescriptor);
    32.             base.Configure(cmd, cameraTextureDescriptor);
    33.         }
    34.  
    35.         // This method is called before executing the render pass.
    36.         // It can be used to configure render targets and their clear state. Also to create temporary render target textures.
    37.         // When empty this render pass will render to the active camera render target.
    38.         // You should never call CommandBuffer.SetRenderTarget. Instead call <c>ConfigureTarget</c> and <c>ConfigureClear</c>.
    39.         // The render pipeline will ensure target setup and clearing happens in a performant manner.
    40.         public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    41.         {
    42.         }
    43.  
    44.         // Here you can implement the rendering logic.
    45.         // Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
    46.         // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
    47.         // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
    48.         public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    49.         {
    50.             // fetch a command buffer to use
    51.             CommandBuffer cmd = CommandBufferPool.Get(profilerTag);
    52.             cmd.Clear();
    53.  
    54.             cmd.Blit(cameraColorTargetIdent, tempTexture.Identifier(), materialToBlit, 0);
    55.             cmd.Blit(tempTexture.Identifier(), cameraColorTargetIdent);
    56.  
    57.             context.ExecuteCommandBuffer(cmd);
    58.  
    59.             cmd.Clear();
    60.             CommandBufferPool.Release(cmd);
    61.         }
    62.  
    63.         public override void FrameCleanup(CommandBuffer cmd)
    64.         {
    65.             cmd.ReleaseTemporaryRT(tempTexture.id);
    66.             base.FrameCleanup(cmd);
    67.         }
    68.  
    69.         // Cleanup any allocated resources that were created during the execution of this render pass.
    70.         public override void OnCameraCleanup(CommandBuffer cmd)
    71.         {
    72.             cmd.ReleaseTemporaryRT(tempTexture.id);
    73.             base.OnCameraCleanup(cmd);
    74.         }
    75.     }
    76.  
    77.     [Serializable]
    78.     public class BlurSettings
    79.     {
    80.         public bool IsEnabled = true;
    81.         public RenderPassEvent RenderPassedOrder = RenderPassEvent.AfterRendering;
    82.         public Material Material;
    83.     }
    84.     public BlurSettings settings = new BlurSettings();
    85.  
    86.     RenderTargetHandle renderTextureHandle;
    87.     BlurPass myRenderPass;
    88.  
    89.  
    90.     /// <inheritdoc/>
    91.     public override void Create()
    92.     {
    93.         myRenderPass = new BlurPass("BLur Pass", settings.RenderPassedOrder, settings.Material);
    94.     }
    95.  
    96.     // Here you can inject one or multiple render passes in the renderer.
    97.     // This method is called when setting up the renderer once per-camera.
    98.     public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    99.     {
    100.         if (!settings.IsEnabled)
    101.         {
    102.             return;
    103.         }
    104.         var cameraColorTargetIdent = renderer.cameraColorTarget;
    105.         myRenderPass.Setup(cameraColorTargetIdent);
    106.  
    107.         renderer.EnqueuePass(myRenderPass);
    108.     }
    109. }
    Basically it just grabs the rendered screen (from backbuffer ?), applies material with the shader to it and then renders it to the screen.
    After adding the shader I tested it's performance on a mobile device. Before adding the shader the FPS was around 37 and with the shader applied the FPS dropped to 20.
    How can optimize the shader so the performance implication won't be that significant?
     
  2. blablaalb

    blablaalb

    Joined:
    Oct 28, 2015
    Posts:
    53
    I edited the shader to this:
    Code (CSharp):
    1. fixed4 frag (v2f i) : SV_Target
    2.    {
    3.        return tex2D(_MainTex, i.uv);
    4.    }
    and the fps is still at 20, so the shader isn't the issue here. I wonder if the ScriptableRenderFeature can be optimized.
     
  3. revolute

    revolute

    Joined:
    Jul 28, 2014
    Posts:
    50
    You could lower resolution of the render texture. Its a blur, half resolution wouldn't make it too noticeable since everything is being mashed up already.
     
  4. blablaalb

    blablaalb

    Joined:
    Oct 28, 2015
    Posts:
    53
    I replaced the blur shader with an empty shader that just returned sampled texture without applying any effect and the fps were still at 20. I guess it means that the shader is not the issue here since even the simplest possible shader drops the fps from 37 to 20.