From cf0c7258ee0524709ab6d05a9aafc7415361bd23 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 15 Jun 2018 16:32:42 -0400 Subject: freedreno/a5xx: MSAA Signed-off-by: Rob Clark --- src/gallium/drivers/freedreno/a5xx/fd5_blend.c | 2 ++ src/gallium/drivers/freedreno/a5xx/fd5_context.c | 2 ++ src/gallium/drivers/freedreno/a5xx/fd5_draw.c | 5 ++-- src/gallium/drivers/freedreno/a5xx/fd5_emit.c | 17 +++++++----- src/gallium/drivers/freedreno/a5xx/fd5_gmem.c | 31 +++++++++++++--------- src/gallium/drivers/freedreno/a5xx/fd5_screen.c | 20 +++++++++++--- src/gallium/drivers/freedreno/a5xx/fd5_texture.c | 1 + src/gallium/drivers/freedreno/freedreno_batch.h | 1 - src/gallium/drivers/freedreno/freedreno_draw.c | 3 --- src/gallium/drivers/freedreno/freedreno_gmem.c | 10 ++++--- src/gallium/drivers/freedreno/freedreno_resource.c | 13 +++------ src/gallium/drivers/freedreno/freedreno_screen.c | 8 ++++-- src/gallium/drivers/freedreno/freedreno_state.c | 2 ++ src/gallium/drivers/freedreno/freedreno_util.h | 16 +++++++++++ 14 files changed, 89 insertions(+), 42 deletions(-) diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_blend.c b/src/gallium/drivers/freedreno/a5xx/fd5_blend.c index 98b6d4498e5..fee6ba346b7 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_blend.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_blend.c @@ -140,8 +140,10 @@ fd5_blend_state_create(struct pipe_context *pctx, } so->rb_blend_cntl = A5XX_RB_BLEND_CNTL_ENABLE_BLEND(mrt_blend) | + COND(cso->alpha_to_coverage, A5XX_RB_BLEND_CNTL_ALPHA_TO_COVERAGE) | COND(cso->independent_blend_enable, A5XX_RB_BLEND_CNTL_INDEPENDENT_BLEND); so->sp_blend_cntl = A5XX_SP_BLEND_CNTL_UNK8 | + COND(cso->alpha_to_coverage, A5XX_SP_BLEND_CNTL_ALPHA_TO_COVERAGE) | COND(mrt_blend, A5XX_SP_BLEND_CNTL_ENABLED); return so; diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_context.c b/src/gallium/drivers/freedreno/a5xx/fd5_context.c index 426a8e0b046..c43a8ad2eca 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_context.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_context.c @@ -101,6 +101,8 @@ fd5_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) if (!pctx) return NULL; + util_blitter_set_texture_multisample(fd5_ctx->base.blitter, true); + fd5_ctx->vs_pvt_mem = fd_bo_new(screen->dev, 0x2000, DRM_FREEDRENO_GEM_TYPE_KMEM); diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c index 8c3be5eabc8..56525e0a9a4 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c @@ -106,8 +106,6 @@ fd5_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info, .vclamp_color = ctx->rasterizer->clamp_vertex_color, .fclamp_color = ctx->rasterizer->clamp_fragment_color, .rasterflat = ctx->rasterizer->flatshade, - .half_precision = ctx->in_blit && - fd_half_precision(&ctx->batch->framebuffer), .ucp_enables = ctx->rasterizer->clip_plane_enable, .has_per_samp = (fd5_ctx->fsaturate || fd5_ctx->vsaturate || fd5_ctx->fastc_srgb || fd5_ctx->vastc_srgb), @@ -209,7 +207,8 @@ fd5_clear_lrz(struct fd_batch *batch, struct fd_resource *zsbuf, double depth) OUT_RING(ring, 0x20fffff); OUT_PKT4(ring, REG_A5XX_GRAS_SU_CNTL, 1); - OUT_RING(ring, A5XX_GRAS_SU_CNTL_LINEHALFWIDTH(0.0)); + OUT_RING(ring, A5XX_GRAS_SU_CNTL_LINEHALFWIDTH(0.0) | + COND(zsbuf->base.nr_samples > 1, A5XX_GRAS_SU_CNTL_MSAA_ENABLE)); OUT_PKT4(ring, REG_A5XX_GRAS_CNTL, 1); OUT_RING(ring, 0x00000000); diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c index 9d17bda476c..d891e68aabc 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_emit.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_emit.c @@ -641,7 +641,8 @@ fd5_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, fd5_rasterizer_stateobj(ctx->rasterizer); OUT_PKT4(ring, REG_A5XX_GRAS_SU_CNTL, 1); - OUT_RING(ring, rasterizer->gras_su_cntl); + OUT_RING(ring, rasterizer->gras_su_cntl | + COND(pfb->samples > 1, A5XX_GRAS_SU_CNTL_MSAA_ENABLE)); OUT_PKT4(ring, REG_A5XX_GRAS_SU_POINT_MINMAX, 2); OUT_RING(ring, rasterizer->gras_su_point_minmax); @@ -734,7 +735,7 @@ fd5_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, } } - if ((dirty & FD_DIRTY_BLEND)) { + if (dirty & FD_DIRTY_BLEND) { struct fd5_blend_stateobj *blend = fd5_blend_stateobj(ctx->blend); uint32_t i; @@ -764,14 +765,18 @@ fd5_emit_state(struct fd_context *ctx, struct fd_ringbuffer *ring, OUT_RING(ring, blend_control); } - OUT_PKT4(ring, REG_A5XX_RB_BLEND_CNTL, 1); - OUT_RING(ring, blend->rb_blend_cntl | - A5XX_RB_BLEND_CNTL_SAMPLE_MASK(0xffff)); - OUT_PKT4(ring, REG_A5XX_SP_BLEND_CNTL, 1); OUT_RING(ring, blend->sp_blend_cntl); } + if (dirty & (FD_DIRTY_BLEND | FD_DIRTY_SAMPLE_MASK)) { + struct fd5_blend_stateobj *blend = fd5_blend_stateobj(ctx->blend); + + OUT_PKT4(ring, REG_A5XX_RB_BLEND_CNTL, 1); + OUT_RING(ring, blend->rb_blend_cntl | + A5XX_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/a5xx/fd5_gmem.c b/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c index 1dacef067b3..4a883eefd5c 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c @@ -85,7 +85,7 @@ emit_mrt(struct fd_ringbuffer *ring, unsigned nr_bufs, psurf->u.tex.first_layer); if (gmem) { - stride = gmem->bin_w * rsc->cpp; + stride = gmem->bin_w * gmem->cbuf_cpp[i]; size = stride * gmem->bin_h; base = gmem->cbuf_base[i]; } else { @@ -580,21 +580,23 @@ fd5_emit_tile_renderprep(struct fd_batch *batch, struct fd_tile *tile) emit_zs(ring, pfb->zsbuf, gmem); emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem); - // TODO MSAA + enum a3xx_msaa_samples samples = fd_msaa_samples(pfb->samples); + OUT_PKT4(ring, REG_A5XX_TPL1_TP_RAS_MSAA_CNTL, 2); - OUT_RING(ring, A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE)); - OUT_RING(ring, A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) | - A5XX_TPL1_TP_DEST_MSAA_CNTL_MSAA_DISABLE); + OUT_RING(ring, A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES(samples)); + OUT_RING(ring, A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES(samples) | + COND(samples == MSAA_ONE, A5XX_TPL1_TP_DEST_MSAA_CNTL_MSAA_DISABLE)); OUT_PKT4(ring, REG_A5XX_RB_RAS_MSAA_CNTL, 2); - OUT_RING(ring, A5XX_RB_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE)); - OUT_RING(ring, A5XX_RB_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) | - A5XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE); + OUT_RING(ring, A5XX_RB_RAS_MSAA_CNTL_SAMPLES(samples)); + OUT_RING(ring, A5XX_RB_DEST_MSAA_CNTL_SAMPLES(samples) | + COND(samples == MSAA_ONE, A5XX_RB_DEST_MSAA_CNTL_MSAA_DISABLE)); + OUT_PKT4(ring, REG_A5XX_GRAS_SC_RAS_MSAA_CNTL, 2); - OUT_RING(ring, A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE)); - OUT_RING(ring, A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) | - A5XX_GRAS_SC_DEST_MSAA_CNTL_MSAA_DISABLE); + OUT_RING(ring, A5XX_GRAS_SC_RAS_MSAA_CNTL_SAMPLES(samples)); + OUT_RING(ring, A5XX_GRAS_SC_DEST_MSAA_CNTL_SAMPLES(samples) | + COND(samples == MSAA_ONE, A5XX_GRAS_SC_DEST_MSAA_CNTL_MSAA_DISABLE)); } @@ -640,6 +642,12 @@ emit_gmem2mem_surf(struct fd_batch *batch, uint32_t base, OUT_PKT4(ring, REG_A5XX_RB_BLIT_CNTL, 1); OUT_RING(ring, A5XX_RB_BLIT_CNTL_BUF(buf)); + struct pipe_framebuffer_state *pfb = &batch->framebuffer; +// bool msaa_resolve = pfb->samples > 1; + bool msaa_resolve = false; + OUT_PKT4(ring, REG_A5XX_RB_CLEAR_CNTL, 1); + OUT_RING(ring, COND(msaa_resolve, A5XX_RB_CLEAR_CNTL_MSAA_RESOLVE)); + fd5_emit_blit(batch->ctx, ring); } @@ -742,7 +750,6 @@ fd5_emit_sysmem_prep(struct fd_batch *batch) emit_zs(ring, pfb->zsbuf, NULL); emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, NULL); - // TODO MSAA OUT_PKT4(ring, REG_A5XX_TPL1_TP_RAS_MSAA_CNTL, 2); OUT_RING(ring, A5XX_TPL1_TP_RAS_MSAA_CNTL_SAMPLES(MSAA_ONE)); OUT_RING(ring, A5XX_TPL1_TP_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE) | diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_screen.c b/src/gallium/drivers/freedreno/a5xx/fd5_screen.c index 7d7e76e869c..6f614751f46 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_screen.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_screen.c @@ -35,6 +35,20 @@ #include "ir3_compiler.h" +static bool +valid_sample_count(unsigned sample_count) +{ + switch (sample_count) { + case 0: + case 1: + case 2: + case 4: + return true; + default: + return false; + } +} + static boolean fd5_screen_is_format_supported(struct pipe_screen *pscreen, enum pipe_format format, @@ -45,7 +59,7 @@ fd5_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) || !util_format_is_supported(format, usage)) { DBG("not supported: format=%s, target=%d, sample_count=%d, usage=%x", util_format_name(format), target, sample_count, usage); @@ -57,11 +71,11 @@ fd5_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) && (fd5_pipe2tex(format) != (enum a5xx_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/a5xx/fd5_texture.c b/src/gallium/drivers/freedreno/a5xx/fd5_texture.c index 9795189b6ef..e8e29d0367a 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_texture.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_texture.c @@ -217,6 +217,7 @@ fd5_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc, so->texconst0 = A5XX_TEX_CONST_0_FMT(fd5_pipe2tex(format)) | + A5XX_TEX_CONST_0_SAMPLES(fd_msaa_samples(prsc->nr_samples)) | fd5_tex_swiz(format, cso->swizzle_r, cso->swizzle_g, cso->swizzle_b, cso->swizzle_a); diff --git a/src/gallium/drivers/freedreno/freedreno_batch.h b/src/gallium/drivers/freedreno/freedreno_batch.h index 56665b70390..b113c071360 100644 --- a/src/gallium/drivers/freedreno/freedreno_batch.h +++ b/src/gallium/drivers/freedreno/freedreno_batch.h @@ -115,7 +115,6 @@ struct fd_batch { FD_GMEM_DEPTH_ENABLED = 0x02, FD_GMEM_STENCIL_ENABLED = 0x04, - FD_GMEM_MSAA_ENABLED = 0x08, FD_GMEM_BLEND_ENABLED = 0x10, FD_GMEM_LOGICOP_ENABLED = 0x20, } gmem_reason; diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index eb36a930751..3bcda342fb8 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -170,9 +170,6 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) buffers |= PIPE_CLEAR_COLOR0 << i; - if (surf->nr_samples > 1) - batch->gmem_reason |= FD_GMEM_MSAA_ENABLED; - if (fd_blend_enabled(ctx, i)) batch->gmem_reason |= FD_GMEM_BLEND_ENABLED; } diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.c b/src/gallium/drivers/freedreno/freedreno_gmem.c index 37a2f33365d..1cd254b3629 100644 --- a/src/gallium/drivers/freedreno/freedreno_gmem.c +++ b/src/gallium/drivers/freedreno/freedreno_gmem.c @@ -135,6 +135,8 @@ calculate_tiles(struct fd_batch *batch) cbuf_cpp[i] = util_format_get_blocksize(pfb->cbufs[i]->format); else cbuf_cpp[i] = 4; + /* if MSAA, color buffers are super-sampled in GMEM: */ + cbuf_cpp[i] *= pfb->samples; } if (!memcmp(gmem->zsbuf_cpp, zsbuf_cpp, sizeof(zsbuf_cpp)) && @@ -393,9 +395,11 @@ fd_gmem_render_tiles(struct fd_batch *batch) if (ctx->emit_sysmem_prep && !batch->nondraw) { if (batch->cleared || batch->gmem_reason || - ((batch->num_draws > 5) && !batch->blit)) { - DBG("GMEM: cleared=%x, gmem_reason=%x, num_draws=%u", - batch->cleared, batch->gmem_reason, batch->num_draws); + ((batch->num_draws > 5) && !batch->blit) || + (pfb->samples > 1)) { + DBG("GMEM: cleared=%x, gmem_reason=%x, num_draws=%u, samples=%u", + batch->cleared, batch->gmem_reason, batch->num_draws, + pfb->samples); } else if (!(fd_mesa_debug & FD_DBG_NOBYPASS)) { sysmem = true; } diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index 7e6de8c057f..8147ff57a99 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -837,6 +837,8 @@ fd_resource_create(struct pipe_screen *pscreen, rsc->internal_format = format; rsc->cpp = util_format_get_blocksize(format); + prsc->nr_samples = MAX2(1, prsc->nr_samples); + rsc->cpp *= prsc->nr_samples; assert(rsc->cpp); @@ -919,8 +921,9 @@ fd_resource_from_handle(struct pipe_screen *pscreen, if (!rsc->bo) goto fail; + prsc->nr_samples = MAX2(1, prsc->nr_samples); rsc->internal_format = tmpl->format; - rsc->cpp = util_format_get_blocksize(tmpl->format); + rsc->cpp = prsc->nr_samples * util_format_get_blocksize(tmpl->format); slice->pitch = handle->stride / rsc->cpp; slice->offset = handle->offset; slice->size0 = handle->stride * prsc->height0; @@ -1030,14 +1033,6 @@ fd_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) struct pipe_blit_info info = *blit_info; bool discard = false; - if (info.src.resource->nr_samples > 1 && - info.dst.resource->nr_samples <= 1 && - !util_format_is_depth_or_stencil(info.src.resource->format) && - !util_format_is_pure_integer(info.src.resource->format)) { - DBG("color resolve unimplemented"); - return; - } - if (info.render_condition_enable && !fd_render_condition_check(pctx)) return; diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 4d830712165..2e842a8da7d 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -197,7 +197,6 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_TGSI_TEXCOORD: case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: - case PIPE_CAP_TEXTURE_MULTISAMPLE: case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_QUERY_MEMORY_INFO: case PIPE_CAP_PCI_GROUP: @@ -216,11 +215,16 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR: case PIPE_CAP_CONDITIONAL_RENDER: case PIPE_CAP_CONDITIONAL_RENDER_INVERTED: - case PIPE_CAP_FAKE_SW_MSAA: case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: case PIPE_CAP_CLIP_HALFZ: return is_a3xx(screen) || is_a4xx(screen) || is_a5xx(screen); + case PIPE_CAP_FAKE_SW_MSAA: + return !fd_screen_get_param(pscreen, PIPE_CAP_TEXTURE_MULTISAMPLE); + + case PIPE_CAP_TEXTURE_MULTISAMPLE: + return is_a5xx(screen); + case PIPE_CAP_DEPTH_CLIP_DISABLE: return is_a3xx(screen) || is_a4xx(screen); diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index 7f9d19aa526..88f6fb557d0 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -245,6 +245,8 @@ fd_set_framebuffer_state(struct pipe_context *pctx, util_copy_framebuffer_state(cso, framebuffer); + cso->samples = util_framebuffer_get_num_samples(cso); + ctx->dirty |= FD_DIRTY_FRAMEBUFFER; ctx->disabled_scissor.minx = 0; diff --git a/src/gallium/drivers/freedreno/freedreno_util.h b/src/gallium/drivers/freedreno/freedreno_util.h index b3511d8f15e..9645561e071 100644 --- a/src/gallium/drivers/freedreno/freedreno_util.h +++ b/src/gallium/drivers/freedreno/freedreno_util.h @@ -430,6 +430,22 @@ pack_rgba(enum pipe_format format, const float *rgba) #define BIT(bit) (1u << bit) +/* + * a3xx+ helpers: + */ + +static inline enum a3xx_msaa_samples +fd_msaa_samples(unsigned samples) +{ + switch (samples) { + default: + debug_assert(0); + case 1: return MSAA_ONE; + case 2: return MSAA_TWO; + case 4: return MSAA_FOUR; + } +} + /* * a4xx+ helpers: */ -- cgit v1.2.3