From 3d13bb88511087193030f669e041cd3fe9e75360 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 22 Jun 2015 13:12:27 -0700 Subject: vc4: Add support for drawing in MSAA. (cherry picked from commit edfd4d853a0d26bc0cde811de7b20116db7e66fc) --- src/gallium/drivers/vc4/vc4_blit.c | 32 ++++++++---- src/gallium/drivers/vc4/vc4_context.c | 23 ++++++++- src/gallium/drivers/vc4/vc4_context.h | 11 ++++ src/gallium/drivers/vc4/vc4_draw.c | 16 +++--- src/gallium/drivers/vc4/vc4_job.c | 97 +++++++++++++++++++++++++---------- src/gallium/drivers/vc4/vc4_state.c | 19 +++++++ 6 files changed, 148 insertions(+), 50 deletions(-) diff --git a/src/gallium/drivers/vc4/vc4_blit.c b/src/gallium/drivers/vc4/vc4_blit.c index 11d499adc32..bdfbf435197 100644 --- a/src/gallium/drivers/vc4/vc4_blit.c +++ b/src/gallium/drivers/vc4/vc4_blit.c @@ -51,8 +51,13 @@ static bool vc4_tile_blit(struct pipe_context *pctx, const struct pipe_blit_info *info) { struct vc4_context *vc4 = vc4_context(pctx); - int tile_width = 64; - int tile_height = 64; + bool old_msaa = vc4->msaa; + int old_tile_width = vc4->tile_width; + int old_tile_height = vc4->tile_height; + bool msaa = (info->src.resource->nr_samples || + info->dst.resource->nr_samples); + int tile_width = msaa ? 32 : 64; + int tile_height = msaa ? 32 : 64; if (util_format_is_depth_or_stencil(info->dst.resource->format)) return false; @@ -94,9 +99,14 @@ vc4_tile_blit(struct pipe_context *pctx, const struct pipe_blit_info *info) vc4_get_blit_surface(pctx, info->src.resource, info->src.level); pipe_surface_reference(&vc4->color_read, src_surf); - pipe_surface_reference(&vc4->color_write, dst_surf); + pipe_surface_reference(&vc4->color_write, + dst_surf->texture->nr_samples ? NULL : dst_surf); + pipe_surface_reference(&vc4->msaa_color_write, + dst_surf->texture->nr_samples ? dst_surf : NULL); pipe_surface_reference(&vc4->zs_read, NULL); pipe_surface_reference(&vc4->zs_write, NULL); + pipe_surface_reference(&vc4->msaa_zs_write, NULL); + vc4->draw_min_x = info->dst.box.x; vc4->draw_min_y = info->dst.box.y; vc4->draw_max_x = info->dst.box.x + info->dst.box.width; @@ -104,9 +114,17 @@ vc4_tile_blit(struct pipe_context *pctx, const struct pipe_blit_info *info) vc4->draw_width = dst_surf->width; vc4->draw_height = dst_surf->height; + vc4->tile_width = tile_width; + vc4->tile_height = tile_height; + vc4->msaa = msaa; vc4->needs_flush = true; + vc4_job_submit(vc4); + vc4->msaa = old_msaa; + vc4->tile_width = old_tile_width; + vc4->tile_height = old_tile_height; + pipe_surface_reference(&dst_surf, NULL); pipe_surface_reference(&src_surf, NULL); @@ -156,14 +174,6 @@ vc4_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info) { struct pipe_blit_info info = *blit_info; - 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)) { - fprintf(stderr, "color resolve unimplemented\n"); - return; - } - if (vc4_tile_blit(pctx, blit_info)) return; diff --git a/src/gallium/drivers/vc4/vc4_context.c b/src/gallium/drivers/vc4/vc4_context.c index 4f3e2263f56..986513eb21a 100644 --- a/src/gallium/drivers/vc4/vc4_context.c +++ b/src/gallium/drivers/vc4/vc4_context.c @@ -67,8 +67,16 @@ vc4_flush(struct pipe_context *pctx) cl_u8(&bcl, VC4_PACKET_FLUSH); cl_end(&vc4->bcl, bcl); + vc4->msaa = false; if (cbuf && (vc4->resolve & PIPE_CLEAR_COLOR0)) { - pipe_surface_reference(&vc4->color_write, cbuf); + pipe_surface_reference(&vc4->color_write, + cbuf->texture->nr_samples ? NULL : cbuf); + pipe_surface_reference(&vc4->msaa_color_write, + cbuf->texture->nr_samples ? cbuf : NULL); + + if (cbuf->texture->nr_samples) + vc4->msaa = true; + if (!(vc4->cleared & PIPE_CLEAR_COLOR0)) { pipe_surface_reference(&vc4->color_read, cbuf); } else { @@ -78,11 +86,21 @@ vc4_flush(struct pipe_context *pctx) } else { pipe_surface_reference(&vc4->color_write, NULL); pipe_surface_reference(&vc4->color_read, NULL); + pipe_surface_reference(&vc4->msaa_color_write, NULL); } if (vc4->framebuffer.zsbuf && (vc4->resolve & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) { - pipe_surface_reference(&vc4->zs_write, zsbuf); + pipe_surface_reference(&vc4->zs_write, + zsbuf->texture->nr_samples ? + NULL : zsbuf); + pipe_surface_reference(&vc4->msaa_zs_write, + zsbuf->texture->nr_samples ? + zsbuf : NULL); + + if (zsbuf->texture->nr_samples) + vc4->msaa = true; + if (!(vc4->cleared & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) { pipe_surface_reference(&vc4->zs_read, zsbuf); } else { @@ -91,6 +109,7 @@ vc4_flush(struct pipe_context *pctx) } else { pipe_surface_reference(&vc4->zs_write, NULL); pipe_surface_reference(&vc4->zs_read, NULL); + pipe_surface_reference(&vc4->msaa_zs_write, NULL); } vc4_job_submit(vc4); diff --git a/src/gallium/drivers/vc4/vc4_context.h b/src/gallium/drivers/vc4/vc4_context.h index 86f2ce5e608..aa973bddcda 100644 --- a/src/gallium/drivers/vc4/vc4_context.h +++ b/src/gallium/drivers/vc4/vc4_context.h @@ -206,6 +206,8 @@ struct vc4_context { struct pipe_surface *color_write; struct pipe_surface *zs_read; struct pipe_surface *zs_write; + struct pipe_surface *msaa_color_write; + struct pipe_surface *msaa_zs_write; /** @} */ /** @{ * Bounding box of the scissor across all queued drawing. @@ -224,6 +226,15 @@ struct vc4_context { uint32_t draw_width; uint32_t draw_height; /** @} */ + /** @{ Tile information, depending on MSAA and float color buffer. */ + uint32_t draw_tiles_x; /** @< Number of tiles wide for framebuffer. */ + uint32_t draw_tiles_y; /** @< Number of tiles high for framebuffer. */ + + uint32_t tile_width; /** @< Width of a tile. */ + uint32_t tile_height; /** @< Height of a tile. */ + /** Whether the current rendering is in a 4X MSAA tile buffer. */ + bool msaa; + /** @} */ struct util_slab_mempool transfer_pool; struct blitter_context *blitter; diff --git a/src/gallium/drivers/vc4/vc4_draw.c b/src/gallium/drivers/vc4/vc4_draw.c index 624a236c573..c00855698b8 100644 --- a/src/gallium/drivers/vc4/vc4_draw.c +++ b/src/gallium/drivers/vc4/vc4_draw.c @@ -68,21 +68,17 @@ vc4_start_draw(struct vc4_context *vc4) vc4_get_draw_cl_space(vc4); - uint32_t width = vc4->framebuffer.width; - uint32_t height = vc4->framebuffer.height; - uint32_t tilew = align(width, 64) / 64; - uint32_t tileh = align(height, 64) / 64; struct vc4_cl_out *bcl = cl_start(&vc4->bcl); - // Tile state data is 48 bytes per tile, I think it can be thrown away // as soon as binning is finished. cl_u8(&bcl, VC4_PACKET_TILE_BINNING_MODE_CONFIG); cl_u32(&bcl, 0); /* tile alloc addr, filled by kernel */ cl_u32(&bcl, 0); /* tile alloc size, filled by kernel */ cl_u32(&bcl, 0); /* tile state addr, filled by kernel */ - cl_u8(&bcl, tilew); - cl_u8(&bcl, tileh); - cl_u8(&bcl, 0); /* flags, filled by kernel. */ + cl_u8(&bcl, vc4->draw_tiles_x); + cl_u8(&bcl, vc4->draw_tiles_y); + /* Other flags are filled by kernel. */ + cl_u8(&bcl, vc4->msaa ? VC4_BIN_CONFIG_MS_MODE_4X : 0); /* START_TILE_BINNING resets the statechange counters in the hardware, * which are what is used when a primitive is binned to a tile to @@ -102,8 +98,8 @@ vc4_start_draw(struct vc4_context *vc4) vc4->needs_flush = true; vc4->draw_calls_queued++; - vc4->draw_width = width; - vc4->draw_height = height; + vc4->draw_width = vc4->framebuffer.width; + vc4->draw_height = vc4->framebuffer.height; cl_end(&vc4->bcl, bcl); } diff --git a/src/gallium/drivers/vc4/vc4_job.c b/src/gallium/drivers/vc4/vc4_job.c index cde24dc074c..79bf2c49eec 100644 --- a/src/gallium/drivers/vc4/vc4_job.c +++ b/src/gallium/drivers/vc4/vc4_job.c @@ -89,22 +89,28 @@ vc4_submit_setup_rcl_surface(struct vc4_context *vc4, submit_surf->hindex = vc4_gem_hindex(vc4, rsc->bo); submit_surf->offset = surf->offset; - if (is_depth) { - submit_surf->bits = - VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_ZS, - VC4_LOADSTORE_TILE_BUFFER_BUFFER); + if (psurf->texture->nr_samples == 0) { + if (is_depth) { + submit_surf->bits = + VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_ZS, + VC4_LOADSTORE_TILE_BUFFER_BUFFER); + } else { + submit_surf->bits = + VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_COLOR, + VC4_LOADSTORE_TILE_BUFFER_BUFFER) | + VC4_SET_FIELD(vc4_rt_format_is_565(psurf->format) ? + VC4_LOADSTORE_TILE_BUFFER_BGR565 : + VC4_LOADSTORE_TILE_BUFFER_RGBA8888, + VC4_LOADSTORE_TILE_BUFFER_FORMAT); + } + submit_surf->bits |= + VC4_SET_FIELD(surf->tiling, + VC4_LOADSTORE_TILE_BUFFER_TILING); } else { - submit_surf->bits = - VC4_SET_FIELD(VC4_LOADSTORE_TILE_BUFFER_COLOR, - VC4_LOADSTORE_TILE_BUFFER_BUFFER) | - VC4_SET_FIELD(vc4_rt_format_is_565(psurf->format) ? - VC4_LOADSTORE_TILE_BUFFER_BGR565 : - VC4_LOADSTORE_TILE_BUFFER_RGBA8888, - VC4_LOADSTORE_TILE_BUFFER_FORMAT); + assert(!is_write); + submit_surf->flags |= VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES; } - submit_surf->bits |= - VC4_SET_FIELD(surf->tiling, VC4_LOADSTORE_TILE_BUFFER_TILING); if (is_write) rsc->writes++; @@ -126,16 +132,38 @@ vc4_submit_setup_rcl_render_config_surface(struct vc4_context *vc4, submit_surf->hindex = vc4_gem_hindex(vc4, rsc->bo); submit_surf->offset = surf->offset; - submit_surf->bits = - VC4_SET_FIELD(vc4_rt_format_is_565(surf->base.format) ? - VC4_RENDER_CONFIG_FORMAT_BGR565 : - VC4_RENDER_CONFIG_FORMAT_RGBA8888, - VC4_RENDER_CONFIG_FORMAT) | - VC4_SET_FIELD(surf->tiling, VC4_RENDER_CONFIG_MEMORY_FORMAT); + if (psurf->texture->nr_samples == 0) { + submit_surf->bits = + VC4_SET_FIELD(vc4_rt_format_is_565(surf->base.format) ? + VC4_RENDER_CONFIG_FORMAT_BGR565 : + VC4_RENDER_CONFIG_FORMAT_RGBA8888, + VC4_RENDER_CONFIG_FORMAT) | + VC4_SET_FIELD(surf->tiling, + VC4_RENDER_CONFIG_MEMORY_FORMAT); + } rsc->writes++; } +static void +vc4_submit_setup_rcl_msaa_surface(struct vc4_context *vc4, + struct drm_vc4_submit_rcl_surface *submit_surf, + struct pipe_surface *psurf) +{ + struct vc4_surface *surf = vc4_surface(psurf); + + if (!surf) { + submit_surf->hindex = ~0; + return; + } + + struct vc4_resource *rsc = vc4_resource(psurf->texture); + submit_surf->hindex = vc4_gem_hindex(vc4, rsc->bo); + submit_surf->offset = surf->offset; + submit_surf->bits = 0; + rsc->writes++; +} + /** * Submits the job to the kernel and then reinitializes it. */ @@ -150,8 +178,8 @@ vc4_job_submit(struct vc4_context *vc4) struct drm_vc4_submit_cl submit; memset(&submit, 0, sizeof(submit)); - cl_ensure_space(&vc4->bo_handles, 4 * sizeof(uint32_t)); - cl_ensure_space(&vc4->bo_pointers, 4 * sizeof(struct vc4_bo *)); + cl_ensure_space(&vc4->bo_handles, 6 * sizeof(uint32_t)); + cl_ensure_space(&vc4->bo_pointers, 6 * sizeof(struct vc4_bo *)); vc4_submit_setup_rcl_surface(vc4, &submit.color_read, vc4->color_read, false, false); @@ -161,8 +189,23 @@ vc4_job_submit(struct vc4_context *vc4) vc4->zs_read, true, false); vc4_submit_setup_rcl_surface(vc4, &submit.zs_write, vc4->zs_write, true, true); - submit.msaa_color_write.hindex = ~0; - submit.msaa_zs_write.hindex = ~0; + + vc4_submit_setup_rcl_msaa_surface(vc4, &submit.msaa_color_write, + vc4->msaa_color_write); + vc4_submit_setup_rcl_msaa_surface(vc4, &submit.msaa_zs_write, + vc4->msaa_zs_write); + + if (vc4->msaa) { + /* This bit controls how many pixels the general + * (i.e. subsampled) loads/stores are iterating over + * (multisample loads replicate out to the other samples). + */ + submit.color_write.bits |= VC4_RENDER_CONFIG_MS_MODE_4X; + /* Controls whether color_write's + * VC4_PACKET_STORE_MS_TILE_BUFFER does 4x decimation + */ + submit.color_write.bits |= VC4_RENDER_CONFIG_DECIMATE_MODE_4X; + } submit.bo_handles = (uintptr_t)vc4->bo_handles.base; submit.bo_handle_count = cl_offset(&vc4->bo_handles) / 4; @@ -175,10 +218,10 @@ vc4_job_submit(struct vc4_context *vc4) submit.uniforms_size = cl_offset(&vc4->uniforms); assert(vc4->draw_min_x != ~0 && vc4->draw_min_y != ~0); - submit.min_x_tile = vc4->draw_min_x / 64; - submit.min_y_tile = vc4->draw_min_y / 64; - submit.max_x_tile = (vc4->draw_max_x - 1) / 64; - submit.max_y_tile = (vc4->draw_max_y - 1) / 64; + submit.min_x_tile = vc4->draw_min_x / vc4->tile_width; + submit.min_y_tile = vc4->draw_min_y / vc4->tile_height; + submit.max_x_tile = (vc4->draw_max_x - 1) / vc4->tile_width; + submit.max_y_tile = (vc4->draw_max_y - 1) / vc4->tile_height; submit.width = vc4->draw_width; submit.height = vc4->draw_height; if (vc4->cleared) { diff --git a/src/gallium/drivers/vc4/vc4_state.c b/src/gallium/drivers/vc4/vc4_state.c index 2a88188a959..d9c0f55b23d 100644 --- a/src/gallium/drivers/vc4/vc4_state.c +++ b/src/gallium/drivers/vc4/vc4_state.c @@ -121,6 +121,9 @@ vc4_create_rasterizer_state(struct pipe_context *pctx, so->offset_factor = float_to_187_half(cso->offset_scale); } + if (cso->multisample) + so->config_bits[0] |= VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_4X; + return so; } @@ -457,6 +460,22 @@ vc4_set_framebuffer_state(struct pipe_context *pctx, rsc->cpp); } + vc4->msaa = false; + if (cso->cbufs[0]) + vc4->msaa = cso->cbufs[0]->texture->nr_samples != 0; + else if (cso->zsbuf) + vc4->msaa = cso->zsbuf->texture->nr_samples != 0; + + if (vc4->msaa) { + vc4->tile_width = 32; + vc4->tile_height = 32; + } else { + vc4->tile_width = 64; + vc4->tile_height = 64; + } + vc4->draw_tiles_x = DIV_ROUND_UP(cso->width, vc4->tile_width); + vc4->draw_tiles_y = DIV_ROUND_UP(cso->height, vc4->tile_height); + vc4->dirty |= VC4_DIRTY_FRAMEBUFFER; } -- cgit v1.2.3