Skip to content

ac/nir: Use nir_opt_constants to create PC-relative loads

Shaders oftentimes use lookup tables, which means they have a big array of constants which they index into indirectly:

const vec4 foo[4] = vec4[4](vec4(0.0, 1.0, 2.0, 3.0), ...);

uint i = ...;
... = foo[i];

There was a GLSL-level optimization used by radeonsi to turn these into uniforms, but since it only looked at array initializers it missed cases where the shader initializes the array contents dynamically, which is common in shaders translated from some low-level IR:

vec4 foo[4];
foo[0] = vec4(0.0, 1.0, 2.0, 3.0);
foo[1] = vec4(...);
foo[2] = vec4(...);
foo[3] = vec4(...);

uint i = ...;
... = foo[i];

radv had no such optimization at all. It turns out NIR already has an optimization pass that can recognize both cases. Using this in combination with LLVM's support for PC-relative loads from a read-only data section after the code, we can get the optimal code sequence for this without having to do much inside the driver itself.

In addition to being a worthwhile optimization on its own, this should fix a regression from enabling scratch support by making the relevant shader use loads from a constant pool instead of storing a bunch of constants to scratch every iteration of a loop.

We can also shut off the GLSL lowering since ours is better, but that will take a bit more work.

Merge request reports