Search Unity

[0.8.4] Case 1153579 - Material loaded from build fails to render with DrawMeshInstanced

Discussion in 'Addressables' started by bitinn, May 11, 2019.

  1. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542
    Case 1153579 summary

    1. What happened

    We reproduced a bug where using Addressables + DrawMeshInstanced together with "Strip All" shader variant stripping feature under Graphics settings, cause Material in use to not render in the Player build, even when the build includes appropriate shaders. (We can also verify this behaviour in the Editor using "Packed Play Mode").

    This issue doesn't appear when either:

    - Shader instancing variant stripping is set to "Strip Unused"
    - When the scene is using DrawMesh instead of DrawMeshInstanced.

    2. How we can reproduce it using the example you attached

    We included 4 zip files, each includes:

    - Minimal repro project, where SampleScene 1 and 2 use DrawMesh and DrawMeshInstanced respectively.
    - A build of SampleScene 1, where we demostrate DrawMeshInstanced failed to draw material, even though the same instancing variant shader exists in scene, and is rendered properly with MeshRenderer
    - A build of SampleScene 2, where we demostrate DrawMesh isn't affected when using the same packed content.
    - A build of SampleScene 1, with shader instancing variant stripping set to "Strip Unused", where DrawMeshInstanced draw these materials just fine.

    See attached screenshots for reference.

    Screen Shot 2019-05-11 at 16.11.13.png Screen Shot 2019-05-11 at 16.11.23.png

    (I spend half a day isolating this issue, hopefully someone can look into it!)
     
  2. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    912
    thanks for the repro and the detailed steps!
     
    bitinn likes this.
  3. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    912
    Now that I've read and replied to the other thread on roughly the same topic (https://forum.unity.com/threads/0-7-5-clarify-how-shader-stripping-affect-addressable.672895/) I'm a little confused.

    Why are you using "Strip All". It, well, strips all. So what exactly are you expecting to happen if you strip all the shader variants? The shaders generally won't work with "strip all" on. There may be some scenarios, where either your usage is very specific, or you are using assets built into the player (scenes in the scenes list), where it might work, but I really don't understand even trying.

    If you have a thing that uses a shader a particular way. And you have a graphics option to "remove that way the shader is used". Why would you turn that on? "Strip unused" is the recommended setup.
     
  4. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542
    There is a good reason for that: reduce shader compilation time during build.

    That's really why people use ShaderVariantCollection: you specify exactly the shader variant you want (instancing or otherwise), so that Unity does less work.

    https://forum.unity.com/threads/compiling-shader-variants-taking-ages.527724/
     
  5. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542
  6. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    912
    Using strip all does improve compile time, by stripping all shader instances. This should be ok, unless you use DrawMeshInstanced (https://docs.unity3d.com/ScriptReference/Graphics.DrawMeshInstanced.html).
    Of note, some of our systems call that under the hood. I believe particles, and perhaps terrain are examples. I'm not sure what others.

    Things baked into scenes are special, as data is flattened into the scene regardless of what settings you have. So the example where your in-scene box shows up, and the others don't are because the scene ignores your strip setting.

    So, long story short, this isn't an addressables problem. You have told the build to strip all shader instances, and then you have asked your game to draw something with a shader instance. This won't work. You may be able to get some good alternative ideas on the graphics forums, but I don't really have any suggestions other than turning off "strip all".
     
  7. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542
    I think there is a lingering question here: Does Addressables support loading instanced shader variant through ShaderVariantCollection? Your answer suggest it does not.

    Basically there is now a very confusing issue on when does the shader stripping took place: the shader is in the asset bundle created by Addressables, and we can load it, but we cannot use it to render, so was it stripped or not? what exactly was loaded anyway?

    I don't think most developers are equipped to answer this question, and they will have to fallback to Strip Used because the confusion here.
     
  8. unity_bill

    unity_bill

    Unity Technologies

    Joined:
    Apr 11, 2017
    Posts:
    912
    ShaderVariantCollection controls which variants exist and are primarily used for shader warmup. See https://docs.unity3d.com/ScriptReference/ShaderVariantCollection.html

    Shader instances are a completely different thing. Instances are needed if you choose to use DrawMeshInstanced.

    You are telling Unity to remove all instances, then add some variants, and are expecting that to add instances back in. It won't. Instances and variants are not the same thing.

    The Unity shader system is very complex, and at times unintuitive and potentially buggy. They are fixing/improving a lot of that with the new scriptable render pipelines. I'd suggest heading over to the graphics forums to see if you can get clarity. This section of the forum won't contain the experts you need.

    -Bill
     
  9. bitinn

    bitinn

    Joined:
    Aug 20, 2016
    Posts:
    542