diff --git a/src/gallium/drivers/r600/evergreen_state.c b/src/gallium/drivers/r600/evergreen_state.c index 07e1b6f8bfc..13a304238ed 100644 --- a/src/gallium/drivers/r600/evergreen_state.c +++ b/src/gallium/drivers/r600/evergreen_state.c @@ -362,6 +362,7 @@ static void *evergreen_create_blend_state_mode(struct pipe_context *ctx, blend->dual_src_blend = util_blend_state_is_dual(state, 0); blend->cb_target_mask = target_mask; blend->alpha_to_one = state->alpha_to_one; + blend->alpha_to_one_and_coverage = state->alpha_to_one && state->alpha_to_coverage; if (target_mask) color_control |= S_028808_MODE(mode); @@ -3837,6 +3838,10 @@ void evergreen_update_ps_state(struct pipe_context *ctx, struct r600_pipe_shader break; } } + + if (unlikely(rctx->alpha_to_one_and_coverage)) + exports_ps |= 1; + if (rshader->uses_kill) db_shader_control |= S_02880C_KILL_ENABLE(1); @@ -4137,14 +4142,17 @@ void evergreen_update_db_shader_control(struct r600_context * rctx) return; } + const bool alpha_to_one_and_coverage = rctx->ps_shader->current->key.ps.alpha_to_one_and_coverage; dual_export = rctx->cb_state.export_16bpc && - !rctx->ps_shader->current->ps_depth_export; + !rctx->ps_shader->current->ps_depth_export && + !alpha_to_one_and_coverage; db_shader_control = rctx->ps_shader->current->db_shader_control | S_02880C_DUAL_EXPORT_ENABLE(dual_export) | S_02880C_DB_SOURCE_FORMAT(dual_export ? V_02880C_EXPORT_DB_TWO : V_02880C_EXPORT_DB_FULL) | - S_02880C_ALPHA_TO_MASK_DISABLE(rctx->cb_state.cb0_is_integer); + S_02880C_ALPHA_TO_MASK_DISABLE(rctx->cb_state.cb0_is_integer) | + S_02880C_COVERAGE_TO_MASK_ENABLE(alpha_to_one_and_coverage); /* When alpha test is enabled we can't trust the hw to make the proper * decision on the order in which ztest should be run related to fragment diff --git a/src/gallium/drivers/r600/evergreend.h b/src/gallium/drivers/r600/evergreend.h index 02456c51a75..19636420be2 100644 --- a/src/gallium/drivers/r600/evergreend.h +++ b/src/gallium/drivers/r600/evergreend.h @@ -964,6 +964,9 @@ #define S_02880C_KILL_ENABLE(x) (((unsigned)(x) & 0x1) << 6) #define G_02880C_KILL_ENABLE(x) (((x) >> 6) & 0x1) #define C_02880C_KILL_ENABLE 0xFFFFFFBF +#define S_02880C_COVERAGE_TO_MASK_ENABLE(x) (((unsigned)(x) & 0x1) << 7) +#define G_02880C_COVERAGE_TO_MASK_ENABLE(x) (((x) >> 7) & 0x1) +#define C_02880C_COVERAGE_TO_MASK_ENABLE 0xFFFFFF7F #define S_02880C_MASK_EXPORT_ENABLE(x) (((unsigned)(x) & 0x1) << 8) #define G_02880C_MASK_EXPORT_ENABLE(x) (((x) >> 8) & 0x1) #define C_02880C_MASK_EXPORT_ENABLE 0XFFFFFEFF diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h index 636e7cc1f44..71a0aae1bea 100644 --- a/src/gallium/drivers/r600/r600_pipe.h +++ b/src/gallium/drivers/r600/r600_pipe.h @@ -301,6 +301,7 @@ struct r600_blend_state { unsigned cb_color_control_no_blend; bool dual_src_blend; bool alpha_to_one; + bool alpha_to_one_and_coverage; }; struct r600_dsa_state { @@ -582,6 +583,7 @@ struct r600_context { struct r600_rasterizer_state *rasterizer; bool alpha_to_one; + bool alpha_to_one_and_coverage; bool force_blend_disable; bool gs_tri_strip_adj_fix; bool dual_src_blend; diff --git a/src/gallium/drivers/r600/r600_shader_common.h b/src/gallium/drivers/r600/r600_shader_common.h index c8a3a4c61b6..75620a35381 100644 --- a/src/gallium/drivers/r600/r600_shader_common.h +++ b/src/gallium/drivers/r600/r600_shader_common.h @@ -126,6 +126,7 @@ union r600_shader_key { unsigned image_size_const_offset:5; unsigned color_two_side:1; unsigned alpha_to_one:1; + unsigned alpha_to_one_and_coverage:1; unsigned apply_sample_id_mask:1; unsigned dual_source_blend:1; } ps; diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index 2e3959064e4..40ff58cf06f 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -359,6 +359,7 @@ static void *r600_create_blend_state_mode(struct pipe_context *ctx, blend->cb_color_control = color_control; blend->cb_color_control_no_blend = color_control & C_028808_TARGET_BLEND_ENABLE; blend->alpha_to_one = state->alpha_to_one; + blend->alpha_to_one_and_coverage = state->alpha_to_one && state->alpha_to_coverage; r600_store_context_reg(&blend->buffer, R_028D44_DB_ALPHA_TO_MASK, S_028D44_ALPHA_TO_MASK_ENABLE(state->alpha_to_coverage) | @@ -2533,6 +2534,10 @@ void r600_update_ps_state(struct pipe_context *ctx, struct r600_pipe_shader *sha break; } } + + if (unlikely(rctx->alpha_to_one_and_coverage)) + exports_ps |= 1; + db_shader_control |= S_02880C_Z_EXPORT_ENABLE(z_export); db_shader_control |= S_02880C_STENCIL_REF_EXPORT_ENABLE(stencil_export); db_shader_control |= S_02880C_MASK_EXPORT_ENABLE(mask_export); @@ -2816,11 +2821,14 @@ void r600_update_db_shader_control(struct r600_context * rctx) return; } + const bool alpha_to_one_and_coverage = rctx->ps_shader->current->key.ps.alpha_to_one_and_coverage; dual_export = rctx->cb_state.export_16bpc && - !rctx->ps_shader->current->ps_depth_export; + !rctx->ps_shader->current->ps_depth_export && + !alpha_to_one_and_coverage; db_shader_control = rctx->ps_shader->current->db_shader_control | - S_02880C_DUAL_EXPORT_ENABLE(dual_export); + S_02880C_DUAL_EXPORT_ENABLE(dual_export) | + S_02880C_COVERAGE_TO_MASK_ENABLE(alpha_to_one_and_coverage); ps_conservative_z = rctx->ps_shader->current->shader.ps_conservative_z; diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c index 62433a4477b..a87526c85dd 100644 --- a/src/gallium/drivers/r600/r600_state_common.c +++ b/src/gallium/drivers/r600/r600_state_common.c @@ -174,6 +174,7 @@ static void r600_bind_blend_state_internal(struct r600_context *rctx, bool update_cb = false; rctx->alpha_to_one = blend->alpha_to_one; + rctx->alpha_to_one_and_coverage = blend->alpha_to_one_and_coverage; rctx->dual_src_blend = blend->dual_src_blend; if (!blend_disable) { @@ -823,6 +824,7 @@ static inline void r600_shader_selector_key(const struct pipe_context *ctx, key->ps.alpha_to_one = rctx->alpha_to_one && rctx->rasterizer && rctx->rasterizer->multisample_enable && !rctx->cb_state.cb0_is_integer; + key->ps.alpha_to_one_and_coverage = key->ps.alpha_to_one && rctx->alpha_to_one_and_coverage; key->ps.nr_cbufs = rctx->framebuffer.state.nr_cbufs; key->ps.apply_sample_id_mask = (rctx->ps_iter_samples > 1) || !rctx->rasterizer->multisample_enable; /* Dual-source blending only makes sense with nr_cbufs == 1. */ diff --git a/src/gallium/drivers/r600/r600d.h b/src/gallium/drivers/r600/r600d.h index e4f14217dbb..d4065193fe5 100644 --- a/src/gallium/drivers/r600/r600d.h +++ b/src/gallium/drivers/r600/r600d.h @@ -850,6 +850,9 @@ #define S_02880C_KILL_ENABLE(x) (((unsigned)(x) & 0x1) << 6) #define G_02880C_KILL_ENABLE(x) (((x) >> 6) & 0x1) #define C_02880C_KILL_ENABLE 0xFFFFFFBF +#define S_02880C_COVERAGE_TO_MASK_ENABLE(x) (((unsigned)(x) & 0x1) << 7) +#define G_02880C_COVERAGE_TO_MASK_ENABLE(x) (((x) >> 7) & 0x1) +#define C_02880C_COVERAGE_TO_MASK_ENABLE 0xFFFFFF7F #define S_02880C_MASK_EXPORT_ENABLE(x) (((unsigned)(x) & 0x1) << 8) #define G_02880C_MASK_EXPORT_ENABLE(x) (((x) >> 8) & 0x1) #define C_02880C_MASK_EXPORT_ENABLE 0xFFFFFEFF diff --git a/src/gallium/drivers/r600/sfn/sfn_assembler.cpp b/src/gallium/drivers/r600/sfn/sfn_assembler.cpp index d90b4528963..93aae8a97b2 100644 --- a/src/gallium/drivers/r600/sfn/sfn_assembler.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_assembler.cpp @@ -87,6 +87,7 @@ public: ConditionalJumpTracker m_jump_tracker; CallStack m_callstack; bool ps_alpha_to_one; + bool ps_alpha_to_one_and_coverage; /* End initialized in constructor */ std::set m_nliterals_in_group; @@ -132,6 +133,7 @@ AssamblerVisitor::AssamblerVisitor(r600_shader *sh, const r600_shader_key& key, m_bc(&sh->bc), m_callstack(sh->bc), ps_alpha_to_one(key.ps.alpha_to_one), + ps_alpha_to_one_and_coverage(key.ps.alpha_to_one_and_coverage), m_legacy_math_rules(legacy_math_rules) { if (m_shader->processor_type == MESA_SHADER_FRAGMENT) @@ -532,6 +534,31 @@ AssamblerVisitor::visit(const ExportInstr& exi) { const auto& value = exi.value(); + if (unlikely(ps_alpha_to_one_and_coverage && exi.export_type() == ExportInstr::pixel && + exi.location() == 0)) { + r600_bytecode_output output; + memset(&output, 0, sizeof(output)); + + output.gpr = value.sel(); + output.elem_size = 3; + output.swizzle_x = 7; + output.swizzle_y = 7; + output.swizzle_z = 7; + output.swizzle_w = value[3]->chan(); + output.array_base = 61; + output.burst_count = 1; + output.op = CF_OP_EXPORT; + output.type = exi.export_type(); + + int r = 0; + if ((r = r600_bytecode_add_output(m_bc, &output))) { + R600_ASM_ERR("Error adding export at location %d : err: %d\n", + output.array_base, + r); + m_result = false; + } + } + r600_bytecode_output output; memset(&output, 0, sizeof(output));