So let’s say I do something like this in a shader:
float foo = 2;
return sqrt(foo);
}```
So the shader compiler seems to be smart enough to precompute the result of sqrt(2). If I hit "Compile and show code", I see this in the output
```0: mov o0.x, l(1.414214)```
However, let's say I wanted "foo" to be configurable per material, so I add a property for it
```Properties {
_Foo("Foo", Range(0, 10)) = 2
}
...
uniform float _Foo;
float ConstantTestFragment() : SV_TARGET {
return sqrt(_Foo);
}```
Now I end up with this code:
```0: sqrt o0.x, cb0[14].x```
I.e. the optimization is gone, since the shader code is generic for all materials and can't make assumptions about the value of foo.
Now, I'm wondering, is there a way I can have each material compile its own version of the shader with optimizations?
So I looked into shader features, and it sort of looks like I can at least get multiple variants to compile i.e.
```#pragma multi_compile SIMPLE_SHADING BETTER_SHADING GOOD_SHADING BEST_SHADING```
and then set foo according to the define. However, what do I do if I want to support arbitrary values of foo?
So I strongly suspect that what I'm wishing for doesn't exist, which I guess would be some kind of constant property that would be compiled for each specific material with it's specific constants (not uniforms). I wouldn't expect to be able to change it run-time, I just want it to be compiled for the material values I have set in the inspector for the material assets in the project.
Now I know I could just do sqrt(foo) on the cpu before sending it, I just chose that as an example because it's easier to see whether the compiler can optimize or not. There are more complicated examples that would greatly benefit from the compiler knowing constant values (branching, loop unrolling or several different uses of the same constant).
If per-material constants are not possible, is there a way I could inject a project-wide #define into a shader? (I'm using a custom scriptable render pipeline if that matters).