o3de / o3de-azslc

Amazon Shader Language (AZSL) Compiler
Other
23 stars 14 forks source link

Shader Option Priority #60

Open santorac opened 1 year ago

santorac commented 1 year ago

The shader variant tree is formed in such a way that the highest priority options are nearest to the root of the tree. That way, if a requested shader variant is not available and a fallback is selected instead, there is a high chance that the fallback variant will still have baked the most impactful shader options.

Currently, the shader option priority order is simply based on the order in which the options are declared in the shader source code. But since the shader options are often declared in a variety of .azsli files and #included together, it is impractical to arrange their priority order in this way. We need some to control the shader option priority order independent of the declaration order.

I suggest the following approach (but I'm open to other ideas): Use a "priority" attribute to assign each option a priority value. If no priority value is provided, the default will be to repeat the previous priority value. The lowest priority number is the highest priority. For example, 10 is a higher priority than 100, and will appear closer to the root of the shader variant tree. If two or more options have the same priority value, they will be sorted in the order of declaration.

Example syntax:

[priority(1000)]
option bool o_enable_IBL = true;

The command line interface for azslc does not need to change, the existing "--options" flag will still output the metadata for the available shader options. The only difference is the order in which the options appear will match the indicated priority order.

The actual priority values do not need to appear in the returned reflection metadata, but I suggest it's a good idea to do so, as the values could come in handy in the future.

galibzon commented 1 year ago

It seems We can actually automate the priority assignment simply by analyzing usage of options by block scopes. Please see the comment from @siliconvoodoo in this discussion: https://github.com/o3de/sig-graphics-audio/discussions/92#discussioncomment-4226443.
For convenience I'm copy/pasting here:

Say:

if (optionA)
{
   for (int i = 0; i < optionB; ++i) switch(optionC){ case A: doA(i); case B: doB(i); };
}
if (optionD) {..}

We could extract a dependency graph. OptionA <- OptionB <- OptionC OptionB <- OptionC OptionC OptionD

Following the dependency chain should determine the order of the options in the Shader Variant Tree.

siliconvoodoo commented 1 year ago

We can mixup that heuristic with the attributes as well. Like the heursitic would give a priority score, and we use that by default of a hand-defined priority. So that if a shader programmer really wants to control the priority manually for some reason, it's still doable.

siliconvoodoo commented 1 year ago

And here it is, the implemented first shot of that heuristical system:

https://github.com/o3de/o3de-azslc/pull/84

ping to @jeremyong if he is still around, for science that might be interesting to see.