From: Michel Dänzer Date: Fri, 2 Nov 2012 14:57:30 +0000 (+0100) Subject: radeonsi: Implement alpha testing in pixel shader. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7708a864648aecd8aafb484ec7db18c2aba9e957;p=mesa.git radeonsi: Implement alpha testing in pixel shader. Signed-off-by: Michel Dänzer --- diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.h b/src/gallium/drivers/radeonsi/radeonsi_pipe.h index 587cba8c841..1bd8bfbbcfd 100644 --- a/src/gallium/drivers/radeonsi/radeonsi_pipe.h +++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.h @@ -134,8 +134,6 @@ struct r600_context { unsigned sprite_coord_enable; unsigned export_16bpc; unsigned spi_shader_col_format; - unsigned alpha_ref; - boolean alpha_ref_dirty; struct r600_textures_info vs_samplers; struct r600_textures_info ps_samplers; struct si_resource *border_color_table; diff --git a/src/gallium/drivers/radeonsi/radeonsi_shader.c b/src/gallium/drivers/radeonsi/radeonsi_shader.c index ce2095c8652..ec9d9f3a7a1 100644 --- a/src/gallium/drivers/radeonsi/radeonsi_shader.c +++ b/src/gallium/drivers/radeonsi/radeonsi_shader.c @@ -31,6 +31,7 @@ #include "gallivm/lp_bld_const.h" #include "gallivm/lp_bld_gather.h" #include "gallivm/lp_bld_intr.h" +#include "gallivm/lp_bld_logic.h" #include "gallivm/lp_bld_tgsi.h" #include "radeon_llvm.h" #include "radeon_llvm_emit.h" @@ -546,6 +547,37 @@ static void si_llvm_emit_prologue(struct lp_build_tgsi_context *bld_base) } +static void si_alpha_test(struct lp_build_tgsi_context *bld_base, + unsigned index) +{ + struct si_shader_context *si_shader_ctx = si_shader_context(bld_base); + struct gallivm_state *gallivm = bld_base->base.gallivm; + + if (si_shader_ctx->key.alpha_func != PIPE_FUNC_NEVER) { + LLVMValueRef out_ptr = si_shader_ctx->radeon_bld.soa.outputs[index][3]; + LLVMValueRef alpha_pass = + lp_build_cmp(&bld_base->base, + si_shader_ctx->key.alpha_func, + LLVMBuildLoad(gallivm->builder, out_ptr, ""), + lp_build_const_float(gallivm, si_shader_ctx->key.alpha_ref)); + LLVMValueRef arg = + lp_build_select(&bld_base->base, + alpha_pass, + lp_build_const_float(gallivm, 1.0f), + lp_build_const_float(gallivm, -1.0f)); + + build_intrinsic(gallivm->builder, + "llvm.AMDGPU.kill", + LLVMVoidTypeInContext(gallivm->context), + &arg, 1, 0); + } else { + build_intrinsic(gallivm->builder, + "llvm.AMDGPU.kilp", + LLVMVoidTypeInContext(gallivm->context), + NULL, 0, 0); + } +} + /* XXX: This is partially implemented for VS only at this point. It is not complete */ static void si_llvm_emit_epilogue(struct lp_build_tgsi_context * bld_base) { @@ -606,6 +638,10 @@ static void si_llvm_emit_epilogue(struct lp_build_tgsi_context * bld_base) param_count++; } else { target = V_008DFC_SQ_EXP_MRT + color_count; + if (color_count == 0 && + si_shader_ctx->key.alpha_func != PIPE_FUNC_ALWAYS) + si_alpha_test(bld_base, index); + color_count++; } break; diff --git a/src/gallium/drivers/radeonsi/radeonsi_shader.h b/src/gallium/drivers/radeonsi/radeonsi_shader.h index 23030bc4f63..6f12e760b8e 100644 --- a/src/gallium/drivers/radeonsi/radeonsi_shader.h +++ b/src/gallium/drivers/radeonsi/radeonsi_shader.h @@ -81,6 +81,8 @@ struct si_shader_key { unsigned export_16bpc:8; unsigned nr_cbufs:4; unsigned color_two_side:1; + unsigned alpha_func:3; + float alpha_ref; }; struct si_pipe_shader { diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c index 3283f47ceb4..3e34fa360bf 100644 --- a/src/gallium/drivers/radeonsi/si_state.c +++ b/src/gallium/drivers/radeonsi/si_state.c @@ -564,7 +564,7 @@ static void *si_create_dsa_state(struct pipe_context *ctx, { struct si_state_dsa *dsa = CALLOC_STRUCT(si_state_dsa); struct si_pm4_state *pm4 = &dsa->pm4; - unsigned db_depth_control, /* alpha_test_control, */ alpha_ref; + unsigned db_depth_control; unsigned db_render_override, db_render_control; uint32_t db_stencil_control = 0; @@ -599,14 +599,12 @@ static void *si_create_dsa_state(struct pipe_context *ctx, } /* alpha */ - //alpha_test_control = 0; - alpha_ref = 0; if (state->alpha.enabled) { - //alpha_test_control = S_028410_ALPHA_FUNC(state->alpha.func); - //alpha_test_control |= S_028410_ALPHA_TEST_ENABLE(1); - alpha_ref = fui(state->alpha.ref_value); + dsa->alpha_func = state->alpha.func; + dsa->alpha_ref = state->alpha.ref_value; + } else { + dsa->alpha_func = PIPE_FUNC_ALWAYS; } - dsa->alpha_ref = alpha_ref; /* misc */ db_render_control = 0; @@ -642,10 +640,6 @@ static void si_bind_dsa_state(struct pipe_context *ctx, void *state) si_pm4_bind_state(rctx, dsa, dsa); si_update_dsa_stencil_ref(rctx); - - // TODO - rctx->alpha_ref = dsa->alpha_ref; - rctx->alpha_ref_dirty = true; } static void si_delete_dsa_state(struct pipe_context *ctx, void *state) @@ -1639,8 +1633,6 @@ static void si_cb(struct r600_context *rctx, struct si_pm4_state *pm4, S_028C70_NUMBER_TYPE(ntype) | S_028C70_ENDIAN(endian); - rctx->alpha_ref_dirty = true; - offset += r600_resource_va(rctx->context.screen, state->cbufs[cb]->texture); offset >>= 8; @@ -1848,6 +1840,12 @@ static INLINE struct si_shader_key si_shader_selector_key(struct pipe_context *c key.color_two_side = rctx->queued.named.rasterizer->two_side; /*key.flatshade = rctx->queued.named.rasterizer->flatshade;*/ } + if (rctx->queued.named.dsa) { + key.alpha_func = rctx->queued.named.dsa->alpha_func; + key.alpha_ref = rctx->queued.named.dsa->alpha_ref; + } else { + key.alpha_func = PIPE_FUNC_ALWAYS; + } } return key; diff --git a/src/gallium/drivers/radeonsi/si_state.h b/src/gallium/drivers/radeonsi/si_state.h index 00d666f520f..c49b029d71a 100644 --- a/src/gallium/drivers/radeonsi/si_state.h +++ b/src/gallium/drivers/radeonsi/si_state.h @@ -55,7 +55,8 @@ struct si_state_rasterizer { struct si_state_dsa { struct si_pm4_state pm4; - unsigned alpha_ref; + float alpha_ref; + unsigned alpha_func; unsigned db_render_override; unsigned db_render_control; uint8_t valuemask[2]; diff --git a/src/gallium/drivers/radeonsi/si_state_draw.c b/src/gallium/drivers/radeonsi/si_state_draw.c index d5587c78a33..b608f201093 100644 --- a/src/gallium/drivers/radeonsi/si_state_draw.c +++ b/src/gallium/drivers/radeonsi/si_state_draw.c @@ -147,7 +147,7 @@ static void si_pipe_shader_ps(struct pipe_context *ctx, struct si_pipe_shader *s if (shader->shader.output[i].name == TGSI_SEMANTIC_STENCIL) db_shader_control |= 0; // XXX OP_VAL or TEST_VAL? } - if (shader->shader.uses_kill) + if (shader->shader.uses_kill || shader->key.alpha_func != PIPE_FUNC_ALWAYS) db_shader_control |= S_02880C_KILL_ENABLE(1); exports_ps = 0; @@ -306,23 +306,6 @@ static bool si_update_draw_info_state(struct r600_context *rctx, return true; } -static void si_update_alpha_ref(struct r600_context *rctx) -{ -#if 0 - unsigned alpha_ref; - struct r600_pipe_state rstate; - - alpha_ref = rctx->alpha_ref; - rstate.nregs = 0; - if (rctx->export_16bpc) - alpha_ref &= ~0x1FFF; - si_pm4_set_reg(&rstate, R_028438_SX_ALPHA_REF, alpha_ref); - - si_pm4_set_state(rctx, TODO, pm4); - rctx->alpha_ref_dirty = false; -#endif -} - static void si_update_spi_map(struct r600_context *rctx) { struct si_shader *ps = &rctx->ps_shader->current->shader; @@ -392,10 +375,6 @@ static void si_update_derived_state(struct r600_context *rctx) si_shader_select(ctx, rctx->ps_shader, &ps_dirty); - if (rctx->alpha_ref_dirty) { - si_update_alpha_ref(rctx); - } - if (!rctx->vs_shader->current->pm4) { si_pipe_shader_vs(ctx, rctx->vs_shader->current); }