Mesa (master): freedreno/a6xx: add support for dual-source blending

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Nov 26 17:36:48 UTC 2020


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

Author: Danylo Piliaiev <dpiliaiev at igalia.com>
Date:   Thu Nov 19 11:27:33 2020 +0200

freedreno/a6xx: add support for dual-source blending

Signed-off-by: Danylo Piliaiev <dpiliaiev at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7708>

---

 src/gallium/drivers/freedreno/a6xx/fd6_blend.c   |  8 ++++++-
 src/gallium/drivers/freedreno/a6xx/fd6_blend.h   |  2 ++
 src/gallium/drivers/freedreno/a6xx/fd6_emit.c    | 28 +++++++++++++++++++++---
 src/gallium/drivers/freedreno/a6xx/fd6_gmem.c    | 23 -------------------
 src/gallium/drivers/freedreno/a6xx/fd6_program.c |  5 +++++
 src/gallium/drivers/freedreno/freedreno_screen.c |  2 +-
 6 files changed, 40 insertions(+), 28 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blend.c b/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
index fe63be97fd5..b645b884ab6 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
@@ -27,6 +27,7 @@
 
 #include "pipe/p_state.h"
 #include "util/u_blend.h"
+#include "util/u_dual_blend.h"
 #include "util/u_string.h"
 #include "util/u_memory.h"
 
@@ -127,6 +128,7 @@ __fd6_setup_blend_variant(struct fd6_blend_stateobj *blend, unsigned sample_mask
 			.unk8              = true,
 			.alpha_to_coverage = cso->alpha_to_coverage,
 			.enabled           = !!mrt_blend,
+			.dual_color_in_enable = blend->use_dual_src_blend,
 		));
 
 	OUT_REG(ring, A6XX_RB_BLEND_CNTL(
@@ -134,7 +136,8 @@ __fd6_setup_blend_variant(struct fd6_blend_stateobj *blend, unsigned sample_mask
 			.alpha_to_coverage = cso->alpha_to_coverage,
 			.alpha_to_one = cso->alpha_to_one,
 			.independent_blend = cso->independent_blend_enable,
-			.sample_mask       = sample_mask
+			.sample_mask       = sample_mask,
+			.dual_color_in_enable = blend->use_dual_src_blend,
 		));
 
 	so->sample_mask = sample_mask;
@@ -161,6 +164,9 @@ fd6_blend_state_create(struct pipe_context *pctx,
 		so->reads_dest |= util_logicop_reads_dest(cso->logicop_func);
 	}
 
+	so->use_dual_src_blend =
+		cso->rt[0].blend_enable && util_blend_state_is_dual(cso, 0);
+
 	unsigned nr = cso->independent_blend_enable ? cso->max_rt : 0;
 	for (unsigned i = 0; i <= nr; i++) {
 		const struct pipe_rt_blend_state *rt = &cso->rt[i];
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blend.h b/src/gallium/drivers/freedreno/a6xx/fd6_blend.h
index ef7dde8cf65..0878cf47c75 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blend.h
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blend.h
@@ -47,6 +47,8 @@ struct fd6_blend_variant {
 struct fd6_blend_stateobj {
 	struct pipe_blend_state base;
 
+	bool use_dual_src_blend;
+
 	struct fd_context *ctx;
 	bool reads_dest;
 	struct util_dynarray variants;
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
index 83afd1c6575..ca21d292da2 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
@@ -955,24 +955,46 @@ fd6_emit_state(struct fd_ringbuffer *ring, struct fd6_emit *emit)
 						   FD6_GROUP_RASTERIZER, ENABLE_ALL);
 	}
 
-	if (dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_RASTERIZER_DISCARD | FD_DIRTY_PROG)) {
+	if (dirty & (FD_DIRTY_FRAMEBUFFER | FD_DIRTY_RASTERIZER_DISCARD |
+				 FD_DIRTY_PROG | FD_DIRTY_BLEND_DUAL)) {
 		struct fd_ringbuffer *ring = fd_submit_new_ringbuffer(
-				emit->ctx->batch->submit, 5 * 4, FD_RINGBUFFER_STREAMING);
+				emit->ctx->batch->submit, 9 * 4, FD_RINGBUFFER_STREAMING);
 
 		unsigned nr = pfb->nr_cbufs;
 
 		if (ctx->rasterizer->rasterizer_discard)
 			nr = 0;
 
+		struct fd6_blend_stateobj *blend = fd6_blend_stateobj(ctx->blend);
+
+		if (blend->use_dual_src_blend)
+			nr++;
+
 		OUT_PKT4(ring, REG_A6XX_RB_FS_OUTPUT_CNTL0, 2);
 		OUT_RING(ring, COND(fs->writes_pos, A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_Z) |
 				COND(fs->writes_smask && pfb->samples > 1,
-						A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_SAMPMASK));
+						A6XX_RB_FS_OUTPUT_CNTL0_FRAG_WRITES_SAMPMASK) |
+				COND(blend->use_dual_src_blend,
+						A6XX_RB_FS_OUTPUT_CNTL0_DUAL_COLOR_IN_ENABLE));
 		OUT_RING(ring, A6XX_RB_FS_OUTPUT_CNTL1_MRT(nr));
 
 		OUT_PKT4(ring, REG_A6XX_SP_FS_OUTPUT_CNTL1, 1);
 		OUT_RING(ring, A6XX_SP_FS_OUTPUT_CNTL1_MRT(nr));
 
+		unsigned mrt_components = 0;
+		for (unsigned i = 0; i < pfb->nr_cbufs; i++) {
+			if (!pfb->cbufs[i])
+				continue;
+			mrt_components |= 0xf << (i * 4);
+		}
+
+		/* dual source blending has an extra fs output in the 2nd slot */
+		if (blend->use_dual_src_blend)
+			mrt_components |= 0xf << 4;
+
+		OUT_REG(ring, A6XX_SP_FS_RENDER_COMPONENTS(.dword = mrt_components));
+		OUT_REG(ring, A6XX_RB_RENDER_COMPONENTS(.dword = mrt_components));
+
 		fd6_emit_take_group(emit, ring, FD6_GROUP_PROG_FB_RAST, ENABLE_DRAW);
 	}
 
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
index 5aac4d5438b..0c1348ca4b5 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
@@ -73,7 +73,6 @@ static void
 emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
 		const struct fd_gmem_stateobj *gmem)
 {
-	unsigned char mrt_comp[A6XX_MAX_RENDER_TARGETS] = {0};
 	unsigned srgb_cntl = 0;
 	unsigned i;
 
@@ -92,8 +91,6 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
 		if (!pfb->cbufs[i])
 			continue;
 
-		mrt_comp[i] = 0xf;
-
 		struct pipe_surface *psurf = pfb->cbufs[i];
 		enum pipe_format pformat = psurf->format;
 		rsc = fd_resource(psurf->texture);
@@ -142,26 +139,6 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
 	OUT_REG(ring, A6XX_RB_SRGB_CNTL(.dword = srgb_cntl));
 	OUT_REG(ring, A6XX_SP_SRGB_CNTL(.dword = srgb_cntl));
 
-	OUT_REG(ring, A6XX_RB_RENDER_COMPONENTS(
-		.rt0 = mrt_comp[0],
-		.rt1 = mrt_comp[1],
-		.rt2 = mrt_comp[2],
-		.rt3 = mrt_comp[3],
-		.rt4 = mrt_comp[4],
-		.rt5 = mrt_comp[5],
-		.rt6 = mrt_comp[6],
-		.rt7 = mrt_comp[7]));
-
-	OUT_REG(ring, A6XX_SP_FS_RENDER_COMPONENTS(
-		.rt0 = mrt_comp[0],
-		.rt1 = mrt_comp[1],
-		.rt2 = mrt_comp[2],
-		.rt3 = mrt_comp[3],
-		.rt4 = mrt_comp[4],
-		.rt5 = mrt_comp[5],
-		.rt6 = mrt_comp[6],
-		.rt7 = mrt_comp[7]));
-
 	OUT_REG(ring, A6XX_GRAS_MAX_LAYER_INDEX(max_layer_index));
 }
 
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_program.c b/src/gallium/drivers/freedreno/a6xx/fd6_program.c
index 6d7f7e45232..512a016a98d 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_program.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_program.c
@@ -483,9 +483,14 @@ setup_stateobj(struct fd_ringbuffer *ring, struct fd_context *ctx,
 	OUT_PKT4(ring, REG_A6XX_SP_MODE_CONTROL, 1);
 	OUT_RING(ring, A6XX_SP_MODE_CONTROL_CONSTANT_DEMOTION_ENABLE | 4);
 
+	bool fs_has_dual_src_color = !binning_pass &&
+		fs->shader->nir->info.fs.color_is_dual_source;
+
 	OUT_PKT4(ring, REG_A6XX_SP_FS_OUTPUT_CNTL0, 1);
 	OUT_RING(ring, A6XX_SP_FS_OUTPUT_CNTL0_DEPTH_REGID(posz_regid) |
 			 A6XX_SP_FS_OUTPUT_CNTL0_SAMPMASK_REGID(smask_regid) |
+			 COND(fs_has_dual_src_color,
+					A6XX_SP_FS_OUTPUT_CNTL0_DUAL_COLOR_IN_ENABLE) |
 			 0xfc000000);
 
 	enum a3xx_threadsize vssz;
diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c
index 705355fd373..b437f0fb853 100644
--- a/src/gallium/drivers/freedreno/freedreno_screen.c
+++ b/src/gallium/drivers/freedreno/freedreno_screen.c
@@ -437,7 +437,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
 	case PIPE_CAP_MAX_RENDER_TARGETS:
 		return screen->max_rts;
 	case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
-		return is_a3xx(screen) ? 1 : 0;
+		return (is_a3xx(screen) || is_a6xx(screen)) ? 1 : 0;
 
 	/* Queries. */
 	case PIPE_CAP_OCCLUSION_QUERY:



More information about the mesa-commit mailing list