From 913eb7fa58c8208722ec71e653262fb66cfeeeab Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 29 Oct 2018 15:44:13 -0400 Subject: [PATCH] freedreno/a6xx: MSAA Reviewed-by: Kristian H. Kristensen Signed-off-by: Rob Clark --- .../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.30.2