From 9607852c30aff3f399cbe2151282a5747cea9c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Thu, 10 Jul 2025 14:29:44 -0400 Subject: [PATCH] nir/opt_varyings: use nir_scalar Reviewed-by: Alyssa Rosenzweig Reviewed-by: Timothy Arceri Part-of: --- src/compiler/nir/nir_opt_varyings.c | 77 ++++++++++++++++++----------- 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/src/compiler/nir/nir_opt_varyings.c b/src/compiler/nir/nir_opt_varyings.c index e58d4037aab..156dc118844 100644 --- a/src/compiler/nir/nir_opt_varyings.c +++ b/src/compiler/nir/nir_opt_varyings.c @@ -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.