summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2017-10-25 12:29:51 -0700
committerEric Anholt <[email protected]>2017-10-30 13:31:27 -0700
commit0ec4b4178f5df2353e97eb6e414040a46bfc728d (patch)
tree0a0e33f6182af345ce3ef9d4875fe0d2b08a630a /src
parent464f1fb73301709cdb33600a7230db59427d1870 (diff)
broadcom/vc5: Emit raw loads for MSAA buffers.
Similar to stores, but we also need to emit dummy stores in between each load, to flush out the previous queued load.
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/vc5/vc5_rcl.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/gallium/drivers/vc5/vc5_rcl.c b/src/gallium/drivers/vc5/vc5_rcl.c
index e5763ac0ea8..01a76e77767 100644
--- a/src/gallium/drivers/vc5/vc5_rcl.c
+++ b/src/gallium/drivers/vc5/vc5_rcl.c
@@ -27,6 +27,25 @@
#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.
*/