mellinoe / ShaderGen

Proof-of-concept library for generating HLSL, GLSL, and Metal shader code from C#,
MIT License
492 stars 55 forks source link

Shader permutation #3

Open amerkoleci opened 6 years ago

amerkoleci commented 6 years ago

This is something that creates panic inside me, how would be possible to handle shader variants or permutation, maybe having the ShaderSet that sends preprocessor defines to roslyn process. Unity has some concept about shader permutation, instead of:

if(NormalMapEnabled) // Create branch on gpu shader generation

if NORMAL_MAP_ENABLED // Macro

mellinoe commented 6 years ago

I've thought about this a bit, too, and I think that it would be fairly easy to accommodate in the current system.

Currently, actual shader code is generated based on the parameters contained in ShaderSetInfo objects. I think it could be optionally augmented with something like a list of "define constants" (simple values, or simple key-value pairs).

There would then be a ShaderBuiltin function (or some other mechanism), that let you compare against those "define constants". For example, you could write something like:

if (ShaderBuiltins.IsDefined("NormalMaps")
{
    normal = Sample(NormalMap, NormalMapSampler, input.TexCoords);
}

The code generator would specially treat the ShaderBuiltins.IsDefined function, and it could either include or omit the block entirely, depending on the defined constants in the current shader set being processed.

You could then include the same shader twice with two different sets of defines:

[ShaderSet("SetWIthNormalMaps", "MyVertexShader", "MyFragmentShader", "NormalMaps=1"]
[ShaderSet("SetWithoutNormalMaps", "MyVertexShader", "MyFragmentShader", "NormalMaps=0;OtherFlag=1"]

Just a rough idea. I haven't given it a ton of thought, but I think it's not that hard.

amerkoleci commented 6 years ago

Thumbs up, definetelly like this approach :)