broadcom/vc5: Emit raw loads for MSAA buffers.
authorEric Anholt <eric@anholt.net>
Wed, 25 Oct 2017 19:29:51 +0000 (12:29 -0700)
committerEric Anholt <eric@anholt.net>
Mon, 30 Oct 2017 20:31:27 +0000 (13:31 -0700)
Similar to stores, but we also need to emit dummy stores in between each
load, to flush out the previous queued load.

src/gallium/drivers/vc5/vc5_rcl.c

index e5763ac..01a76e7 100644 (file)
 #include "broadcom/cle/v3d_packet_v33_pack.h"
 
 static void
+load_raw(struct vc5_cl *cl, struct pipe_surface *psurf, int buffer)
+{
+        struct vc5_surface *surf = vc5_surface(psurf);
+        struct vc5_resource *rsc = vc5_resource(psurf->texture);
+
+        cl_emit(cl, LOAD_TILE_BUFFER_GENERAL, load) {
+                load.raw_mode = true;
+                load.buffer_to_load = buffer;
+                load.address = cl_address(rsc->bo, surf->offset);
+
+                struct vc5_resource_slice *slice =
+                        &rsc->slices[psurf->u.tex.level];
+                load.padded_height_of_output_image_in_uif_blocks =
+                        (slice->size / slice->stride) /
+                        (2 * vc5_utile_height(rsc->cpp));
+        }
+}
+
+static void
 store_raw(struct vc5_cl *cl, struct pipe_surface *psurf, int buffer,
           bool color_clear, bool z_clear, bool s_clear)
 {
@@ -64,6 +83,20 @@ zs_buffer_from_pipe_bits(int pipe_clear_bits)
         }
 }
 
+/* The HW queues up the load until the tile coordinates show up, but can only
+ * track one at a time.  If we need to do more than one load, then we need to
+ * flush out the previous load by emitting the tile coordinates and doing a
+ * dummy store.
+ */
+static void
+flush_last_load(struct vc5_cl *cl)
+{
+        cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);
+        cl_emit(cl, STORE_TILE_BUFFER_GENERAL, store) {
+                store.buffer_to_store = NONE;
+        }
+}
+
 static void
 vc5_rcl_emit_generic_per_tile_list(struct vc5_job *job, int last_cbuf)
 {
@@ -82,6 +115,31 @@ vc5_rcl_emit_generic_per_tile_list(struct vc5_job *job, int last_cbuf)
 
         uint32_t read_but_not_cleared = job->resolve & ~job->cleared;
 
+        for (int i = 0; i < VC5_MAX_DRAW_BUFFERS; i++) {
+                uint32_t bit = PIPE_CLEAR_COLOR0 << i;
+                if (!(read_but_not_cleared & bit))
+                        continue;
+
+                struct pipe_surface *psurf = job->cbufs[i];
+                if (!psurf || psurf->texture->nr_samples <= 1)
+                        continue;
+
+                load_raw(cl, psurf, RENDER_TARGET_0 + i);
+                read_but_not_cleared &= ~bit;
+
+                if (read_but_not_cleared)
+                        flush_last_load(cl);
+        }
+
+        if (job->zsbuf && job->zsbuf->texture->nr_samples > 1 &&
+            read_but_not_cleared & PIPE_CLEAR_DEPTHSTENCIL) {
+                load_raw(cl, job->zsbuf,
+                         zs_buffer_from_pipe_bits(read_but_not_cleared));
+                read_but_not_cleared &= ~PIPE_CLEAR_DEPTHSTENCIL;
+                if (read_but_not_cleared)
+                        cl_emit(cl, TILE_COORDINATES_IMPLICIT, coords);
+        }
+
         /* The initial reload will be queued until we get the
          * tile coordinates.
          */