vc4: Add support for drawing in MSAA.

This commit is contained in:
Eric Anholt 2015-06-22 13:12:27 -07:00
parent e7c8ad0a6c
commit edfd4d853a
6 changed files with 148 additions and 50 deletions

View File

@ -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;
@ -104,9 +109,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;
@ -114,9 +124,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);
@ -166,14 +184,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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}