From 879cf1bd746a417d9d150067ff920d64083de98f Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Thu, 7 May 2026 09:39:31 -0400 Subject: [PATCH] i915/corm: direct output writes for vec construction When a vec2/3/4 construction has a single consumer that is a store_output, emit the partial-writemask MOVs directly to the output register (oC/oD) instead of building in a temp and copying. Skip this for the same_reg case which already collapses to a zero-instruction swizzle alias. Also fix TGSI-win reporting: preserve loser stats before freeing so corm_win_reason shows the actual delta instead of "only". shader-db (I915_FS=nir): 214/403 compiled, 3231 alu shader-db (I915_FS=both): nir won 214 (26 identical, 1 tied, 184 better, 3 only), 73 TGSI, 116 neither Assisted-by: Claude --- src/gallium/drivers/i915/i915_fpc_nir.c | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/gallium/drivers/i915/i915_fpc_nir.c b/src/gallium/drivers/i915/i915_fpc_nir.c index 27f57ece08b..8daa84e4a9e 100644 --- a/src/gallium/drivers/i915/i915_fpc_nir.c +++ b/src/gallium/drivers/i915/i915_fpc_nir.c @@ -517,6 +517,27 @@ emit_alu(struct nir_to_i915 *c, nir_alu_instr *alu) return; } + /* If this vec's only consumer is a store_output, write directly + * to the output register instead of going through a temp. + */ + if (list_is_singular(&def->uses)) { + nir_src *use = list_first_entry(&def->uses, nir_src, use_link); + nir_instr *use_instr = nir_src_use_instr(use); + if (use_instr->type == nir_instr_type_intrinsic) { + nir_intrinsic_instr *store = + nir_instr_as_intrinsic(use_instr); + if (store->intrinsic == nir_intrinsic_store_output && + nir_intrinsic_component(store) == 0) { + nir_io_semantics sem = nir_intrinsic_io_semantics(store); + uint32_t out = sem.location == FRAG_RESULT_DEPTH + ? UREG(REG_TYPE_OD, 0) : UREG(REG_TYPE_OC, 0); + i915_release_temp(p, GET_UREG_NR(dest)); + dest = out; + set_ureg(c, def, dest); + } + } + } + static const uint32_t chan_mask[] = { A0_DEST_CHANNEL_X, A0_DEST_CHANNEL_Y, A0_DEST_CHANNEL_Z, A0_DEST_CHANNEL_W, @@ -796,6 +817,11 @@ emit_intrinsic(struct nir_to_i915 *c, nir_intrinsic_instr *intr) dest = UREG(REG_TYPE_OC, 0); } + /* Vec direct-output already wrote to oC/oD */ + uint32_t val_type = GET_UREG_TYPE(val); + if (val_type == REG_TYPE_OC || val_type == REG_TYPE_OD) + break; + nir_def *src_def = intr->src[0].ssa; uint32_t *prev = c->def_csr[src_def->index];