[SOLVED] 64 Keyword Limit questions

So I found out that we are limited to 64 keywords via Unity’s shader documentation, and naturally had a few questions:

  • How does the system count the number of keywords? Does it include ones that are only ever defined within a shader and not used outside it? Is it limited to those defined as part of #multi_compile directives?
  • The documentation says it applies to all shaders in a given project. So does that mean I can reduce the count by removing shaders I am not using?
  • Is there any way that I can see the current keyword total for my project?
  • Why does Unity even have this seemingly arbitrary keyword limit? Is it some kind of hardware limitation? Is it a legacy thing?
  • Is there a limit on the number of #multi_compile directives a shader can have, or is the keyword thing the only real limiting factor?

Thanks for any help you can provide.

No one probably knows everything for sure (unless it has been posted somewhere), as it is likely handled within the unity shader compiler and unity itself, but for what I would assume:

  • I don’t know how the keywords are counted. I can only assume this is being done when the compiler does its work and keeps track of it. Not sure what you mean with defined outside of the shader, but considering the doc talks about shader variants, I think it’s safe to assume it only counts for the mulit_compile directives.
  • Likely, it depends if the count is being done for the shaders that are being used during play or in the editor.
  • Not that I know, but you can always count by hand :stuck_out_tongue:
  • Perhaps the compiler starts to have trouble when going over more than 64. Who knows.
  • Only one way to find out, not sure if you want to have 64 variants in one shader though.

Not that much help I’m affraid, but it’s something :slight_smile:

This counts all the keywords ever seen, in the whole project. Basically, each keyword is assigned a number, and there can only be 64 of them. In all shaders in the whole project that were ever loaded.

FYI, Unity 5.0 will very likely increase the limit to 128.

Yes.

No, not really :expressionless:

We use a bitmask to select the “most appropriate shader variant”, and having up to 64 keywords in total allows that bitmask to be conveniently represented as a 64 bit integer. 64 bit integer operations are reasonably fast.

No, the maximum number of keywords is the only limitation.

For Unity 5.0, we’re planning to make it easier to not “use up” two keywords for simple on/off features. E.g. if you want to do a “#pragma multi_compile FOO_OFF FOO_ON”, then it should be possible to represent this with just a single keyword - if it is not set, then it’s off; otherwise it’s on. So in 5.0 we’ll have a multi_compile syntax to enable that.

2 Likes

Wait, this is two things. There’s “all shaders in the whole project” and “all shaders in the whole project that were ever loaded”.

I’m using only a handful .shader files in the final output, but like to have 100s of imported assets (sans their scripts) “in the project” for quick & easy reference, 99.5% of those don’t ever make it into the build. (But how else to instantly access any assets I own during prototyping and technique-researching without even alt-tabbing, let alone lengthy unpack-and-import procedures all the time.) So anything that isn’t referenced in any Scene or is in a Resources folder or in the “always included shaders” list shouldn’t be counted “part of the project” IMHO, especially as far as shaders are concerned.

Since I imported Skyshop yesterday, I keep getting the “Maximum number (64) of shader keywords exceeded, keyword AZ_EMIT_REFL will be ignored”, this keyword isn’t known to me, isn’t used in any shaders that are ever loaded by my scene, 100% guaranteed. I can still enter Play Mode but I suppose next time I wanna Build this error will bite me.

I considered a custom import postprocessor renaming .shader files into .shader.txt but what a messy hack :smile:

@Aras
I’m guessing this system seemed like a real elegant solution to this problem until people like me came along and started writing “kitchen sink” shader sets that abuse multi_compile. :stuck_out_tongue:

I’m not exactly thrilled by these answers, as I plan to add many more features to my shader set to make them more robust. I guess I will have to find ways to avoid using keywords.

PS.

#pragma multi_compile _THING_TAG_OFF _THING_TAG_ON

#ifdef _THING_TAG_ON
    #define _LEGACY_THING_TAG
#endif

Does Unity count this as three keywords?

Only 2, if custom #defines were counted as keywords, I’d have killed myself already :smile:

I’ve taken to reducing some on/off keywords to uniforms in select cases, especially since pre 4.5 compilation times were so excessively long and knowing that static branching (ie. on uniform/constant values) isn’t a significant cost anymore whatsoever on basically all current platforms.

1 Like

Correct, that case is two keywords.

And yeah, using uniform-based branching is a very practical approach. That is effectively “close to being free” on most modern hardware.

1 Like

Just curious, what happen if there’s no keyword limit?? (Honestly i don’t know about this, that’s why i’m asking :smile:)

I’m still on 4.3.4 but (correct me if I’m wrong) as far as I can tell this is already well supported: if one just does this:

#pragma multi_compile MYTHANG

Then one can EnableKeyword(“MYTHANG”) and DisableKeyword(“MYTHANG”) – voila, an on/off toggle with a single keyword!

Seems to work well… am I missing some hidden lurking danger here or what? :smile:

@metaleap , no, that should not work. What this basically does, is always define MYTHANG in all shader variants.

1 Like

Then why the heck does it work so incredibly and reliably and consistently well right now for me? :smile:

I tell you, I use it with #ifdef MYTHANG and it’s indeed off when I DisableKeyword and back on when I EnableKeyword…

Unity’s mysterious ways :stuck_out_tongue: probably it’ll stop working like it does right now next time I restart Unity or something. Well good to know it “shouldn’t” work, then I won’t go crazy when it stops working…

@Aras
Just to confirm, the keyword count only increases with multi_compile declarations in shaders, correct? I just want to make sure it is not affected by parameter definitions that use dropdowns and toggles. Those controls would still be useful to me as float values.

It is affected by anything that causes a “shader keyword” to be created. That is mostly multi_compile, but some MaterialPropertyDrawers (e.g. KeyworkEnum) also create keywords.

1 Like

I guess I should just avoid Toggle and KeywordEnum for now. The only place where I might need a toggle, I can do just as easily with a slider.

Thanks for the help everyone.

For Toggle, you could make your own that only sets the float to 0…1 (but does nothing about keywords). For enums, there’s already [Enum(name1,value1,name2,value2,…)] if you don’t need keywords.

I’m sorry to say it, but this limitation makes the whole multi_compile thing pretty useless, in particular for an asset store vendor.
I’d exchange happily the global 64 keyword limit for 1 keyword per shader.
Most people already have something like skyshop using most keywords already and things will break randomly based on order of packages being imported.
I was all hyped up for the combination of Toggle and fast shader compilation in 4.5, but I realized that I just can’t realistically take advantage of it. :frowning:

1 Like

Yes. That’s why we’re making the limit higher in Unity 5.0 (to 128). And yeah, a proper solution would be to have some limit of “global keywords” (e.g. 32) and some limit that is per-shader (e.g. 32). But that is quite a bit involved to implement, so 5.0 will have a “stopgap” solution of increasing the limit a bit.

I’m having the “64 Keyword Limit” problem when using a bunch of 3rd party assets in one project (Alloy, Skyshop, Amplify Color, TC Particles and several others).

I’ve removed a lot of shaders I won’t use, but am still having this issue. Is there any kind of fix, or can I see what shaders are using which keywords, etc?

Yep, you can select the shader in Project and click the Show button in the Inspector (Variants line) or you can open the shader and look for #pragma multi_compile to see what’s in use. But if you want to remove some keywords you’ll have to modify the shaders (and probably the material editors as well, if any)…

Today I switched from 3.5.3 to 3.5.5 with the same project and now I have that error messages, too.