nir/opt_varyings: use nir_scalar

Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36091>
This commit is contained in:
Marek Olšák 2025-07-10 14:29:44 -04:00 committed by Marge Bot
parent 2e06da1597
commit 9607852c30

View file

@ -629,7 +629,7 @@ struct scalar_slot {
* computing the stored value. Used by constant and uniform propagation
* to the next shader.
*/
nir_instr *value;
nir_scalar value;
} producer;
struct {
@ -1594,9 +1594,9 @@ gather_outputs(struct nir_builder *builder, nir_intrinsic_instr *intr, void *cb_
return false;
if (is_store) {
nir_def *value = intr->src[0].ssa;
nir_scalar value = nir_scalar_resolved(intr->src[0].ssa, 0);
const bool constant = value->parent_instr->type == nir_instr_type_load_const;
const bool constant = nir_scalar_is_const(value);
/* If the store instruction is executed in a divergent block, the value
* that's stored in the output becomes divergent.
@ -1609,19 +1609,19 @@ gather_outputs(struct nir_builder *builder, nir_intrinsic_instr *intr, void *cb_
intr->instr.block->divergent ||
nir_src_is_divergent(&intr->src[0]);
if (!out->producer.value) {
if (!out->producer.value.def) {
/* This is the first store to this output. */
BITSET_SET(linkage->output_equal_mask, slot);
out->producer.value = value->parent_instr;
out->producer.value = value;
/* Set whether the value is convergent. Such varyings can be
* promoted to flat regardless of their original interpolation
* mode.
*/
if (linkage->consumer_stage == MESA_SHADER_FRAGMENT && !divergent) {
if (value->bit_size == 32)
if (value.def->bit_size == 32)
BITSET_SET(linkage->convergent32_mask, slot);
else if (value->bit_size == 16)
else if (value.def->bit_size == 16)
BITSET_SET(linkage->convergent16_mask, slot);
else
unreachable("invalid store_output type");
@ -1630,14 +1630,14 @@ gather_outputs(struct nir_builder *builder, nir_intrinsic_instr *intr, void *cb_
/* There are multiple stores to the same output. If they store
* different values, clear the mask.
*/
if (out->producer.value != value->parent_instr)
if (!nir_scalar_equal(out->producer.value, value))
BITSET_CLEAR(linkage->output_equal_mask, slot);
/* Update divergence information. */
if (linkage->consumer_stage == MESA_SHADER_FRAGMENT && divergent) {
if (value->bit_size == 32)
if (value.def->bit_size == 32)
BITSET_CLEAR(linkage->convergent32_mask, slot);
else if (value->bit_size == 16)
else if (value.def->bit_size == 16)
BITSET_CLEAR(linkage->convergent16_mask, slot);
else
unreachable("invalid store_output type");
@ -1650,9 +1650,9 @@ gather_outputs(struct nir_builder *builder, nir_intrinsic_instr *intr, void *cb_
nir_instr *vertex_index_instr = vertex_index_src->ssa->parent_instr;
if (!is_sysval(vertex_index_instr, SYSTEM_VALUE_INVOCATION_ID)) {
if (value->bit_size == 32)
if (value.def->bit_size == 32)
BITSET_SET(linkage->cross_invoc32_mask, slot);
else if (value->bit_size == 16)
else if (value.def->bit_size == 16)
BITSET_SET(linkage->cross_invoc16_mask, slot);
else
unreachable("invalid store_output type");
@ -2352,12 +2352,15 @@ clone_ssa_impl(struct linkage_info *linkage, nir_builder *b, nir_def *ssa)
}
static nir_def *
clone_ssa(struct linkage_info *linkage, nir_builder *b, nir_def *ssa)
clone_ssa(struct linkage_info *linkage, nir_builder *b, nir_scalar scalar)
{
assert(!linkage->clones_ht);
linkage->clones_ht = _mesa_pointer_hash_table_create(NULL);
nir_def *clone = clone_ssa_impl(linkage, b, ssa);
nir_def *clone = clone_ssa_impl(linkage, b, scalar.def);
if (clone->num_components > 1)
clone = nir_channel(b, clone, scalar.comp);
_mesa_hash_table_destroy(linkage->clones_ht, NULL);
linkage->clones_ht = NULL;
@ -2465,7 +2468,7 @@ propagate_uniform_expressions(struct linkage_info *linkage,
*/
nir_shader_clear_pass_flags(linkage->producer_builder.shader);
if (!is_uniform_expression(slot->producer.value, &state))
if (!is_uniform_expression(slot->producer.value.def->parent_instr, &state))
continue;
if (state.cost > linkage->max_varying_expression_cost)
@ -2476,9 +2479,9 @@ propagate_uniform_expressions(struct linkage_info *linkage,
* no effect.
*/
if (is_interpolated_color(linkage, i) &&
(slot->producer.value->type != nir_instr_type_load_const ||
nir_instr_as_load_const(slot->producer.value)->value[0].f32 < 0 ||
nir_instr_as_load_const(slot->producer.value)->value[0].f32 > 1))
(!nir_scalar_is_const(slot->producer.value) ||
nir_scalar_as_float(slot->producer.value) < 0 ||
nir_scalar_as_float(slot->producer.value) > 1))
continue;
/* TEXn.zw can be propagated only if it's equal to (0, 1) because it's
@ -2489,11 +2492,10 @@ propagate_uniform_expressions(struct linkage_info *linkage,
if (i % 8 == 0 || /* TEXn.x */
i % 8 == 2 || /* TEXn.y */
slot->producer.value->type != nir_instr_type_load_const)
!nir_scalar_is_const(slot->producer.value))
continue;
float value =
nir_instr_as_load_const(slot->producer.value)->value[0].f32;
float value = nir_scalar_as_float(slot->producer.value);
/* This ignores signed zeros, but those are destroyed by
* interpolation, so it doesn't matter.
@ -2516,8 +2518,7 @@ propagate_uniform_expressions(struct linkage_info *linkage,
b->cursor = nir_before_instr(&loadi->instr);
/* Copy the uniform expression before the load. */
nir_def *clone = clone_ssa(linkage, b,
nir_instr_def(slot->producer.value));
nir_def *clone = clone_ssa(linkage, b, slot->producer.value);
/* Interpolation converts Infs to NaNs. If we skip it, we need to
* convert Infs to NaNs manually.
@ -2703,6 +2704,24 @@ get_input_qualifier(struct linkage_info *linkage, unsigned i)
return qual + pixel_location;
}
static uint32_t
nir_ht_scalar_hash(const void *key)
{
nir_scalar s;
static_assert(offsetof(nir_scalar, def) == 0, "known layout");
static_assert(offsetof(nir_scalar, comp) == sizeof(s.def), "no padding");
static_assert(sizeof(s.comp) == sizeof(unsigned), "known layout");
/* Don't include structure padding of nir_scalar. */
return _mesa_hash_data(key, offsetof(nir_scalar, comp) + sizeof(unsigned));
}
static bool
nir_ht_scalar_equal(const void *a, const void *b)
{
return nir_scalar_equal(*(nir_scalar*)a, *(nir_scalar*)b);
}
static void
deduplicate_outputs(struct linkage_info *linkage,
nir_opt_varyings_progress *progress)
@ -2738,13 +2757,14 @@ deduplicate_outputs(struct linkage_info *linkage,
struct hash_table **table = &tables[qualifier];
if (!*table)
*table = _mesa_pointer_hash_table_create(NULL);
*table = _mesa_hash_table_create(NULL, nir_ht_scalar_hash,
nir_ht_scalar_equal);
nir_instr *value = slot->producer.value;
nir_scalar value = slot->producer.value;
struct hash_entry *entry = _mesa_hash_table_search(*table, value);
struct hash_entry *entry = _mesa_hash_table_search(*table, &value);
if (!entry) {
_mesa_hash_table_insert(*table, value, (void *)(uintptr_t)i);
_mesa_hash_table_insert(*table, &value, (void *)(uintptr_t)i);
continue;
}
@ -3725,7 +3745,8 @@ try_move_postdominator(struct linkage_info *linkage,
*/
b = &linkage->producer_builder;
b->cursor = nir_after_block_before_jump(block);
nir_def *producer_clone = clone_ssa(linkage, b, postdom_def);
nir_def *producer_clone = clone_ssa(linkage, b,
nir_get_scalar(postdom_def, 0));
/* Boolean post-dominators are upcast in the producer because we can't
* use 1-bit outputs.