vc4: Add support for drawing in MSAA.
authorEric Anholt <eric@anholt.net>
Mon, 22 Jun 2015 20:12:27 +0000 (13:12 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 8 Dec 2015 17:49:53 +0000 (09:49 -0800)
src/gallium/drivers/vc4/vc4_blit.c
src/gallium/drivers/vc4/vc4_context.c
src/gallium/drivers/vc4/vc4_context.h
src/gallium/drivers/vc4/vc4_draw.c
src/gallium/drivers/vc4/vc4_job.c
src/gallium/drivers/vc4/vc4_state.c

index 757583c3ff72b48704cfe51817d02887144dea54..16dcece1ea186a0f700a1a90383dbc5000839dee 100644 (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;
 
index c783e7b2e5a703046bc7d17b8d1641abe0c9d660..1cd167600b9980e8649da062f9bd2c701cf89625 100644 (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);
index 86f2ce5e608cd3e97e9b68017985c92bdbb4373d..aa973bddcdaabe91d2b74e7c35b911684bc52c5c 100644 (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;
index 624a236c5733ed501aa9dd4dd8ab7cbc31aa3cc4..c00855698b87ad87d66634c2dc759644862306f3 100644 (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);
 }
index cde24dc074cfa72cef466ffe7f10106a03450e54..79bf2c49eec7f7544e71a35d78e75f72ecff3746 100644 (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) {
index 2a88188a959a7fc3dd51aff1abf3aa1fcbb1e71d..d9c0f55b23db3dcbf85760ef955caf4f51e2cb01 100644 (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;
 }