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.
OpenGL's pixel shader is built with rslc's builder as the other
backends' are, and the text generator goes. rslc is told what the
context's header said: framebuffer fetch by the EXT or ARM extension,
conservative depth in place of early fragment tests, and subgroup
reductions.
Built for random pixel uids against GLSL 4.50 with subgroups, 3.30 with
conservative depth, and ES 3.10 and 3.20 with either framebuffer fetch,
each stage these contexts can be asked for compiles in glslangValidator.
The pixel shader is built with rslc's builder instead of printed as text
and parsed again, on Vulkan, D3D11, D3D12 and Metal. Built and printed
stages compile to the same SPIR-V and DXBC words: 15,619 random pixel
uids and host configs, with and without subgroup reduction, and every
uid the text refuses the builder refuses too.
The builder's flags say what the text's header said of the device:
subgroup operations, an inverted gl_HelperInvocation and subgroup
operations broken by discard. Vulkan and Metal pass them; Metal builds
at MSL 2.3, as its text compiles.
OpenGL still prints the stage as text until rslc prints framebuffer
fetch, conservative depth and subgroups in GLSL.
In Async (UberShaders), where ubershaders draw only until the
specialized pipeline is built, their pipelines are keyed sized for 8
texgens, and the pixel shader reads the draw's count from XF's, kept
in the pixel constants' padding (the block and savestates keep their
size). 3 are built before the game starts where there were 27. Over
the corpus, shaders made fall from 134 to 102, their words from 737739
to 274571, pipelines from 182 to 158, and loading from about 1.03 s to
0.22 s on lavapipe, with the same pictures; ubershaders sized so drew
every frame the same too. Synchronous (UberShaders) keeps them sized
for the draw's texgens.
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.
The geometry shader generator and the layered pass-through geometry
stage now write GLSL for Direct3D too, as for OpenGL and Vulkan, and the
vendored rslc compiles them to DXBC like the other stages. Direct3D
binds the geometry block at b0.
With every stage compiled by rslc, the runtime compiler is no longer
used: d3dcompiler_47.dll is not loaded, D3DCompile and its target table
are gone, and the core no longer needs the DLL on the system.
GenerateVSOutputMembers loses its Direct3D geometry-stage case and its
HLSL semantics, which only the HLSL generators used.
The vendored rslc reads a subpassInput and prints it to MSL as the
colour attachment's [[color(N)]] value, so the pixel header defines
INPUT_ATTACHMENT_BINDING and FB_FETCH_VALUE again and the backend
reports framebuffer fetch on Apple GPUs and on the Intel GPUs whose
probe draws a pixel that reads back doubled.
Both fed user-written GLSL to the backends at runtime, which the move to
bytecode emitted straight from the shader generators leaves no compiler
for. The frontend's own shader pipeline covers post-processing.
The presentation pass keeps a plain copy and the built-in correction
shader for output resampling, colour space and gamma correction and HDR
scaling, now compiled in rather than loaded from Sys/Shaders. The
graphics-mod system keeps its draw, EFB, projection and texture actions;
custom pipelines, materials, shader, mesh and sampler assets, the custom
constant buffers in every backend and the two mods built on them are
gone, along with the shader generators' custom-shader hooks.
Yellow squiggly lines begone!
Done automatically on .cpp files through `run-clang-tidy`, with manual corrections to the mistakes.
If an import is directly used, but is technically unnecessary since it's recursively imported by something else, it is *not* removed.
The tool doesn't touch .h files, so I did some of them by hand while fixing errors due to old recursive imports.
Not everything is removed, but the cleanup should be substantial enough.
Because this done on Linux, code that isn't used on it is mostly untouched.
(Hopefully no open PR is depending on these imports...)
While the NV extension is totally fine, the KHR extension should be able to support more hardware.
For NVIDIA, the hardware either supports both or neither, it just needs a driver from the last two years.
For AMD, the drivers from late 2022-12 seems to bring support for the KHR extension.
For Intel, the KHR is also supported for some years.
Otherwise, texelFetch() will use an out-of-bounds layer for game textures (that have 1 layer; EFB copies have 2 layers in stereoscopic 3D mode), which is undefined behavior (often resulting in a black image). The fast texture sampling path uses texture(), which always clamps (see https://www.khronos.org/opengl/wiki/Array_Texture#Access_in_shaders), so it was unaffected by this difference.
It stores both the konst selection value for alpha and color channels (for two tev stages per ksel), and half of a swap table row (there are 4 total swap tables, which can be used for swizzling the rasterized color and the texture color, and indices selecting which tables to use are stored per tev stage in the alpha combiner). Since these are indexed very differently, the old code was hard to follow.
Adds a pass to process driver deficiencies between UID caching and use, allowing a full view of the whole pipeline, since some bugs/workarounds involve interactions between blend modes and the pixel shader