Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Why is a URP Simple Lit shader so large in memory?

Discussion in '2022.1 Beta' started by creat327, Mar 29, 2022.

Thread Status:
Not open for further replies.
  1. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    I've been checking why my Android device runs out of memory since I migrated to URP and it was running fine using the built-in render pipeline... to find out that Unity shaders take a huuuuuuuge amount of memory on the device.

    URP Simple Lit on android device compiled for opengl 3.0 is about 38 megas. To give you an idea, my terrain meshes, all game meshes and most of my textures combined... take less RAM than the URP Simple Lit shader.
    It is in fact the LARGEST item in memory for the whole game.

    Oh, and I have all the built settings set up for stripping the shaders variants and all.

    So what's going on? That's a single shader. If I start to combine shaders it gets crazy quick on mobile.

    Here is a snapshot of the memory profiler.
    memory2.jpg
     
    Last edited: Mar 29, 2022
  2. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,055
    How many variants of this shader do you have in the build?
    You can check this in the Editor.log, it prints the stats when doing a build.
     
  3. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    We found Unity's shader stripping rather lackluster, rolling out our own reduced the size of shaders by more than a 10 fold.

    What we do is enable shader compilation logging (its a player setting), and let our game run for a while. This will give you an exact list of what shader is used, with what variant, pass etc. Then using an IPreprocessShaders you can strip out the shaders that arent used. One downside is that your buildflow is now kinda wack, you need to make a clean unstripped build every time a new variant is included, to collect it.

    For example without stripping we've even seen META passes get compiled into the game. This is especially bad on platforms with shared memory.
     
  4. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    Yeah, I had to manually edit the shader and remove chunks of code to reduce it to about 3 mb. Still, 3mb for a shader is horrible, and this is URP which should be ok for mobile.

    Answering the question about variants, I don't need to check the log, I can see it compiling about 1400 variants when I build. With stripping enabled and the settings set for only 1 directional light and depth camera. On android OpenGL 3.0

    To give you an idea, on built-in with exactly the same image quality and more settings enabled (I had to disable tons so that it would run at a decent fps on URP)... it takes less than 1/4 the memory of URP.

    Definitely not happy with URP and its current state. But at least begin by reducing the RAM requirement... I can't imagine the huge amount of unused code that must be there to generate 38 mb from a single shader on mobile. Isn't this larger than the whole Unity engine compiled on mobile? Just one shader...
     
    ImpossibleRobert likes this.
  5. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,055
    Which Unity version do you use?
     
  6. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    latest b14 right now
     
  7. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    3,055
    URP added a lot of features in 2021.2. Most of that should be handled by the stripping that is shipped with URP, though, so I'm surprised to see you mentioning it compiles 1.400 variants. Did you tweak URP settings? They drive the amount of variants that end up in the build.
     
  8. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    Yep, but it’s easy to test. Steps:
    1) create new urp project, empty. Settings for mobile android OpenGL 3.0. Set the usual mobile optimizations, but enable shadows and depth buffer. Also make sure to set shader variant stripping on. I just want to prove that the default settings without going into manually editing shaders are not right.
    2) add a plain cube. Set material to Lit Simple… because it’s mobile and we want it light and fast.
    3) add a basic terrain. As basic as you want. Any texture setup. Try to make it super small if you want to. Or large. It doesn’t matter for the shader as long as you have a texture there.
    4) add a light and make shadows available for the project.

    compile and run on the device. It should work fine. I won’t comment on the fps (it’s crap compared to built in doing the same). But let’s focus on the memory for now.

    open the memory profiler and take a snapshot of the device. Do you think Unity is doing a good job with the shaders size? What results do you get? My device ram is consumed primarily by the shader. By a large amount.
     
    Last edited: Mar 31, 2022
    elZach likes this.
  9. Spikebor

    Spikebor

    Joined:
    May 30, 2019
    Posts:
    288
    This is a brilliant way to do the shader stripping. Will employ this idea for my game, thank you.
    It's especially great when you do this at the end cycle of the development, as so we know no more shader variants will be added afterward. For during development, I recommend just strip unused shaders instead of doing this procedure every build.
     
  10. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    Do you mind sharing that script?
     
  11. TJHeuvel-net

    TJHeuvel-net

    Joined:
    Jul 31, 2012
    Posts:
    838
    Sorry i cant do that, but with the gist of what i explained you should be able to make it!

    Its based on this (non unity) blogpost: https://therealmjp.github.io/posts/shader-permutations-part2/
     
    Last edited: Apr 6, 2022
  12. dnach

    dnach

    Unity Technologies

    Joined:
    Mar 9, 2022
    Posts:
    90
    An older forum post by Christophe Riccio provides information on scriptable stripping:
    https://blog.unity.com/technology/stripping-scriptable-shader-variants
    The general idea is to strip shader variants based on keywords/combinations that are not needed at runtime.
    We are currently working to provide up-to-date documentation.

    For URP shaders, a good practice is to also check the Render Pipeline Assets and disable any features that are not needed: https://docs.unity3d.com/Packages/c....universal@12.0/manual/universalrp-asset.html
    Also, in the URP global settings, ensure the stripping settings are enabled:
    https://docs.unity3d.com/Packages/c...niversal@12.0/manual/urp-global-settings.html
     
    hippocoder likes this.
  13. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    @dnach all that is a given. Doing all that, the URP shader is larger in RAM than the whole unity engine. You can test it yourself, just create a terrain and paint it a bit, nothing else, disable everything you want. Enable stripping. Optimize the hell out of it. Build and run on android. Check the memory profiler. See all the junk loaded from the URP terrain shader and tell me that is normal and cannot be improved.

    Repeat the process using built-in render pipeline. Use the terrain diffuse shader, not the PBR that nobody uses in mobile if they want performance and that it spilled over URP. Check the memory on the android device.

    RAM in terrain shaders in URP: 180 mb.
    RAM in terrain shader in built-in: 5mb

    Don't blame it on the user and how they set it up please. URP is so unoptimized and so memory hungry it's insulting.
     
    ilia_infable and lclemens like this.
  14. dnach

    dnach

    Unity Technologies

    Joined:
    Mar 9, 2022
    Posts:
    90
    @creat327 We are currently working on immediate and longer term solutions to improve shader variant management as a whole, including reducing the runtime memory usage of shaders.

    We understand this is a big pain, and are not taking it lightly!
     
    hippocoder and JesOb like this.
  15. creat327

    creat327

    Joined:
    Mar 19, 2009
    Posts:
    1,756
    Thanks, but at this point, fewer words and more actions. It's version 14 of URP with countless versions in between. I'm sorry if I sound negative, but Unity made me like this.
     
    JasonFPL and Reahreic like this.
  16. dnach

    dnach

    Unity Technologies

    Joined:
    Mar 9, 2022
    Posts:
    90
    Several immediate improvements will be released in beta soon, and will soon share more information on the expected release and when you'll see backports.

    One of these improvements is dynamic shader loading, to allow controlling runtime memory usage for shaders:
    https://portal.productboard.com/8ufdwj59ehtmsvxenjumxo82/c/1457-dynamic-shader-loading

    Edit: you can find more detail on the above, as well as general guidelines and other useful information about shader variants logging and stripping, in the following post:
    https://forum.unity.com/threads/improvements-to-shader-build-time-and-runtime-memory-usage.1305615/
     
    Last edited: Jul 11, 2022
    LeonhardP, Rallix and hippocoder like this.
Thread Status:
Not open for further replies.