From fbaa5ad0c35c6be23c30ec5c0ab0b89e9cb323db Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Thu, 23 Apr 2026 15:31:54 -0700 Subject: [PATCH] iris: Implement force_dual_color_blend_by_location via NIR We can just have iris look at its own program key and change the fragment shader output variable's location/index in the NIR. By doing this before lowering fragment shader outputs, the rest of the output lowering does the right thing, and the backend no longer has to consider hacks for broken OpenGL apps. Reviewed-by: Alyssa Rosenzweig Part-of: --- src/gallium/drivers/iris/iris_program.c | 16 ++++++++++++++-- src/intel/compiler/brw/brw_compiler.h | 4 +--- src/intel/compiler/brw/brw_from_nir.cpp | 2 +- src/intel/compiler/jay/jay_nir.c | 1 - 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/iris/iris_program.c b/src/gallium/drivers/iris/iris_program.c index 3458f0a40d4..743d92843f7 100644 --- a/src/gallium/drivers/iris/iris_program.c +++ b/src/gallium/drivers/iris/iris_program.c @@ -558,7 +558,6 @@ iris_to_brw_fs_key(const struct iris_screen *screen, .alpha_to_coverage = key->alpha_to_coverage ? INTEL_ALWAYS : INTEL_NEVER, .persample_interp = key->persample_interp ? INTEL_ALWAYS : INTEL_NEVER, .multisample_fbo = key->multisample_fbo ? INTEL_ALWAYS : INTEL_NEVER, - .force_dual_color_blend = key->force_dual_color_blend, .ignore_sample_mask_out = !key->multisample_fbo, }; } @@ -638,7 +637,6 @@ iris_to_elk_fs_key(const struct iris_screen *screen, .alpha_to_coverage = key->alpha_to_coverage ? ELK_ALWAYS : ELK_NEVER, .persample_interp = key->persample_interp ? ELK_ALWAYS : ELK_NEVER, .multisample_fbo = key->multisample_fbo ? ELK_ALWAYS : ELK_NEVER, - .force_dual_color_blend = key->force_dual_color_blend, .coherent_fb_fetch = key->coherent_fb_fetch, .color_outputs_valid = key->color_outputs_valid, .input_slots_valid = key->input_slots_valid, @@ -2734,6 +2732,17 @@ iris_update_compiled_gs(struct iris_context *ice) } } +static void +iris_force_dual_color_blend(nir_shader *nir) +{ + nir_variable *var = nir_find_variable_with_location(nir, nir_var_shader_out, + FRAG_RESULT_DATA1); + if (var) { + var->data.location = FRAG_RESULT_DATA0; + var->data.index = 1; + } +} + /** * Compile a fragment (pixel) shader, and upload the assembly. */ @@ -2760,6 +2769,9 @@ iris_compile_fs(struct iris_screen *screen, iris_setup_uniforms(devinfo, mem_ctx, nir, &system_values, &num_system_values, &num_cbufs); + if (key->force_dual_color_blend) + iris_force_dual_color_blend(nir); + /* Lower output variables to load_output intrinsics before setting up * binding tables, so iris_setup_binding_table can map any load_output * intrinsics to IRIS_SURFACE_GROUP_RENDER_TARGET_READ on Gfx8 for diff --git a/src/intel/compiler/brw/brw_compiler.h b/src/intel/compiler/brw/brw_compiler.h index 2afe5ad99ed..5ee2d461703 100644 --- a/src/intel/compiler/brw/brw_compiler.h +++ b/src/intel/compiler/brw/brw_compiler.h @@ -371,8 +371,6 @@ struct brw_fs_prog_key { bool alpha_test_replicate_alpha:1; enum intel_sometimes alpha_to_coverage:2; - bool force_dual_color_blend:1; - /** Whether or inputs are interpolated at sample rate by default * * This corresponds to the sample shading API bit in Vulkan or OpenGL which @@ -395,7 +393,7 @@ struct brw_fs_prog_key { bool ignore_sample_mask_out:1; bool coarse_pixel:1; bool api_sample_shading:1; - unsigned pad:12; + unsigned pad:13; }; static inline bool diff --git a/src/intel/compiler/brw/brw_from_nir.cpp b/src/intel/compiler/brw/brw_from_nir.cpp index c84ba0cbff9..040a26a3b83 100644 --- a/src/intel/compiler/brw/brw_from_nir.cpp +++ b/src/intel/compiler/brw/brw_from_nir.cpp @@ -3292,7 +3292,7 @@ alloc_frag_output(nir_to_brw_state &ntb, unsigned location) const unsigned l = GET_FIELD(location, BRW_NIR_FRAG_OUTPUT_LOCATION); const unsigned i = GET_FIELD(location, BRW_NIR_FRAG_OUTPUT_INDEX); - if (i > 0 || (key->force_dual_color_blend && l == FRAG_RESULT_DATA1)) + if (i > 0) return alloc_temporary(ntb.bld, 4, &s.dual_src_output, 1); else if (l == FRAG_RESULT_COLOR) diff --git a/src/intel/compiler/jay/jay_nir.c b/src/intel/compiler/jay/jay_nir.c index 7d9b4bfd724..f7dd15bc377 100644 --- a/src/intel/compiler/jay/jay_nir.c +++ b/src/intel/compiler/jay/jay_nir.c @@ -364,7 +364,6 @@ jay_process_nir(const struct intel_device_info *devinfo, &prog_data->vue.vue_map, 0, 0); } else if (stage == MESA_SHADER_FRAGMENT) { assert(key->fs.mesh_input == INTEL_NEVER && "todo"); - assert(!key->fs.force_dual_color_blend && "todo"); brw_nir_apply_key(pt, &key->base, 32); brw_nir_lower_fs_inputs(nir, devinfo, &key->fs); brw_nir_lower_fs_outputs(nir);