Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

HDRP - Horrible framerate with pretty simple setup

Discussion in 'Graphics Experimental Previews' started by TchPowDog85, Dec 29, 2018.

  1. TchPowDog85

    TchPowDog85

    Joined:
    Dec 29, 2015
    Posts:
    124
    I'll start by sharing my PC setup so you know that's not the issue:
    CPU: i7 2700k
    GPU: GTX 1060
    RAM: 24gb

    So I have a basic scene. I have a 10'x10' plane (imported from Blender), it is 1 quad (2 tris). I placed a collider on it with a 2k texture(w/ PBR maps). On start, I instantiate and array of the plane prefab (200x200). Total of 20,000 prefabs. They are all set to static and I combine them using:
    Code (CSharp):
    1. StaticBatchingUtility.Combine(gameObject);
    Here is the game object:


    Here is the result on play:


    Notice the horrible framerate!

    This is the script attached to the plane object:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class CreateGround : MonoBehaviour
    6. {
    7.     public int gridSize = 10;
    8.     public GameObject plankPrefab;
    9.     private List<GameObject> allGameObjects;
    10.    
    11.     void Start()
    12.     {
    13.         for (int x = 0; x < gridSize; x++) {
    14.             for (int z = 0; z < gridSize; z++) {
    15.                 if (x + z != 0) {
    16.                     Renderer gameObjectRenderer = plankPrefab.GetComponent<Renderer>();
    17.                     Vector3 position = new Vector3(gameObjectRenderer.bounds.size.x * x, plankPrefab.transform.position.y, gameObjectRenderer.bounds.size.z * z);
    18.                     GameObject newPlank = Instantiate(plankPrefab);
    19.                     newPlank.transform.position = position;
    20.                     newPlank.transform.parent = transform;
    21.                 }
    22.             }
    23.         }
    24.         StaticBatchingUtility.Combine(gameObject);
    25.  
    26.     }
    27.  
    28.  
    29.     void Update()
    30.     {
    31.        
    32.     }
    33. }
    34.  
    This is what the Profiler says (I don't really know how to dissect this):


    Any advice?
    Thanks, guys!
     
  2. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    upload_2018-12-29_18-40-58.png

    They're not merged. You are still brute force drawing everything and HDRP is struggling to batch them for you (assuming the experimental batcher in the HDRP config asset file is enabled).

    Also static batching is for huge chunks of geo (on non-instanced or old hardware), not for a lot of quads. The absolute worst-case scenario for static batching is what you just did.

    What happens in this case is static batching will perform the same as not batching them at all, and really, static batching + dynamic batching are both redundant with HDRP anyway (it's own batcher is by far more efficient, assuming gpu instancing).

    If on HDRP:

    1. don't use dynamic or static batching - both are more expensive than instancing
    2. enable the SRP batcher
    3. merge your meshes properly

    If merging meshes isn't something you want to do, use DrawInstancedIndirect to draw 20,000 quads. It should not take long to render in that case (60fps on a decent mobile would be realistic).
     
  3. TchPowDog85

    TchPowDog85

    Joined:
    Dec 29, 2015
    Posts:
    124
    Combining them did the trick. Thanks!
     
  4. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Yeah although I really need Unity to start putting good practises info out better because everyone still, a decade after static batching was added, don't realise that it performs badly with lots of little meshes. Pretty much everyone got that wrong. Also, dynamic batching consumes large amounts of CPU time that is (in my testing) always slower than just using GPU instancing tickbox on material.

    In any case, there are even faster ways to do what you want but if it's sufficient now, who cares? :)
     
    AcidArrow likes this.
  5. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    12,891
    Hi,

    I use the HDRP Lit shader and enabled GPU instancing for objects copied and scaled - rotated around, but the batches are still enormous (like 3000) and "saved by batching' metric reports a minus -2000, is this meaning the batching is working ? The objects are in constant motion.
     
    Yohan_Lim likes this.
  6. interpol_kun

    interpol_kun

    Joined:
    Jul 28, 2016
    Posts:
    134
    Can you elaborate? Also, what is the best way to render a lot of small identical objects?
     
  7. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,001
    This is a necro of an old thread, but in any case, if the meshes are close by, you might as well merge them before hand.

    Static batching does merge the meshes, but it also keeps the visibility bounding boxes and vertices for each one, so it can perform culling and turn on/off parts of the mesh.

    And if you use tons of small meshes, which results in a lot of data that culling has to go through, "just render all of them" quickly becomes faster than "try to figure out if you can turn off a few".
     
    Last edited: Mar 1, 2020
    hippocoder and interpol_kun like this.
  8. valarus

    valarus

    Joined:
    Apr 7, 2019
    Posts:
    430
    How do you merge them before hand ? You mean parent them as one object?
     
  9. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,001
    I just do the placement in my DCC software directly these days. (copy paste the tris).

    If you already have a placement you like, you can select all meshes, export as FBX (with Unity's FBX exporter, although not the latest one, because the latest one does not work), open in Blender/Modo/Whatever, merge them all in one mesh, then use that instead of the many meshes.

    It would be nice if Unity had an easy way to merge meshes at build time, since doing the above, loses you some flexibility in easily updating the models at a later date. It's supposedly scriptable with Mesh.CombineMeshes ( https://docs.unity3d.com/ScriptReference/Mesh.CombineMeshes.html ), but I have never gotten a script that uses that to work properly, but maybe it's just me.
     
  10. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Combine them into groups of objects without static batching, or use https://docs.unity3d.com/ScriptReference/Graphics.DrawMeshInstancedIndirect.html or similar instancing...

    What happens when you use lots of small objects with static batching is it will consume much more memory, do more work etc, culling still has to be done. When you have lots of small things pre-merged it culls the one merged mesh obviously, a big CPU saving. Static batching is an old technology, I don't see the point of it, it should be replaced by HLOD.
     
  11. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    The stats window is broken especially with SRP. For a confirmation you need to use the frame debugger.

    HDRP lit shader is already batching, it's not using "gpu instancing" on the material. Instead it uses SRP batcher (if enabled). Both cannot run at the same time and SRP batcher is higher performance, so Unity ignores the material setting in this case.

    But for speed, see drawmesh instanced indirect for fastest, then drawmesh instanced and then SRP batcher, then regular GPU instancing option in that order for meshes which should remain separate.

    All of this is solving dynamic stuff though. GPUs prefer big beefy jobs with no interruptions where possible.
     
    Ofx360 likes this.
  12. Korindian

    Korindian

    Joined:
    Jun 25, 2013
    Posts:
    584
    In addition to the frame debugger as @hippocoder mentioned, there is an SRPBatcherProfiler.cs script in a github link mentioned in this blog post which you can use to see the performance of the SRPBatcher.
     
  13. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    12,891
    Thanks for all the input and hints, will check towards this direction for the debugging.
     
    hippocoder likes this.
  14. Neogene

    Neogene

    Joined:
    Dec 29, 2010
    Posts:
    92
    I can't find the SRP Batcher selecting the settings on HDRP latest version 7.3.1, someone could point to the right area?
     

    Attached Files:

  15. valarus

    valarus

    Joined:
    Apr 7, 2019
    Posts:
    430
    I think it's in the editor/player settings of Unity editor not HDRP asset itself.
     
  16. Grimreaper358

    Grimreaper358

    Joined:
    Apr 8, 2013
    Posts:
    789
    The option got removed and by default, the SRP Batcher is enabled. You can only disable it by code
     
    MassimoFrancesco and Neogene like this.
  17. Ymmersive

    Ymmersive

    Joined:
    Jul 6, 2017
    Posts:
    7
    In HDRP 7.3.1, the SRP Batcher is enabled by default. It can be toggled by clicking the 3 vertical dots in the upper right corner on the Inspector of the HDRP Asset, then enable the Debug window.