Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug RenderLoop.ScheduleDraw performance drop at different camera positions and rotations.

Discussion in 'Editor & General Support' started by leom44, Dec 5, 2023.

  1. leom44

    leom44

    Joined:
    Jul 29, 2019
    Posts:
    1
    I've created an empty scene without any lighting, in which using ComputeShaders and Graphics.RenderMeshPrimitives I generate and render 262.144 cubes/voxels of different colors. I'm using URP and the cubes have a unlit shader in which through a custom shader graph node I gather their position and color from the compute shader. For some reason based on where the MainCamera is positioned the rendering performance improves or decreases. Analysing the performance using the profiler I've discovered that this is due to "RenderLoop.ScheduleDraw" taking more or less time to execute as in the pictures below (from 15.4ms to 21.4ms execution time).

    Main c# script:
    Code (CSharp):
    1. protected void InitRenderParameters()
    2. {
    3.     rendParameters = new RenderParams(MeshMaterial);
    4.     rendParameters.worldBounds = new Bounds(Vector3.zero, Vector3.one * 256f);
    5.     rendParameters.motionVectorMode = MotionVectorGenerationMode.ForceNoMotion;
    6.     rendParameters.shadowCastingMode = ShadowCastingMode.Off;
    7.     rendParameters.lightProbeUsage = LightProbeUsage.Off;
    8.     rendParameters.receiveShadows = false;
    9.     rendParameters.camera = Camera.main;
    10. }
    11.  
    12. private void OnEnable()
    13. {   // 3 values * 4 bytes = 3 floats
    14.     const int size_of_float = 4;
    15.  
    16.     // Object buffers
    17.     colorsBuffer = new ComputeBuffer(64 * 64 * 64, size_of_float * 4);
    18.     positionsBuffer = new ComputeBuffer(64 * 64 * 64, size_of_float * 4)
    19. }
    20.  
    21. /*
    22. * UPDATE
    23. */
    24. void Update()
    25. {
    26.     HandleInput();
    27.  
    28.     // Draw meshes -> keep as last function in Update
    29.     DrawInstances();
    30. }
    31.  
    32. /*
    33. * MESH INSTANCING
    34. */
    35. protected void DrawInstances()
    36. {
    37.     /*int layer = 0;
    38.     Bounds bounds = new Bounds(Vector3.zero, Vector3.one * 256f);
    39.     Graphics.DrawMeshInstancedProcedural(
    40.         ResetCube, 0, MeshMaterial, bounds, positionsBuffer.count, null, ShadowCastingMode.Off, false, layer, Camera.main, LightProbeUsage.Off
    41.     );*/
    42.  
    43.     Graphics.RenderMeshPrimitives(rendParameters, ResetCube, 0, positionsBuffer.count);
    44. }
    45.  
    46. // Called once
    47. internal void Fill()
    48. {
    49.     int kernelIndex = computeShader.FindKernel("FillVoxel");
    50.  
    51.     computeShader.SetBuffer(kernelIndex, colorsId, colorsBuffer);
    52.     computeShader.SetBuffer(kernelIndex, positionsId, positionsBuffer);
    53.     computeShader.SetFloat(correctionId, -31.5f);
    54.  
    55.     computeShader.Dispatch(kernelIndex, 8, 8, 8);
    56.  
    57.     MeshMaterial.SetBuffer(colorsId, colorsBuffer);
    58.     MeshMaterial.SetBuffer(positionsId, positionsBuffer);
    59.     MeshMaterial.SetFloat(stepId, 1f);
    60. }
    Compute shader:
    Code (HLSL):
    1. [numthreads(8, 8, 8)]
    2. void FillVoxel(uint3 id : SV_DispatchThreadID)
    3. {
    4.     int index = index_1d(id.x, id.y, id.z);
    5.     _Positions[index] = float4(id.x + _Correction, id.y + _Correction, id.z + _Correction, S_ACTIVE);
    6.     _Colors[index] = float4(id.x / 64.f, id.y / 64.f, id.z / 64.f, 1.f);
    7. }
    8.  
    Positions gathering custom node:
    Code (HLSL):
    1. #if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
    2.     StructuredBuffer<float4> _Positions;
    3. #endif
    4.  
    5. float _Step;
    6.  
    7. void ConfigureProcedural () {
    8.     #if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
    9.         float3 position = (float3)_Positions[unity_InstanceID];
    10.  
    11.         unity_ObjectToWorld = 0.0;
    12.         unity_ObjectToWorld._m03_m13_m23_m33 = float4(position.xyz, 1.0);
    13.         unity_ObjectToWorld._m00_m11_m22 = _Step;
    14.     #endif
    15. }
    16.  
    17. void ShaderGraphFunction_float (float3 In, out float3 Out) {
    18.     Out = In;
    19. }
    20.  
    21. void ShaderGraphFunction_half (half3 In, out half3 Out) {
    22.     Out = In;
    23. }
    Color custom shader node:
    Code (HLSL):
    1. #if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
    2.     StructuredBuffer<float4> _Colors;
    3. #endif
    4.  
    5. float4 GetColor()
    6. {
    7.     #if defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
    8.         return _Colors[unity_InstanceID];
    9.  
    10.     #elif !defined(UNITY_PROCEDURAL_INSTANCING_ENABLED)
    11.         return float4(1.f, 1.f, 1.f, 1.f);
    12.     #endif
    13. }
    14.  
    15.  
    16. void ColorFunction_half(half3 Normal, out half3 Out, out half Alpha)
    17. {
    18.     half4 data = GetColor();
    19.     Out = data.xyz; // Out = Color;
    20.     Alpha = data.w;
    21. }



    Although performance is not affected much on PC (Just a few milliseconds), on mobile (Android, Snapdragon 732G, OpenGLES3) FPS drops drastically from 60 to an average of 20. What could be the possible cause of this performance instability?