Most of the time with nir_def_rewrite_uses_after, you want to rewrite after the
replacement. Make that the default thing to be more ergonomic and to drop
parent_instr uses.
We leave nir_def_rewrite_uses_after_instr defined if you really want the old
signature with an arbitrary after point.
Via Coccinelle patch:
@@
expression a, b;
@@
-nir_def_rewrite_uses_after(a, b, b->parent_instr)
+nir_def_rewrite_uses_after_def(a, b)
Followed by a bunch of sed.
Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Emma Anholt <emma@anholt.net>
Reviewed-by: Marek Olšák <maraeo@gmail.com>
Acked-by: Karol Herbst <kherbst@redhat.com>
Acked-by: Konstantin Seurer <konstantin.seurer@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36489>
97 lines
2.9 KiB
C
97 lines
2.9 KiB
C
/*
|
|
* Copyright 2022 Alyssa Rosenzweig
|
|
* Copyright 2020 Collabora, Ltd.
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "nir.h"
|
|
#include "nir_builder.h"
|
|
#include "nir_deref.h"
|
|
|
|
struct opts {
|
|
unsigned coord_replace;
|
|
bool point_coord_is_sysval;
|
|
};
|
|
|
|
static bool
|
|
pass(nir_builder *b, nir_instr *instr, void *data)
|
|
{
|
|
struct opts *opts = data;
|
|
|
|
if (instr->type != nir_instr_type_intrinsic)
|
|
return false;
|
|
|
|
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
|
if (intr->intrinsic != nir_intrinsic_load_interpolated_input &&
|
|
intr->intrinsic != nir_intrinsic_load_input)
|
|
return false;
|
|
|
|
nir_src *offset = nir_get_io_offset_src(intr);
|
|
assert(nir_src_is_const(*offset) && "no indirects supported");
|
|
|
|
nir_io_semantics sem = nir_intrinsic_io_semantics(intr);
|
|
unsigned location = sem.location + nir_src_as_uint(*offset);
|
|
signed component = nir_intrinsic_component(intr);
|
|
|
|
if (location < VARYING_SLOT_TEX0 || location > VARYING_SLOT_TEX7)
|
|
return false;
|
|
|
|
if (!(opts->coord_replace & BITFIELD_BIT(location - VARYING_SLOT_TEX0)))
|
|
return false;
|
|
|
|
b->cursor = nir_before_instr(instr);
|
|
nir_def *channels[4] = {
|
|
NULL, NULL,
|
|
nir_imm_float(b, 0.0),
|
|
nir_imm_float(b, 1.0)
|
|
};
|
|
|
|
if (opts->point_coord_is_sysval) {
|
|
nir_def *pntc = nir_load_point_coord(b);
|
|
|
|
b->cursor = nir_after_instr(instr);
|
|
channels[0] = nir_channel(b, pntc, 0);
|
|
channels[1] = nir_channel(b, pntc, 1);
|
|
} else {
|
|
sem.location = VARYING_SLOT_PNTC;
|
|
nir_src_rewrite(offset, nir_imm_int(b, 0));
|
|
nir_intrinsic_set_io_semantics(intr, sem);
|
|
nir_def *raw = &intr->def;
|
|
|
|
b->cursor = nir_after_instr(instr);
|
|
channels[0] = nir_channel_or_undef(b, raw, 0 - component);
|
|
channels[1] = nir_channel_or_undef(b, raw, 1 - component);
|
|
}
|
|
|
|
nir_def *res = nir_vec(b, &channels[component], intr->num_components);
|
|
nir_def_rewrite_uses_after(&intr->def, res);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
nir_lower_texcoord_replace_late(nir_shader *s, unsigned coord_replace,
|
|
bool point_coord_is_sysval)
|
|
{
|
|
assert(s->info.stage == MESA_SHADER_FRAGMENT);
|
|
assert(coord_replace != 0);
|
|
|
|
uint64_t replace_mask = (((uint64_t)coord_replace) << VARYING_SLOT_TEX0);
|
|
|
|
/* If no relevant texcoords are read, there's nothing to do */
|
|
if (!(s->info.inputs_read & replace_mask))
|
|
return false;
|
|
|
|
/* Otherwise, we're going to replace these texcoord reads with a PNTC read */
|
|
s->info.inputs_read &= ~(((uint64_t)coord_replace) << VARYING_SLOT_TEX0);
|
|
|
|
if (!point_coord_is_sysval)
|
|
s->info.inputs_read |= VARYING_BIT_PNTC;
|
|
|
|
return nir_shader_instructions_pass(s, pass,
|
|
nir_metadata_control_flow,
|
|
&(struct opts){
|
|
.coord_replace = coord_replace,
|
|
.point_coord_is_sysval = point_coord_is_sysval,
|
|
});
|
|
}
|