nir: add FRAG_RESULT_DUAL_SRC_BLEND and an option to use it

This is potentially nicer for some drivers. AMD drivers will use it.

mesa_frag_result_get_color_index will be used often.

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38604>
This commit is contained in:
Marek Olšák 2025-11-23 13:11:11 -05:00 committed by Marge Bot
parent ddd0b0c3a8
commit 9a2f1be814
7 changed files with 55 additions and 7 deletions

View file

@ -1999,7 +1999,7 @@ typedef enum {
typedef struct nir_io_semantics { typedef struct nir_io_semantics {
unsigned location : 7; /* gl_vert_attrib, gl_varying_slot, or gl_frag_result */ unsigned location : 7; /* gl_vert_attrib, gl_varying_slot, or gl_frag_result */
unsigned num_slots : 6; /* max 32, may be pessimistic with const indexing */ unsigned num_slots : 6; /* max 32, may be pessimistic with const indexing */
unsigned dual_source_blend_index : 1; unsigned dual_source_blend_index : 1; /* used without nir_io_use_frag_result_dual_src_blend */
unsigned fb_fetch_output : 1; /* for GL_KHR_blend_equation_advanced */ unsigned fb_fetch_output : 1; /* for GL_KHR_blend_equation_advanced */
unsigned fb_fetch_output_coherent : 1; unsigned fb_fetch_output_coherent : 1;
unsigned gs_streams : 8; /* xxyyzzww: 2-bit stream index for each component */ unsigned gs_streams : 8; /* xxyyzzww: 2-bit stream index for each component */

View file

@ -586,10 +586,12 @@ consume_dual_stores(nir_builder *b, nir_intrinsic_instr *store, void *data)
store->instr.pass_flags = 0; store->instr.pass_flags = 0;
nir_io_semantics sem = nir_intrinsic_io_semantics(store); nir_io_semantics sem = nir_intrinsic_io_semantics(store);
if (sem.dual_source_blend_index == 0) int rt = 0;
if (sem.dual_source_blend_index)
rt = color_index_for_location(sem.location);
else if (sem.location != FRAG_RESULT_DUAL_SRC_BLEND)
return false; return false;
int rt = color_index_for_location(sem.location);
assert(rt >= 0 && rt < 8 && "bounds for dual-source blending"); assert(rt >= 0 && rt < 8 && "bounds for dual-source blending");
outputs[rt] = store->src[0].ssa; outputs[rt] = store->src[0].ssa;

View file

@ -600,6 +600,17 @@ emit_store(struct lower_io_state *state, nir_def *data,
} }
int location = var->data.location; int location = var->data.location;
bool dual_src_blend = var->data.index > 0;
/* Set FRAG_RESULT_DUAL_SRC_BLEND if the driver prefers that. */
if (dual_src_blend &&
b->shader->options->io_options & nir_io_use_frag_result_dual_src_blend) {
assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);
assert(location == FRAG_RESULT_COLOR || location == FRAG_RESULT_DATA0);
location = FRAG_RESULT_DUAL_SRC_BLEND;
dual_src_blend = false;
}
/* Maximum values in nir_io_semantics. */ /* Maximum values in nir_io_semantics. */
assert(num_slots <= 63); assert(num_slots <= 63);
@ -608,7 +619,7 @@ emit_store(struct lower_io_state *state, nir_def *data,
nir_io_semantics semantics = { 0 }; nir_io_semantics semantics = { 0 };
semantics.location = location; semantics.location = location;
semantics.num_slots = num_slots; semantics.num_slots = num_slots;
semantics.dual_source_blend_index = var->data.index; semantics.dual_source_blend_index = dual_src_blend;
semantics.gs_streams = gs_streams; semantics.gs_streams = gs_streams;
semantics.medium_precision = is_medium_precision(b->shader, var); semantics.medium_precision = is_medium_precision(b->shader, var);
semantics.per_view = var->data.per_view; semantics.per_view = var->data.per_view;

View file

@ -206,6 +206,16 @@ typedef enum {
*/ */
nir_io_assign_color_input_bases_after_all_other_inputs = BITFIELD_BIT(11), nir_io_assign_color_input_bases_after_all_other_inputs = BITFIELD_BIT(11),
/**
* Whether nir_lower_io should use FRAG_RESULT_DUAL_SRC_BLEND instead of
* nir_io_semantics::dual_source_blend_index.
*
* This has the advantage that it behaves like a normal output and its
* presence is reflected in shader_info::outputs_written instead of
* shader_info::fs::color_is_dual_source.
*/
nir_io_use_frag_result_dual_src_blend = BITFIELD_BIT(11),
/* Options affecting the GLSL compiler or Gallium are below. */ /* Options affecting the GLSL compiler or Gallium are below. */
/** /**

View file

@ -468,6 +468,7 @@ gl_frag_result_name(gl_frag_result result)
ENUM(FRAG_RESULT_DATA5), ENUM(FRAG_RESULT_DATA5),
ENUM(FRAG_RESULT_DATA6), ENUM(FRAG_RESULT_DATA6),
ENUM(FRAG_RESULT_DATA7), ENUM(FRAG_RESULT_DATA7),
ENUM(FRAG_RESULT_DUAL_SRC_BLEND),
}; };
STATIC_ASSERT(ARRAY_SIZE(names) == FRAG_RESULT_MAX); STATIC_ASSERT(ARRAY_SIZE(names) == FRAG_RESULT_MAX);
return NAME(result); return NAME(result);
@ -487,3 +488,19 @@ mesa_scope_name(mesa_scope scope)
}; };
return NAME(scope); return NAME(scope);
} }
int
mesa_frag_result_get_color_index(gl_frag_result result)
{
switch (result) {
case FRAG_RESULT_COLOR:
return 0;
case FRAG_RESULT_DUAL_SRC_BLEND:
return 1;
default:
if (result >= FRAG_RESULT_DATA0 && result <= FRAG_RESULT_DATA7)
return result - FRAG_RESULT_DATA0;
return -1;
}
}

View file

@ -1026,11 +1026,18 @@ typedef enum
FRAG_RESULT_DATA5, FRAG_RESULT_DATA5,
FRAG_RESULT_DATA6, FRAG_RESULT_DATA6,
FRAG_RESULT_DATA7, FRAG_RESULT_DATA7,
/* The color output that sets the values for the SRC1 blend factors, also
* known as dual source blending. This is typically the second color output,
* and DATA1-DATA7 can't be written when this one is written. Enabled by
* nir_io_use_frag_result_dual_src_blend.
*/
FRAG_RESULT_DUAL_SRC_BLEND,
FRAG_RESULT_MAX,
} gl_frag_result; } gl_frag_result;
const char *gl_frag_result_name(gl_frag_result result); const char *gl_frag_result_name(gl_frag_result result);
int mesa_frag_result_get_color_index(gl_frag_result result);
#define FRAG_RESULT_MAX (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
/** /**
* \brief Layout qualifiers for gl_FragDepth. * \brief Layout qualifiers for gl_FragDepth.

View file

@ -327,7 +327,8 @@ arb_output_attrib_string(GLuint index, unsigned stage)
"result.color[4]", "result.color[4]",
"result.color[5]", "result.color[5]",
"result.color[6]", "result.color[6]",
"result.color[7]" /* MAX_DRAW_BUFFERS = 8 */ "result.color[7]", /* MAX_DRAW_BUFFERS = 8 */
"result.dual_src_blend",
}; };
/* sanity checks */ /* sanity checks */