[Mesa-dev] [PATCH 2/2] radeonsi: Implement alpha testing in pixel shader.

Michel Dänzer michel at daenzer.net
Thu Nov 8 10:37:05 PST 2012


From: Michel Dänzer <michel.daenzer at amd.com>

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/gallium/drivers/radeonsi/radeonsi_pipe.h   |    2 --
 src/gallium/drivers/radeonsi/radeonsi_shader.c |   36 ++++++++++++++++++++++++
 src/gallium/drivers/radeonsi/radeonsi_shader.h |    2 ++
 src/gallium/drivers/radeonsi/si_state.c        |   24 ++++++++--------
 src/gallium/drivers/radeonsi/si_state.h        |    3 +-
 src/gallium/drivers/radeonsi/si_state_draw.c   |   23 +--------------
 6 files changed, 52 insertions(+), 38 deletions(-)

diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.h b/src/gallium/drivers/radeonsi/radeonsi_pipe.h
index 587cba8..1bd8bfb 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 ce2095c..ec9d9f3 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 23030bc..6f12e76 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 3283f47..3e34fa3 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 00d666f..c49b029 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 d5587c7..b608f20 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);
 	}
-- 
1.7.10.4



More information about the mesa-dev mailing list