SRP Batch Problem : Node use different shader keywords

I am having an issue where the Frame Debugger reports to me that a batch is broken due to using different shader keywords.

However, Frame Debugger is not reporting the use of any keywords at all.

My shader was made in Shader Graph, and I am using 2018.4.2f1, and the preview package of LWRP.

Here is a screenshot illustrating my problem. Does anyone know what might be going on?

Is there a way for me to print to my console log what keywords every shader in my scene is using?

So, I discovered that the Frame Debugger does not accurately report all Shader Keywords, at least in the case of the SRP used in 2018.4.2f1. So, while my above screenshot made it appear the two broken batches had no keywords, at least one of them did.

For anyone else who may run into this problem, I was able to solve it gathering all of the keywords from a material using this Unity - Scripting API: Material.shaderKeywords

Then I set each one of my different Materials that use specific shaders to occupy a different part of the RenderQueue in increments of 50.

Finally, I created a Dictionary so that each unique keyword combination would receive a “modifier” value, and thus each Shader+Keyword combo would reside in its own unique RenderQueue number. I am assuming there will not be more than 49 unique combos, thus I will not enter another Shader’s designated RenderQueue window. This system could be improved of course, but it works for my purposes.

//This block of code is for more efficient SRP Batching, because a batch will break if Keywords are different
//We group their RenderQueue numbers together based on their keywords
if (newMat.shaderKeywords.Length > 0)
{
    var keywords = "";

    foreach (var s in newMat.shaderKeywords)
        keywords += s + ",";

    //Debug.Log(string.Format($"{newMat.shader.name} has additional keywords: {keywords}"));

    if (!keywordRenderQueueModifier.ContainsKey(keywords))
        keywordRenderQueueModifier.Add(keywords, keywordRenderQueueModifier.Count + 1);

    //Debug.Log(string.Format($"keywordRenderQueueModifier[{newMat.shader.name}][{keywords}]={keywordRenderQueueModifier[newMat.shader.name][keywords]}"));
    newMat.renderQueue += keywordRenderQueueModifier[keywords];
}

As far as I am aware, modifying the RenderQueue is the only way to manipulate the batcher into not jumping around between things (and thus breaking batches) in a way I don’t understand myself.

2 Likes

Could this have anything to do with Local vs Global Keywords? Total shot in the dark but it sounds like setting a global keyword might effect shaders that do not care about that keyword after the keyword has been set.
Probably wrong but worth a test.

For anyone else who comes across this thread, I just want to add that you can set the inspector to debug mode and see all the keywords that are being saved to your materials. I was able to significantly reduce batches by simply clearing keywords that had been left behind by an earlier shader.

10 Likes

You are Awesome!

1 Like

OMG, you’re such a life saver man ! so glad I’ve found your post early in my investigation. This sort of mistake on unity part could’ve taken me couple days to figure out :open_mouth: … Also i’m really hard at work trying to find the proper method to actually make a RemoveRemnantKeyword() function to automatically parsed a project … but so far i’m unable to properly access this string apart from the actual .mat file in text format

1 Like

Were you able to find out how to access the m_InvalidKeywords section of the file? I couldnt find anything either on the asset importer

I’m not convinced these are breaking batching, I couldnt reproduce it, but to remove them all from the materials in the project, I just used notepad++ and this regular expression to find and remove all of the invalid keywords

.m_InvalidKeywords:\n( - \w\n)*

8786461--1193479--upload_2023-2-6_23-13-26.png

1 Like

The m_InvalidKeywords field has no effect on batching whatsoever.

I’m having this same issue. It can be seen in this 5 consecutive batches, which break even though the frame debugger reports the same keywords for all of them. Using the latest Unity 2021 LTS

I’m on the process of removing keywords from shaders, so the materials used in this cases were created when the shaders had keywords that made them different. I’ve clicked on all the materials and made sure using the debug mode in the inspector that there’s no keywords inside the valid keywords array (all the remaining keywords are set globally, none on the material).

EDIT:
I was able to find the problem.
The batcher breaks in between lightmapped and not lightmapped objects even if the shader doesn’t have #pragma multi_compile _ LIGHTMAP_ON. Having any value in the “lightmap index” variable of the render, which gets set by the lightmapper or can be also set manually, breaks the SRP batcher even though all it should do is set the LIGHTMAP_ON keyword and pass the lightmap, scale and offset parameters (for simple lightmaps at least, dual lightmaps have more stuff but I don’t use them so idk).

@forestrf Please report a bug. Thanks!

Done! CASE IN-64130

This bug should only affect those who use a shader where lightmapping is behind a dynamic branch instead of a different shader variant, which is probably rare, but not impossible. I don’t know if it also breaks in between different lightmap indices, only that it breaks in between lightmapped and not lightmapped independently of the shader having or not LIGHTMAP_ON or other keywords.

1 Like