summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2015-06-22 13:12:27 -0700
committerEric Anholt <[email protected]>2015-12-08 09:49:53 -0800
commitedfd4d853a0d26bc0cde811de7b20116db7e66fc (patch)
treee154c0ed3b29e39e2cedf1545fdedb7624d27caf
parente7c8ad0a6c8ba263f29b7c3c5120bc6beabeba7b (diff)
vc4: Add support for drawing in MSAA.
-rw-r--r--src/gallium/drivers/vc4/vc4_blit.c32
-rw-r--r--src/gallium/drivers/vc4/vc4_context.c23
-rw-r--r--src/gallium/drivers/vc4/vc4_context.h11
-rw-r--r--src/gallium/drivers/vc4/vc4_draw.c16
-rw-r--r--src/gallium/drivers/vc4/vc4_job.c97
-rw-r--r--src/gallium/drivers/vc4/vc4_state.c19
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 757583c3ff7..16dcece1ea1 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;
@@ -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;
diff --git a/src/gallium/drivers/vc4/vc4_context.c b/src/gallium/drivers/vc4/vc4_context.c
index c783e7b2e5a..1cd167600b9 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;
}