Mesa (master): freedreno/a3xx: handle frag z write

Rob Clark robclark at kemper.freedesktop.org
Sat Feb 1 17:05:12 UTC 2014


Module: Mesa
Branch: master
Commit: 8d27be2633f2fc543a6d00d66dcb033798d44749
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=8d27be2633f2fc543a6d00d66dcb033798d44749

Author: Rob Clark <robclark at freedesktop.org>
Date:   Tue Jan 14 13:03:20 2014 -0500

freedreno/a3xx: handle frag z write

Signed-off-by: Rob Clark <robclark at freedesktop.org>

---

 src/gallium/drivers/freedreno/a3xx/fd3_compiler.c |    9 ++++-
 src/gallium/drivers/freedreno/a3xx/fd3_draw.c     |   15 ++++----
 src/gallium/drivers/freedreno/a3xx/fd3_emit.c     |   38 +++++++++++++++------
 src/gallium/drivers/freedreno/a3xx/fd3_emit.h     |    2 +-
 src/gallium/drivers/freedreno/a3xx/fd3_program.c  |   11 ++++--
 src/gallium/drivers/freedreno/a3xx/fd3_program.h  |    1 +
 src/gallium/drivers/freedreno/freedreno_screen.c  |    2 +-
 7 files changed, 53 insertions(+), 25 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c b/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c
index c8e66fc..2c32c0f 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_compiler.c
@@ -1341,6 +1341,7 @@ decl_out(struct fd3_compile_context *ctx, struct tgsi_full_declaration *decl)
 {
 	struct fd3_shader_stateobj *so = ctx->so;
 	unsigned base = ctx->base_reg[TGSI_FILE_OUTPUT];
+	unsigned comp = 0;
 	unsigned name = decl->Semantic.Name;
 	unsigned i;
 
@@ -1351,6 +1352,8 @@ decl_out(struct fd3_compile_context *ctx, struct tgsi_full_declaration *decl)
 	if (ctx->type == TGSI_PROCESSOR_VERTEX) {
 		switch (name) {
 		case TGSI_SEMANTIC_POSITION:
+			so->writes_pos = true;
+			/* fallthrough */
 		case TGSI_SEMANTIC_PSIZE:
 		case TGSI_SEMANTIC_COLOR:
 		case TGSI_SEMANTIC_GENERIC:
@@ -1363,6 +1366,10 @@ decl_out(struct fd3_compile_context *ctx, struct tgsi_full_declaration *decl)
 		}
 	} else {
 		switch (name) {
+		case TGSI_SEMANTIC_POSITION:
+			comp = 2;  /* tgsi will write to .z component */
+			so->writes_pos = true;
+			/* fallthrough */
 		case TGSI_SEMANTIC_COLOR:
 			break;
 		default:
@@ -1374,7 +1381,7 @@ decl_out(struct fd3_compile_context *ctx, struct tgsi_full_declaration *decl)
 	for (i = decl->Range.First; i <= decl->Range.Last; i++) {
 		unsigned n = so->outputs_count++;
 		so->outputs[n].semantic = decl_semantic(&decl->Semantic);
-		so->outputs[n].regid = regid(i + base, 0);
+		so->outputs[n].regid = regid(i + base, comp);
 	}
 }
 
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c
index 4f28b0e..a482aec 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_draw.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_draw.c
@@ -70,7 +70,7 @@ static void
 draw_impl(struct fd_context *ctx, const struct pipe_draw_info *info,
 		struct fd_ringbuffer *ring, unsigned dirty, bool binning)
 {
-	fd3_emit_state(ctx, ring, dirty, binning);
+	fd3_emit_state(ctx, ring, &ctx->prog, dirty, binning);
 
 	if (dirty & FD_DIRTY_VTXBUF)
 		emit_vertexbufs(ctx, ring);
@@ -114,10 +114,7 @@ fd3_clear_binning(struct fd_context *ctx, unsigned dirty)
 	struct fd3_context *fd3_ctx = fd3_context(ctx);
 	struct fd_ringbuffer *ring = ctx->binning_ring;
 
-	fd3_emit_state(ctx, ring, dirty & (FD_DIRTY_VIEWPORT |
-			FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR), true);
-
-	fd3_program_emit(ring, &ctx->solid_prog, true);
+	fd3_emit_state(ctx, ring, &ctx->solid_prog, dirty, true);
 
 	fd3_emit_vertex_bufs(ring, &ctx->solid_prog, (struct fd3_vertex_buf[]) {
 			{ .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT },
@@ -152,11 +149,13 @@ fd3_clear(struct fd_context *ctx, unsigned buffers,
 	unsigned dirty = ctx->dirty;
 	unsigned ce, i;
 
+	dirty &= FD_DIRTY_VIEWPORT | FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR;
+	dirty |= FD_DIRTY_PROG;
+
 	fd3_clear_binning(ctx, dirty);
 
 	/* emit generic state now: */
-	fd3_emit_state(ctx, ring, dirty & (FD_DIRTY_VIEWPORT |
-			FD_DIRTY_FRAMEBUFFER | FD_DIRTY_SCISSOR), false);
+	fd3_emit_state(ctx, ring, &ctx->solid_prog, dirty, false);
 
 	OUT_PKT0(ring, REG_A3XX_RB_BLEND_ALPHA, 1);
 	OUT_RING(ring, A3XX_RB_BLEND_ALPHA_UINT(0xff) |
@@ -246,8 +245,6 @@ fd3_clear(struct fd_context *ctx, unsigned buffers,
 	OUT_PKT0(ring, REG_A3XX_GRAS_SU_MODE_CONTROL, 1);
 	OUT_RING(ring, A3XX_GRAS_SU_MODE_CONTROL_LINEHALFWIDTH(0));
 
-	fd3_program_emit(ring, &ctx->solid_prog, false);
-
 	fd3_emit_vertex_bufs(ring, &ctx->solid_prog, (struct fd3_vertex_buf[]) {
 			{ .prsc = fd3_ctx->solid_vbuf, .stride = 12, .format = PIPE_FORMAT_R32G32B32_FLOAT },
 		}, 1);
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c
index 543c116..3ca49ff 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.c
@@ -338,7 +338,7 @@ fd3_emit_vertex_bufs(struct fd_ringbuffer *ring,
 
 void
 fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
-		uint32_t dirty, bool binning)
+		struct fd_program_stateobj *prog, uint32_t dirty, bool binning)
 {
 	emit_marker(ring, 5);
 
@@ -370,9 +370,6 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
 		OUT_PKT0(ring, REG_A3XX_RB_ALPHA_REF, 1);
 		OUT_RING(ring, zsa->rb_alpha_ref);
 
-		OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
-		OUT_RING(ring, zsa->rb_depth_control);
-
 		OUT_PKT0(ring, REG_A3XX_RB_STENCIL_CONTROL, 1);
 		OUT_RING(ring, zsa->rb_stencil_control);
 
@@ -383,6 +380,17 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
 				A3XX_RB_STENCILREFMASK_BF_STENCILREF(sr->ref_value[1]));
 	}
 
+	if (dirty & (FD_DIRTY_ZSA | FD_DIRTY_PROG)) {
+		struct fd3_shader_stateobj *fp = prog->fp;
+		uint32_t val = fd3_zsa_stateobj(ctx->zsa)->rb_depth_control;
+		if (fp->writes_pos) {
+			val |= A3XX_RB_DEPTH_CONTROL_FRAG_WRITES_Z;
+			val |= A3XX_RB_DEPTH_CONTROL_EARLY_Z_DISABLE;
+		}
+		OUT_PKT0(ring, REG_A3XX_RB_DEPTH_CONTROL, 1);
+		OUT_RING(ring, val);
+	}
+
 	if (dirty & FD_DIRTY_RASTERIZER) {
 		struct fd3_rasterizer_stateobj *rasterizer =
 				fd3_rasterizer_stateobj(ctx->rasterizer);
@@ -397,15 +405,23 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
 		OUT_PKT0(ring, REG_A3XX_GRAS_SU_POLY_OFFSET_SCALE, 2);
 		OUT_RING(ring, rasterizer->gras_su_poly_offset_scale);
 		OUT_RING(ring, rasterizer->gras_su_poly_offset_offset);
+	}
 
+	if (dirty & (FD_DIRTY_RASTERIZER | FD_DIRTY_PROG)) {
+		struct fd3_shader_stateobj *fp = prog->fp;
+		uint32_t val = fd3_rasterizer_stateobj(ctx->rasterizer)
+				->gras_cl_clip_cntl;
+		if (fp->writes_pos) {
+			val |= A3XX_GRAS_CL_CLIP_CNTL_ZCLIP_DISABLE;
+		}
 		OUT_PKT0(ring, REG_A3XX_GRAS_CL_CLIP_CNTL, 1);
-		OUT_RING(ring, rasterizer->gras_cl_clip_cntl);
+		OUT_RING(ring, val);
 	}
 
 	if (dirty & (FD_DIRTY_RASTERIZER | FD_DIRTY_PROG)) {
 		struct fd3_rasterizer_stateobj *rasterizer =
 				fd3_rasterizer_stateobj(ctx->rasterizer);
-		struct fd3_shader_stateobj *fp = ctx->prog.fp;
+		struct fd3_shader_stateobj *fp = prog->fp;
 		uint32_t stride_in_vpc;
 
 		stride_in_vpc = align(fp->total_in, 4) / 4;
@@ -443,14 +459,14 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
 	}
 
 	if (dirty & FD_DIRTY_PROG)
-		fd3_program_emit(ring, &ctx->prog, binning);
+		fd3_program_emit(ring, prog, binning);
 
 	OUT_PKT3(ring, CP_EVENT_WRITE, 1);
 	OUT_RING(ring, HLSQ_FLUSH);
 
-	if (dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) {
-		struct fd_program_stateobj *prog = &ctx->prog;
-
+	if ((dirty & (FD_DIRTY_PROG | FD_DIRTY_CONSTBUF)) &&
+			/* evil hack to deal sanely with clear path: */
+			(prog == &ctx->prog)) {
 		emit_constants(ring,  SB_VERT_SHADER,
 				&ctx->constbuf[PIPE_SHADER_VERTEX],
 				(prog->dirty & FD_SHADER_DIRTY_VP) ? prog->vp : NULL);
@@ -459,7 +475,7 @@ fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
 				(prog->dirty & FD_SHADER_DIRTY_FP) ? prog->fp : NULL);
 	}
 
-	if (dirty & FD_DIRTY_BLEND) {
+	if ((dirty & FD_DIRTY_BLEND) && ctx->blend) {
 		struct fd3_blend_stateobj *blend = fd3_blend_stateobj(ctx->blend);
 		uint32_t i;
 
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h
index 1b4774d..8584eb5 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_emit.h
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_emit.h
@@ -59,7 +59,7 @@ void fd3_emit_vertex_bufs(struct fd_ringbuffer *ring,
 		struct fd_program_stateobj *prog,
 		struct fd3_vertex_buf *vbufs, uint32_t n);
 void fd3_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring,
-		uint32_t dirty, bool binning);
+		struct fd_program_stateobj *prog, uint32_t dirty, bool binning);
 void fd3_emit_restore(struct fd_context *ctx);
 
 #endif /* FD3_EMIT_H */
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_program.c b/src/gallium/drivers/freedreno/a3xx/fd3_program.c
index 2d95583..3df29ec 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_program.c
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_program.c
@@ -247,7 +247,7 @@ fd3_program_emit(struct fd_ringbuffer *ring,
 	const struct fd3_shader_stateobj *fp = prog->fp;
 	const struct ir3_shader_info *vsi = &vp->info;
 	const struct ir3_shader_info *fsi = &fp->info;
-	uint32_t pos_regid, psize_regid, color_regid;
+	uint32_t pos_regid, posz_regid, psize_regid, color_regid;
 	int i;
 
 	if (binning) {
@@ -259,6 +259,8 @@ fd3_program_emit(struct fd_ringbuffer *ring,
 
 	pos_regid = find_regid(vp,
 		fd3_semantic_name(TGSI_SEMANTIC_POSITION, 0));
+	posz_regid = find_regid(fp,
+		fd3_semantic_name(TGSI_SEMANTIC_POSITION, 0));
 	psize_regid = find_regid(vp,
 		fd3_semantic_name(TGSI_SEMANTIC_PSIZE, 0));
 	color_regid = find_regid(fp,
@@ -389,7 +391,12 @@ fd3_program_emit(struct fd_ringbuffer *ring,
 	OUT_RING(ring, 0x00000000);        /* SP_FS_FLAT_SHAD_MODE_REG_1 */
 
 	OUT_PKT0(ring, REG_A3XX_SP_FS_OUTPUT_REG, 1);
-	OUT_RING(ring, 0x00000000);        /* SP_FS_OUTPUT_REG */
+	if (fp->writes_pos) {
+		OUT_RING(ring, A3XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE |
+				A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID(posz_regid));
+	} else {
+		OUT_RING(ring, 0x00000000);
+	}
 
 	OUT_PKT0(ring, REG_A3XX_SP_FS_MRT_REG(0), 4);
 	OUT_RING(ring, A3XX_SP_FS_MRT_REG_REGID(color_regid) |
diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_program.h b/src/gallium/drivers/freedreno/a3xx/fd3_program.h
index e7aaa47..4aeeb2e 100644
--- a/src/gallium/drivers/freedreno/a3xx/fd3_program.h
+++ b/src/gallium/drivers/freedreno/a3xx/fd3_program.h
@@ -81,6 +81,7 @@ struct fd3_shader_stateobj {
 		fd3_semantic semantic;
 		uint8_t regid;
 	} outputs[16];
+	bool writes_pos;
 
 	/* vertices/inputs: */
 	unsigned inputs_count;
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index f36bd8b..d6d3c6c 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -153,7 +153,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
 	case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
 	case PIPE_CAP_BLEND_EQUATION_SEPARATE:
 	case PIPE_CAP_TEXTURE_SWIZZLE:
-	case PIPE_CAP_SHADER_STENCIL_EXPORT:
 	case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
 	case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
 	case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
@@ -176,6 +175,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
 	case PIPE_CAP_USER_CONSTANT_BUFFERS:
 		return 1;
 
+	case PIPE_CAP_SHADER_STENCIL_EXPORT:
 	case PIPE_CAP_TGSI_TEXCOORD:
 	case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
 		return 0;




More information about the mesa-commit mailing list