Search Unity

Question A question on how much shadergraph optimizes unused code

Discussion in 'Shader Graph' started by dgoyette, May 1, 2019.

  1. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Two similar questions:

    First, let's say I have some nodes in a graph that aren't actually plugged into the Master output node. Do those nodes end up having any impact on the performance cost of the shader? Or are they ignored if they're not connected to the output node?

    Second, let's say I have a subgraph like this:

    upload_2019-5-1_12-49-3.png

    If I end up using only one component of the output of this subgraph (that is, if I only use the "x" component of this subgraph in my shader), does shadergraph still compute the y and z components, even though they aren't used? Or does shadergraph need to perform the "combine" node in entirety before passing the full Vector3 to the output node? I'm trying to decide how general or specific my subgraphs should be. The more general, the more reusable, but that might not be worth it if it's computing a bunch of stuff it doesn't need.
     
  2. alexandral_unity

    alexandral_unity

    Unity Technologies

    Joined:
    Jun 18, 2018
    Posts:
    163
    If nodes are not connected to the output of the master node, they aren't compiled into the final shader at all. They only live inside of the graph window, but not the shader in the scene. That being said, for the most part, all nodes are calculated even if only one of their output ports are connected. The only exception to this would be nodes with parameters (drop down menus, etc) inside of the node. Only the selected drop down option gets compiled.

    Specifically your question about the combine node, yes, all of the components are being calculated even you're only using the X or Y etc.
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    This will increase compile times, but generally not increase the cost of the shader vs. a node with only one output that does only the work required to produce that value.* That's because shader compilers are generally smart about removing unused code.

    There's a big asterisk there because it's possible that "one output" could be calculated another way that would produce the same results more cheaply. Shader compilers generally won't fix that.
     
    Last edited: May 2, 2019
    alexandral_unity and dgoyette like this.
  4. JonPQ

    JonPQ

    Joined:
    Aug 10, 2016
    Posts:
    120
    is there a way to see the cost of each node? or the overall cost of the shader in number vertex and pixel instructions and texture reads? this used to visible in compiled shaders in unit 4 and 5, but I can't find any performance info in shadergraph, or by exporting the compiled shader and searching in the code.
     
  5. bgolus

    bgolus

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

    Not in the UI, no.

    Still exists for Unity 2019 and 2020, assuming you're compiling to a platform that shows that data.

    If by "exporting" you mean right click on a node in the Shader Graph and click on "Show Generated Code", then no. That's the uncompiled shader that the Shader Graph generates. That can be pasted into a .shader file and it'd work like any "regular" vertex fragment shader, because that's what it is. If you want to see the compiled shader, which shows the stats, you can copy the generated shader code into a .shader file and click on the "Compile and show code" button in the inspector for that ... or just select your Shader Graph asset in the project view and click on the same inspector button. It exists for Shader Graph shaders and .shader vertex fragment shaders alike.
     
    JonPQ likes this.
  6. JonPQ

    JonPQ

    Joined:
    Aug 10, 2016
    Posts:
    120
    Thanks much !
    I have tried right clicking, and pasting into a new shader file, then clicking compile and show on that shader, I also tried adding #pragma debug into that shader... but I don't see anything that looks like the output it used to show...
    for example...a simple list of.... Vertex shader instructions :20 texture reads:3. etc.....
    I am currently on a mac, in build target PC, Mac and standalone... maybe I should switch to iOS and try that ? or maybe the data is there, but described in a different way?
    thanks again !
    Possibly it just lists things differently since changing to hlsl.

    I tried build target as pc/mac and iOS... but the compiled output looks the same.
     
    Last edited: May 22, 2020
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    They changed to HLSL over 5 years ago and deleted everything actually Cg based shortly afterward, they just didn't bother renaming all of the files that ended in ".cginc" to ".hlsl" or change
    CGPROGRAM
    to
    HLSLPROGRAM
    until the SRPs. You could of done that 5 years ago though and it would have worked.

    What you're describing sounds to me like the old OpenGL compiled shader output. I'm guessing you're now seeing the Metal output, which is what Unity now defaults to on the Mac. But I honestly have no idea because I'm not a MacOS dev and I only recently even found out that compiling shaders for OpenGL on Macs shows similar stat values as Direct3D does on Windows. There's no such stats for OpenGL on Windows.
     
    JonPQ likes this.
  8. JonPQ

    JonPQ

    Joined:
    Aug 10, 2016
    Posts:
    120
    thanks for the info bgolus
     
  9. VincentAbert

    VincentAbert

    Joined:
    May 2, 2020
    Posts:
    123
    I have an additional question on the matter : let's say I would like to have to make a modular shader where I use booleans to choose whether I want to use a detail map, whether I want to height blend some vertex painting etc.

    Is there a way to set up the graph so that if the boolean is false in the material, part of the graph is excluded from the code, to optimize it ? Or is that just not how shaders work ? Because I can see how I could use the booleans node and a Lerp to disable features, but it would still take the whole graph into account.

    On a related matter : is it heavier to to use the channel of a map that's used ? What I mean is let's say I have a detail map in the alpha channel of my albedo, would a shader that doesn't use it be faster, or does the renderer have to load every channel, even unused ?

    I'm very much a beginner and have a lot to learn, thanks a lot !
     
  10. alexanderameye

    alexanderameye

    Joined:
    Nov 27, 2013
    Posts:
    1,383
    You can use keywords for this. Add keywords in the blackboard and set them to 'shader feature'. This will result in 'shader variants' though and so increased compile times. There is also a limit of 128 variants but you can increase this in the shader graph preferences.
     
  11. Ruzzbug

    Ruzzbug

    Joined:
    May 23, 2018
    Posts:
    1
    Does it still compute everything before the boolean keyword in this case?
     
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    No. Keywords generate completely different versions of the shader internally with only that code which is on the active side of the Keyword Node.