The pixel ubershader is built with rslc's builder instead of printed as
text and parsed again, on every backend. Built and printed stages
compile to the same SPIR-V and DXBC words: each of the 108 uids with 30
random host configs, on Vulkan with and without subgroup reduction and
on D3D. For OpenGL, where framebuffer fetch blends and logic-ops in the
shader, each stage a GLSL 4.50, 3.30, ES 3.10 or ES 3.20 context can be
asked for compiles in glslangValidator.
Both pixel generators now declare their inputs in one place. The text
the ubershader was the last user of goes: the pixel shaders' common
header, the switch trees, the lighting function, the bitfieldExtract
header and the VS_OUTPUT members and their interpolation qualifiers.
The vertex ubershader is built through rslc's builder, as the
specialized vertex shader already is, so no GLSL is generated or
parsed for it on the compile workers.
The lighting function and the per-channel vertex lighting it shares
with the pixel ubershader, and bitfieldExtract for backends without it,
are builder pieces of their own. The text writers nothing uses any
more go: the vertex ubershader's, the line and point expansion, the
line offset, dolphin_isnan's and the output member assignment.
Metal's built shaders now get the same MSL header and fixups its
parsed ones do, so the ubershader lighting loop stays unrolled.
Built stages compile to the same words the text did for Vulkan and
D3D for every texgen count across random host configurations.
ShaderText is one growing block of chars with room kept in front for a
header. ShaderCode writes into it as it is or printf-style, without fmt
or std::string; the generators' string parameters, tables and switch
trees are plain C strings, and the UID enumerations fill arrays.
SPDX standardizes how source code conveys its copyright and licensing
information. See https://spdx.github.io/spdx-spec/1-rationale/ . SPDX
tags are adopted in many large projects, including things like the Linux
kernel.
Cel-damage depends on lighting being calculated for the first channel
even though there is no color in the vertex format (defaults to the
material color). If lighting for the channel is not enabled, the vertex
will use the default color as before.
The default value of the color is determined by the number of elements in
the vertex format. This fixes the grey cubes in Super Mario Sunshine.
If the color channel count is zero, we set the color to black before the
end of the vertex shader. It's possible that this would be undefined
behavior on hardware if a vertex color index that was greater than the
channel count was used within TEV.
Now that we've converted all of the shader generators over to using fmt,
we can drop the old Write() member function and perform a rename
operation on the WriteFmt() to turn it into the new Write() function.
All changes within this are the removal of a <cstdarg> header, since the
previous printf-based Write() required it, and renaming. No functional
changes are made at all.
These are only ever used with ShaderCode instances and nothing else.
Given that, we can convert these helper functions to expect that type of
object as an argument and remove the need for templates, improving
compiler throughput a marginal amount, as the template instantiation
process doesn't need to be performed.
We can also move the definitions of these functions into the cpp file,
which allows us to remove a few inclusions from the ShaderGenCommon
header. This uncovered a few instances of indirect inclusions being
relied upon in other source files.
One other benefit is this allows changes to be made to the definitions
of the functions without needing to recompile all translation units that
make use of these functions, making change testing a little quicker.
Moving the definitions into the cpp file also allows us to completely
hide DefineOutputMember() from external view, given it's only ever used
inside of GenerateVSOutputMembers().
Cel-damage uses the color from the lighting stage of the vertex pipeline
as texture coordinates, but sets numColorChans to zero.
We now calculate the colors in all cases, but override the color before
writing it from the vertex shader if numColorChans is set to a lower value.