can IPreprocessShaders check SubShader LOD?

I have several custom surface shaders defined with LODs, like this:

SubShader{ LOD 400 }
SubShader{ LOD 500 }
SubShader{ LOD 600 }

On PC, I let users change their Shader.globalMaximumLOD, works great. On Consoles, it just means a lot of memory wasted on book keeping these shader variants. I figured I could strip them, via IPreprocessShaders, but there does not seem to be a clear path.

Is there some way to do this?

Hi!
I don’t think there’s a way to do that right now.
I’ll write this down as a feature request :slight_smile:

Damn, I see. Hopefully it can be done relatively soon, kinda desperately grasping at ways to lower runtime memory with shaders (we have a lot).

Any tips for ways I could go about something similar? My next idea was adding tags to sub shaders, but there doesn’t seem to be a way to strip by tags either.

edit: I think for now I’m just going to refactor things to not use SubShaders, and instead just use a multi_compile. In our case this seems feasible.

Yes, using multi_compile for this is a good alternative for now.

1 Like

It works for our game thankfully. However, I can still see some valid use cases. For example, what if I want to toggle tessellation on one .shader file via subshader LODs, and want to strip out the tessellation variants from the build? My current solution for that is actually just making two .shader files, not very elegant, but its an okay workaround.

As I said - feature request added :slight_smile:

1 Like

Has this feature been released?

Yes! :slight_smile:

Thanks. My project uses 2020.3, looks like we need to upgrade the version to 2021.2.

Hey, just want to know can I manually strip shader variants that generated by subshaders that have a specific tag? Currently, the ShaderCompilerData provided by IPreprocessShaders.OnProcessShader only allows me to check shader keywords.

Hi thank you for the reply.

I checked that API, but it seems it needs a ShaderData object, which although can be created by a Shader object, how can I then strip shader variants from that shader object? As I understand, IPreprocessShaders.OnProcessShader provides a list of ShaderCompilerData, from which we can remove unnecessary ShaderCompilerData to strip shader variants, but how can we do it with the shader object itself?

OnProcessShader has three parameters. You can create a ShaderData object from the first one, get the subshader index from the second one (snippet.pass.SubshaderIndex) and check the tags of this subshader. Then you know whether it’s currently processing a subshader with the tag you’re interested in or not.

Thank you very much for the detail.

So when I know it’s currently processing a subshader with the tag I’m interested in, then I just set the third parameter, which is the list of ShaderCompilerData to an empty list? What I want to do is to strip shader variants generated by that subshader. I thought OnProcessShader is called per shader, and the shader variants generated by other subshaders, which I won’t strip are also in that list. Is the OnProcessShader actually called per subshader, or is there any other misunderstandings?

Yes.

It can be called multiple times per shader stage of a specific pass, depending on the number of variants.

1 Like

I see it. Thanks, aleksandrk! Your help is very much appreciated.

1 Like