Search Unity

Resolved Vertex shader called multiple times?

Discussion in 'Shader Graph' started by GameDeveloper1111, Jan 6, 2021.

  1. GameDeveloper1111

    GameDeveloper1111

    Joined:
    Jul 24, 2020
    Posts:
    100
    I'm new to shaders and made a Shader Graph that inflates a mesh along its normals, using the Lit shader Master Stack. I noticed that the code generated from the Lit-shader-based Shader Graph has multiple passes and it seems that each pass recomputes the vertex displacement.

    If each pass does recompute the vertex displacement, is there a way to avoid this? I would like to compute the vertex displacement once and then have each pass use the result.

    Here's the Shader Graph:

    upload_2021-1-6_14-27-11.png

    Here's the Scene view result with a sphere collider for reference:

    upload_2021-1-6_14-26-9.png

    Here's the generated code corresponding to the vertex displacement:

    Code (CSharp):
    1. VertexDescription VertexDescriptionFunction(VertexDescriptionInputs IN)
    2. {
    3.     VertexDescription description = (VertexDescription)0;
    4.     float _Float_ea07e58a9c3e49a59d9d8f1223cb4d31_Out_0 = 0.5;
    5.     float3 _Multiply_23975ed8aacd4318aafbf99ccf9222ee_Out_2;
    6.     Unity_Multiply_float(IN.ObjectSpaceNormal, (_Float_ea07e58a9c3e49a59d9d8f1223cb4d31_Out_0.xxx), _Multiply_23975ed8aacd4318aafbf99ccf9222ee_Out_2);
    7.     float3 _Add_a1315b18917244fea035f817669fbddc_Out_2;
    8.     Unity_Add_float3(IN.ObjectSpacePosition, _Multiply_23975ed8aacd4318aafbf99ccf9222ee_Out_2, _Add_a1315b18917244fea035f817669fbddc_Out_2);
    9.     description.Position = _Add_a1315b18917244fea035f817669fbddc_Out_2;
    10.     description.Normal = IN.ObjectSpaceNormal;
    11.     description.Tangent = IN.ObjectSpaceTangent;
    12.     return description;
    13. }
    The names are obscure but you can see that the Add, Multiply, and so on correspond to the Shader Graph above.

    Here's the Find results, showing 16 calls to the vertex displacement code:

    upload_2021-1-6_14-38-9.png

    The pass named "ShadowCaster" calls it, as well as the passes named "META" and "ScenePickingPass", and so on.

    In my use case I'll be displacing 28,000 vertices per frame and modifying 28,000 normals per frame.

    I'm not advanced enough yet to know how to profile this to answer my own question, but I'm working on it. Thanks in advance for any help.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Yep.

    Technically yes. You could modify the mesh via the CPU side c# instead. But that’s way, way slower. So don’t bother.

    GPUs are really good at doing basic math. Especially the same bit of math over and over. This is what GPUs are designed to do. And the bit of math to expand the mesh is an utterly inconsequential amount of math compared to how much math it’s going to do per vertex anyway.
     
    GameDeveloper1111 likes this.
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    It’s also important to understand, many of those passes aren’t called every frame anyway. Some are just for the editor, like meta and scene picking pass. The meta pass is used for in editor light map generation, and the scene picking pass is for ... well ... scene picking. When you click in the scene view, that pass is used to render your object to check if it’s under your cursor.

    That said also it’s totally normal for a single object’s to get rendered several times. Even in a relatively basic scene setup with one light and camera, the object might get rendered 5 times, or more, and that’s totally normal.

    The thing you have to try to understand with GPUs is that memory bandwidth & usage patterns often have a much bigger impact on performance than the work shaders do, or redo. It’s often much cheaper to recalculate something over and over than it is to store it someplace and access it again.
     
    GameDeveloper1111 likes this.