glsl,st/mesa: always lower IO for GLSL, unlower IO for drivers

This enables nir_opt_varyings for all gallium drivers.

Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31942>
This commit is contained in:
Marek Olšák 2024-11-01 00:42:50 -04:00
parent 1dc85a34f3
commit dae57e184a
4 changed files with 82 additions and 6 deletions

View file

@ -1524,8 +1524,7 @@ gl_nir_lower_optimize_varyings(const struct gl_constants *consts,
nir_shader *nir = shader->Program->nir; nir_shader *nir = shader->Program->nir;
if (nir->info.stage == MESA_SHADER_COMPUTE || if (nir->info.stage == MESA_SHADER_COMPUTE)
!(nir->options->io_options & nir_io_has_intrinsics))
return; return;
shaders[num_shaders] = nir; shaders[num_shaders] = nir;

View file

@ -332,10 +332,6 @@ _mesa_spirv_to_nir(struct gl_context *ctx,
NIR_PASS(_, nir, nir_split_var_copies); NIR_PASS(_, nir, nir_split_var_copies);
NIR_PASS(_, nir, nir_split_per_member_structs); NIR_PASS(_, nir, nir_split_per_member_structs);
if (nir->info.stage == MESA_SHADER_VERTEX &&
!(nir->options->io_options & nir_io_has_intrinsics))
nir_remap_dual_slot_attributes(nir, &linked_shader->Program->DualSlotInputs);
NIR_PASS(_, nir, nir_lower_frexp); NIR_PASS(_, nir, nir_lower_frexp);
return nir; return nir;

View file

@ -69,6 +69,7 @@
#include "util/thread_sched.h" #include "util/thread_sched.h"
#include "cso_cache/cso_context.h" #include "cso_cache/cso_context.h"
#include "compiler/glsl/glsl_parser_extras.h" #include "compiler/glsl/glsl_parser_extras.h"
#include "nir.h"
DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", false) DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", false)

View file

@ -512,6 +512,11 @@ st_create_nir_shader(struct st_context *st, struct pipe_shader_state *state)
nir_shader *nir = state->ir.nir; nir_shader *nir = state->ir.nir;
gl_shader_stage stage = nir->info.stage; gl_shader_stage stage = nir->info.stage;
/* Renumber SSA defs to make it easier to run diff on printed NIR. */
nir_foreach_function_impl(impl, nir) {
nir_index_ssa_defs(impl);
}
if (ST_DEBUG & DEBUG_PRINT_IR) { if (ST_DEBUG & DEBUG_PRINT_IR) {
fprintf(stderr, "NIR before handing off to driver:\n"); fprintf(stderr, "NIR before handing off to driver:\n");
nir_print_shader(nir, stderr); nir_print_shader(nir, stderr);
@ -752,6 +757,54 @@ force_persample_shading(struct nir_builder *b, nir_intrinsic_instr *intr,
return false; return false;
} }
static int
xfb_compare_dst_offset(const void *a, const void *b)
{
const struct pipe_stream_output *var0 = (const struct pipe_stream_output*)a;
const struct pipe_stream_output *var1 = (const struct pipe_stream_output*)b;
if (var0->output_buffer != var1->output_buffer)
return var0->output_buffer > var1->output_buffer ? 1 : -1;
return var0->dst_offset - var1->dst_offset;
}
static void
get_stream_output_info_from_nir(nir_shader *nir,
struct pipe_stream_output_info *info)
{
/* Get pipe_stream_output_info from NIR. Only used by IO variables. */
nir_xfb_info *xfb = nir->xfb_info;
memset(info, 0, sizeof(*info));
if (!xfb)
return;
info->num_outputs = xfb->output_count;
for (unsigned i = 0; i < 4; i++)
info->stride[i] = nir->info.xfb_stride[i];
for (unsigned i = 0; i < xfb->output_count; i++) {
struct pipe_stream_output *out = &info->output[i];
assert(!xfb->outputs[i].high_16bits);
out->register_index =
util_bitcount64(nir->info.outputs_written &
BITFIELD64_MASK(xfb->outputs[i].location));
out->start_component = xfb->outputs[i].component_offset;
out->num_components = util_bitcount(xfb->outputs[i].component_mask);
out->output_buffer = xfb->outputs[i].buffer;
out->dst_offset = xfb->outputs[i].offset / 4;
out->stream = xfb->buffer_to_stream[out->output_buffer];
}
/* Intel requires that xfb outputs are sorted by dst_offset. */
qsort(info->output, info->num_outputs, sizeof(info->output[0]),
xfb_compare_dst_offset);
}
static struct st_common_variant * static struct st_common_variant *
st_create_common_variant(struct st_context *st, st_create_common_variant(struct st_context *st,
struct gl_program *prog, struct gl_program *prog,
@ -812,7 +865,26 @@ st_create_common_variant(struct st_context *st,
if (finalize || !st->allow_st_finalize_nir_twice || key->is_draw_shader) { if (finalize || !st->allow_st_finalize_nir_twice || key->is_draw_shader) {
st_finalize_nir(st, prog, prog->shader_program, state.ir.nir, false, st_finalize_nir(st, prog, prog->shader_program, state.ir.nir, false,
key->is_draw_shader); key->is_draw_shader);
}
/* This should be after all passes that touch IO. */
if (state.ir.nir->info.io_lowered &&
(!(state.ir.nir->options->io_options & nir_io_has_intrinsics) ||
key->is_draw_shader)) {
assert(!state.stream_output.num_outputs || state.ir.nir->xfb_info);
get_stream_output_info_from_nir(state.ir.nir, &state.stream_output);
NIR_PASS(_, state.ir.nir, st_nir_unlower_io_to_vars);
if (state.ir.nir->info.stage == MESA_SHADER_TESS_CTRL &&
state.ir.nir->options->compact_arrays &&
state.ir.nir->options->vectorize_tess_levels)
NIR_PASS(_, state.ir.nir, nir_vectorize_tess_levels);
gl_nir_opts(state.ir.nir);
finalize = true;
}
if (finalize || !st->allow_st_finalize_nir_twice || key->is_draw_shader) {
struct pipe_screen *screen = st->screen; struct pipe_screen *screen = st->screen;
if (!key->is_draw_shader && screen->finalize_nir) { if (!key->is_draw_shader && screen->finalize_nir) {
char *msg = screen->finalize_nir(screen, state.ir.nir); char *msg = screen->finalize_nir(screen, state.ir.nir);
@ -1178,6 +1250,14 @@ st_create_fp_variant(struct st_context *st,
finalize = true; finalize = true;
} }
/* This should be after all passes that touch IO. */
if (state.ir.nir->info.io_lowered &&
!(state.ir.nir->options->io_options & nir_io_has_intrinsics)) {
NIR_PASS(_, state.ir.nir, st_nir_unlower_io_to_vars);
gl_nir_opts(state.ir.nir);
finalize = true;
}
if (finalize || !st->allow_st_finalize_nir_twice) { if (finalize || !st->allow_st_finalize_nir_twice) {
/* Some of the lowering above may have introduced new varyings */ /* Some of the lowering above may have introduced new varyings */
nir_shader_gather_info(state.ir.nir, nir_shader_gather_info(state.ir.nir,