diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 5f25c46ca91..26cb81a1481 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -1999,7 +1999,7 @@ typedef enum { typedef struct nir_io_semantics { 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 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_coherent : 1; unsigned gs_streams : 8; /* xxyyzzww: 2-bit stream index for each component */ diff --git a/src/compiler/nir/nir_lower_blend.c b/src/compiler/nir/nir_lower_blend.c index 10f50d89513..a549cd6a386 100644 --- a/src/compiler/nir/nir_lower_blend.c +++ b/src/compiler/nir/nir_lower_blend.c @@ -586,10 +586,12 @@ consume_dual_stores(nir_builder *b, nir_intrinsic_instr *store, void *data) store->instr.pass_flags = 0; 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; - int rt = color_index_for_location(sem.location); assert(rt >= 0 && rt < 8 && "bounds for dual-source blending"); outputs[rt] = store->src[0].ssa; diff --git a/src/compiler/nir/nir_lower_io.c b/src/compiler/nir/nir_lower_io.c index 87044cd3db0..bbebc51e633 100644 --- a/src/compiler/nir/nir_lower_io.c +++ b/src/compiler/nir/nir_lower_io.c @@ -600,6 +600,17 @@ emit_store(struct lower_io_state *state, nir_def *data, } 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. */ assert(num_slots <= 63); @@ -608,7 +619,7 @@ emit_store(struct lower_io_state *state, nir_def *data, nir_io_semantics semantics = { 0 }; semantics.location = location; 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.medium_precision = is_medium_precision(b->shader, var); semantics.per_view = var->data.per_view; diff --git a/src/compiler/nir/nir_shader_compiler_options.h b/src/compiler/nir/nir_shader_compiler_options.h index 9c850ed3aa3..68a353b57ac 100644 --- a/src/compiler/nir/nir_shader_compiler_options.h +++ b/src/compiler/nir/nir_shader_compiler_options.h @@ -206,6 +206,16 @@ typedef enum { */ 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. */ /** diff --git a/src/compiler/shader_enums.c b/src/compiler/shader_enums.c index 7d8bced137b..089fbbe707e 100644 --- a/src/compiler/shader_enums.c +++ b/src/compiler/shader_enums.c @@ -468,6 +468,7 @@ gl_frag_result_name(gl_frag_result result) ENUM(FRAG_RESULT_DATA5), ENUM(FRAG_RESULT_DATA6), ENUM(FRAG_RESULT_DATA7), + ENUM(FRAG_RESULT_DUAL_SRC_BLEND), }; STATIC_ASSERT(ARRAY_SIZE(names) == FRAG_RESULT_MAX); return NAME(result); @@ -487,3 +488,19 @@ mesa_scope_name(mesa_scope 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; + } +} diff --git a/src/compiler/shader_enums.h b/src/compiler/shader_enums.h index 73141a4c407..e13c18a0089 100644 --- a/src/compiler/shader_enums.h +++ b/src/compiler/shader_enums.h @@ -1026,11 +1026,18 @@ typedef enum FRAG_RESULT_DATA5, FRAG_RESULT_DATA6, 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; const char *gl_frag_result_name(gl_frag_result result); - -#define FRAG_RESULT_MAX (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS) +int mesa_frag_result_get_color_index(gl_frag_result result); /** * \brief Layout qualifiers for gl_FragDepth. diff --git a/src/mesa/program/prog_print.c b/src/mesa/program/prog_print.c index 3951e1dc489..ca2508b6dc0 100644 --- a/src/mesa/program/prog_print.c +++ b/src/mesa/program/prog_print.c @@ -327,7 +327,8 @@ arb_output_attrib_string(GLuint index, unsigned stage) "result.color[4]", "result.color[5]", "result.color[6]", - "result.color[7]" /* MAX_DRAW_BUFFERS = 8 */ + "result.color[7]", /* MAX_DRAW_BUFFERS = 8 */ + "result.dual_src_blend", }; /* sanity checks */