[Mesa-dev] [PATCH v3 4/5] freedreno/a6xx: MSAA

Kristian H. Kristensen hoegsberg at gmail.com
Fri Nov 30 19:48:35 UTC 2018


From: Rob Clark <robdclark at gmail.com>

Signed-off-by: Rob Clark <robdclark at gmail.com>
---
 .../drivers/freedreno/a6xx/fd6_blend.c        |  2 +
 .../drivers/freedreno/a6xx/fd6_context.c      |  2 +
 src/gallium/drivers/freedreno/a6xx/fd6_emit.c | 12 ++++--
 src/gallium/drivers/freedreno/a6xx/fd6_gmem.c | 41 +++++++++++--------
 .../drivers/freedreno/a6xx/fd6_rasterizer.c   |  4 +-
 .../drivers/freedreno/a6xx/fd6_screen.c       | 24 +++++++++--
 .../drivers/freedreno/a6xx/fd6_texture.c      |  1 +
 .../drivers/freedreno/adreno_common.xml.h     |  1 +
 .../drivers/freedreno/freedreno_resource.c    |  9 ++++
 .../drivers/freedreno/freedreno_util.h        |  2 +
 10 files changed, 74 insertions(+), 24 deletions(-)

diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_blend.c b/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
index 185b061cd1e..f888e162cf9 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_blend.c
@@ -138,8 +138,10 @@ fd6_blend_state_create(struct pipe_context *pctx,
 	}
 
 	so->rb_blend_cntl = A6XX_RB_BLEND_CNTL_ENABLE_BLEND(mrt_blend) |
+		COND(cso->alpha_to_coverage, A6XX_RB_BLEND_CNTL_ALPHA_TO_COVERAGE) |
 		COND(cso->independent_blend_enable, A6XX_RB_BLEND_CNTL_INDEPENDENT_BLEND);
 	so->sp_blend_cntl = A6XX_SP_BLEND_CNTL_UNK8 |
+		COND(cso->alpha_to_coverage, A6XX_SP_BLEND_CNTL_ALPHA_TO_COVERAGE) |
 		COND(mrt_blend, A6XX_SP_BLEND_CNTL_ENABLED);
 
 	return so;
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_context.c b/src/gallium/drivers/freedreno/a6xx/fd6_context.c
index 3282b7d86cf..35fd03c3d99 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_context.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_context.c
@@ -104,6 +104,8 @@ fd6_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
 	if (!pctx)
 		return NULL;
 
+	util_blitter_set_texture_multisample(fd6_ctx->base.blitter, true);
+
 	/* fd_context_init overwrites delete_rasterizer_state, so set this
 	 * here. */
 	pctx->delete_rasterizer_state = fd6_rasterizer_state_delete;
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
index 70b93340e77..c4d43c22f99 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
@@ -879,14 +879,18 @@ fd6_emit_state(struct fd_ringbuffer *ring, struct fd6_emit *emit)
 			OUT_RING(ring, blend_control);
 		}
 
-		OUT_PKT4(ring, REG_A6XX_RB_BLEND_CNTL, 1);
-		OUT_RING(ring, blend->rb_blend_cntl |
-				A6XX_RB_BLEND_CNTL_SAMPLE_MASK(0xffff));
-
 		OUT_PKT4(ring, REG_A6XX_SP_BLEND_CNTL, 1);
 		OUT_RING(ring, blend->sp_blend_cntl);
 	}
 
+	if (dirty & (FD_DIRTY_BLEND | FD_DIRTY_SAMPLE_MASK)) {
+		struct fd6_blend_stateobj *blend = fd6_blend_stateobj(ctx->blend);
+
+		OUT_PKT4(ring, REG_A6XX_RB_BLEND_CNTL, 1);
+		OUT_RING(ring, blend->rb_blend_cntl |
+				A6XX_RB_BLEND_CNTL_SAMPLE_MASK(ctx->sample_mask));
+	}
+
 	if (dirty & FD_DIRTY_BLEND_COLOR) {
 		struct pipe_blend_color *bcolor = &ctx->blend_color;
 
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
index 94ad6641718..8cda7d6ddae 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_gmem.c
@@ -89,7 +89,7 @@ emit_mrt(struct fd_ringbuffer *ring, struct pipe_framebuffer_state *pfb,
 		offset = fd_resource_offset(rsc, psurf->u.tex.level,
 									psurf->u.tex.first_layer);
 
-		stride = slice->pitch * rsc->cpp;
+		stride = slice->pitch * rsc->cpp * pfb->samples;
 
 		debug_assert(psurf->u.tex.first_layer == psurf->u.tex.last_layer);
 		debug_assert((offset + slice->size0) <= fd_bo_size(rsc->bo));
@@ -414,23 +414,27 @@ emit_binning_pass(struct fd_batch *batch)
 }
 
 static void
-disable_msaa(struct fd_ringbuffer *ring)
+emit_msaa(struct fd_ringbuffer *ring, unsigned nr)
 {
-	// TODO MSAA
+	enum a3xx_msaa_samples samples = fd_msaa_samples(nr);
+
 	OUT_PKT4(ring, REG_A6XX_SP_TP_RAS_MSAA_CNTL, 2);
-	OUT_RING(ring, A6XX_SP_TP_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
-	OUT_RING(ring, A6XX_SP_TP_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
-			 A6XX_SP_TP_DEST_MSAA_CNTL_MSAA_DISABLE);
+	OUT_RING(ring, A6XX_SP_TP_RAS_MSAA_CNTL_SAMPLES(samples));
+	OUT_RING(ring, A6XX_SP_TP_DEST_MSAA_CNTL_SAMPLES(samples) |
+			 COND(samples == MSAA_ONE, A6XX_SP_TP_DEST_MSAA_CNTL_MSAA_DISABLE));
 
 	OUT_PKT4(ring, REG_A6XX_GRAS_RAS_MSAA_CNTL, 2);
-	OUT_RING(ring, A6XX_GRAS_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
-	OUT_RING(ring, A6XX_GRAS_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
-			 A6XX_GRAS_DEST_MSAA_CNTL_MSAA_DISABLE);
+	OUT_RING(ring, A6XX_GRAS_RAS_MSAA_CNTL_SAMPLES(samples));
+	OUT_RING(ring, A6XX_GRAS_DEST_MSAA_CNTL_SAMPLES(samples) |
+			 COND(samples == MSAA_ONE, A6XX_GRAS_DEST_MSAA_CNTL_MSAA_DISABLE));
 
 	OUT_PKT4(ring, REG_A6XX_RB_RAS_MSAA_CNTL, 2);
-	OUT_RING(ring, A6XX_RB_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE));
-	OUT_RING(ring, A6XX_RB_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) |
-			 A6XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE);
+	OUT_RING(ring, A6XX_RB_RAS_MSAA_CNTL_SAMPLES(samples));
+	OUT_RING(ring, A6XX_RB_DEST_MSAA_CNTL_SAMPLES(samples) |
+			 COND(samples == MSAA_ONE, A6XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE));
+
+	OUT_PKT4(ring, REG_A6XX_RB_MSAA_CNTL, 1);
+	OUT_RING(ring, A6XX_RB_MSAA_CNTL_SAMPLES(samples));
 }
 
 static void prepare_tile_setup_ib(struct fd_batch *batch);
@@ -467,8 +471,7 @@ fd6_emit_tile_init(struct fd_batch *batch)
 
 	emit_zs(ring, pfb->zsbuf, &ctx->gmem);
 	emit_mrt(ring, pfb, &ctx->gmem);
-
-	disable_msaa(ring);
+	emit_msaa(ring, pfb->samples);
 
 	if (use_hw_binning(batch)) {
 		set_bin_size(ring, gmem->bin_w, gmem->bin_h,
@@ -608,6 +611,8 @@ emit_blit(struct fd_batch *batch,
 	uint32_t stride = slice->pitch * rsc->cpp;
 	uint32_t size = slice->size0;
 	enum a3xx_color_swap swap = fd6_pipe2swap(pfmt);
+	enum a3xx_msaa_samples samples =
+			fd_msaa_samples(rsc->base.nr_samples);
 
 	// TODO: tile mode
 	// bool tiled;
@@ -617,6 +622,7 @@ emit_blit(struct fd_batch *batch,
 	OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 5);
 	OUT_RING(ring,
 			 A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) |
+			 A6XX_RB_BLIT_DST_INFO_SAMPLES(samples) |
 			 A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(format) |
 			 A6XX_RB_BLIT_DST_INFO_COLOR_SWAP(swap));
 	OUT_RELOCW(ring, rsc->bo, offset, 0, 0);  /* RB_BLIT_DST_LO/HI */
@@ -665,6 +671,7 @@ emit_clears(struct fd_batch *batch, struct fd_ringbuffer *ring)
 {
 	struct pipe_framebuffer_state *pfb = &batch->framebuffer;
 	struct fd_gmem_stateobj *gmem = &batch->ctx->gmem;
+	enum a3xx_msaa_samples samples = fd_msaa_samples(pfb->samples);
 
 	uint32_t buffers = batch->fast_cleared;
 
@@ -721,6 +728,7 @@ emit_clears(struct fd_batch *batch, struct fd_ringbuffer *ring)
 
 			OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 1);
 			OUT_RING(ring, A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) |
+				A6XX_RB_BLIT_DST_INFO_SAMPLES(samples) |
 				A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(fd6_pipe2color(pfmt)));
 
 			OUT_PKT4(ring, REG_A6XX_RB_BLIT_INFO, 1);
@@ -771,6 +779,7 @@ emit_clears(struct fd_batch *batch, struct fd_ringbuffer *ring)
 
 		OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 1);
 		OUT_RING(ring, A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) |
+			A6XX_RB_BLIT_DST_INFO_SAMPLES(samples) |
 			A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(fd6_pipe2color(pfmt)));
 
 		OUT_PKT4(ring, REG_A6XX_RB_BLIT_INFO, 1);
@@ -796,6 +805,7 @@ emit_clears(struct fd_batch *batch, struct fd_ringbuffer *ring)
 	if (has_separate_stencil && (buffers & PIPE_CLEAR_STENCIL)) {
 		OUT_PKT4(ring, REG_A6XX_RB_BLIT_DST_INFO, 1);
 		OUT_RING(ring, A6XX_RB_BLIT_DST_INFO_TILE_MODE(TILE6_LINEAR) |
+				 A6XX_RB_BLIT_DST_INFO_SAMPLES(samples) |
 				 A6XX_RB_BLIT_DST_INFO_COLOR_FORMAT(RB6_R8_UINT));
 
 		OUT_PKT4(ring, REG_A6XX_RB_BLIT_INFO, 1);
@@ -1049,8 +1059,7 @@ fd6_emit_sysmem_prep(struct fd_batch *batch)
 
 	emit_zs(ring, pfb->zsbuf, NULL);
 	emit_mrt(ring, pfb, NULL);
-
-	disable_msaa(ring);
+	emit_msaa(ring, pfb->samples);
 }
 
 static void
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_rasterizer.c b/src/gallium/drivers/freedreno/a6xx/fd6_rasterizer.c
index 26bb567f65c..a50e471c68f 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_rasterizer.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_rasterizer.c
@@ -69,7 +69,9 @@ fd6_rasterizer_state_create(struct pipe_context *pctx,
 			A6XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP(cso->offset_clamp);
 
 	so->gras_su_cntl =
-			A6XX_GRAS_SU_CNTL_LINEHALFWIDTH(cso->line_width/2.0);
+			A6XX_GRAS_SU_CNTL_LINEHALFWIDTH(cso->line_width/2.0) |
+			COND(cso->multisample, A6XX_GRAS_SU_CNTL_MSAA_ENABLE);
+
 #if 0
 	so->pc_raster_cntl =
 		A6XX_PC_RASTER_CNTL_POLYMODE_FRONT_PTYPE(fd_polygon_mode(cso->fill_front)) |
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_screen.c b/src/gallium/drivers/freedreno/a6xx/fd6_screen.c
index a191ea696ba..910a71ccc96 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_screen.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_screen.c
@@ -35,6 +35,24 @@
 
 #include "ir3/ir3_compiler.h"
 
+static bool
+valid_sample_count(unsigned sample_count)
+{
+	switch (sample_count) {
+	case 0:
+	case 1:
+	case 2:
+	case 4:
+// TODO seems 8x works, but increases lrz width or height.. but the
+// blob I have doesn't seem to expose any egl configs w/ 8x, so
+// just hide it for now and revisit later.
+//	case 8:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static boolean
 fd6_screen_is_format_supported(struct pipe_screen *pscreen,
 		enum pipe_format format,
@@ -46,7 +64,7 @@ fd6_screen_is_format_supported(struct pipe_screen *pscreen,
 	unsigned retval = 0;
 
 	if ((target >= PIPE_MAX_TEXTURE_TYPES) ||
-			(sample_count > 1)) { /* TODO add MSAA */
+			!valid_sample_count(sample_count)) {
 		DBG("not supported: format=%s, target=%d, sample_count=%d, usage=%x",
 				util_format_name(format), target, sample_count, usage);
 		return FALSE;
@@ -60,11 +78,11 @@ fd6_screen_is_format_supported(struct pipe_screen *pscreen,
 		retval |= PIPE_BIND_VERTEX_BUFFER;
 	}
 
-	if ((usage & PIPE_BIND_SAMPLER_VIEW) &&
+	if ((usage & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_SHADER_IMAGE)) &&
 			(target == PIPE_BUFFER ||
 			 util_format_get_blocksize(format) != 12) &&
 			(fd6_pipe2tex(format) != (enum a6xx_tex_fmt)~0)) {
-		retval |= PIPE_BIND_SAMPLER_VIEW;
+		retval |= usage & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_SHADER_IMAGE);
 	}
 
 	if ((usage & (PIPE_BIND_RENDER_TARGET |
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c
index 0fa20e01e67..373a7937e40 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_texture.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_texture.c
@@ -245,6 +245,7 @@ fd6_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
 
 	so->texconst0 =
 		A6XX_TEX_CONST_0_FMT(fd6_pipe2tex(format)) |
+		A6XX_TEX_CONST_0_SAMPLES(fd_msaa_samples(prsc->nr_samples)) |
 		fd6_tex_swiz(format, cso->swizzle_r, cso->swizzle_g,
 				cso->swizzle_b, cso->swizzle_a);
 
diff --git a/src/gallium/drivers/freedreno/adreno_common.xml.h b/src/gallium/drivers/freedreno/adreno_common.xml.h
index f67dae75534..69cf3faa366 100644
--- a/src/gallium/drivers/freedreno/adreno_common.xml.h
+++ b/src/gallium/drivers/freedreno/adreno_common.xml.h
@@ -161,6 +161,7 @@ enum a3xx_msaa_samples {
 	MSAA_ONE = 0,
 	MSAA_TWO = 1,
 	MSAA_FOUR = 2,
+	MSAA_EIGHT = 3,
 };
 
 enum a3xx_threadmode {
diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c
index 252fd84b456..85bbbe271f9 100644
--- a/src/gallium/drivers/freedreno/freedreno_resource.c
+++ b/src/gallium/drivers/freedreno/freedreno_resource.c
@@ -853,6 +853,15 @@ fd_resource_create(struct pipe_screen *pscreen,
 				DRM_FREEDRENO_GEM_TYPE_KMEM; /* TODO */
 		unsigned lrz_pitch  = align(DIV_ROUND_UP(tmpl->width0, 8), 64);
 		unsigned lrz_height = DIV_ROUND_UP(tmpl->height0, 8);
+
+		/* LRZ buffer is super-sampled: */
+		switch (prsc->nr_samples) {
+		case 4:
+			lrz_pitch *= 2;
+		case 2:
+			lrz_height *= 2;
+		}
+
 		unsigned size = lrz_pitch * lrz_height * 2;
 
 		size += 0x1000; /* for GRAS_LRZ_FAST_CLEAR_BUFFER */
diff --git a/src/gallium/drivers/freedreno/freedreno_util.h b/src/gallium/drivers/freedreno/freedreno_util.h
index b0ed3fa8e4f..479f255f6fc 100644
--- a/src/gallium/drivers/freedreno/freedreno_util.h
+++ b/src/gallium/drivers/freedreno/freedreno_util.h
@@ -457,9 +457,11 @@ fd_msaa_samples(unsigned samples)
 	switch (samples) {
 	default:
 		debug_assert(0);
+	case 0:
 	case 1: return MSAA_ONE;
 	case 2: return MSAA_TWO;
 	case 4: return MSAA_FOUR;
+	case 8: return MSAA_EIGHT;
 	}
 }
 
-- 
2.18.1



More information about the mesa-dev mailing list