summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/freedreno/a5xx/fd5_draw.c
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2017-06-03 13:36:25 -0400
committerRob Clark <[email protected]>2017-06-07 12:32:00 -0400
commit5b60004525876616c4719bb790108db4650b1f49 (patch)
treecc11b8987407f837a7967a8b2a4087d3a3deaed2 /src/gallium/drivers/freedreno/a5xx/fd5_draw.c
parent313f6360aa1204eea8639112d5ddce697a7aabdf (diff)
freedreno/a5xx: LRZ support
Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers/freedreno/a5xx/fd5_draw.c')
-rw-r--r--src/gallium/drivers/freedreno/a5xx/fd5_draw.c99
1 files changed, 96 insertions, 3 deletions
diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c
index bc5232a4c17..d1f1d039b69 100644
--- a/src/gallium/drivers/freedreno/a5xx/fd5_draw.c
+++ b/src/gallium/drivers/freedreno/a5xx/fd5_draw.c
@@ -128,12 +128,19 @@ fd5_draw_vbo(struct fd_context *ctx, const struct pipe_draw_info *info,
fixup_shader_state(ctx, &emit.key);
unsigned dirty = ctx->dirty;
+ const struct ir3_shader_variant *vp = fd5_emit_get_vp(&emit);
+ const struct ir3_shader_variant *fp = fd5_emit_get_fp(&emit);
/* do regular pass first, since that is more likely to fail compiling: */
- if (!(fd5_emit_get_vp(&emit) && fd5_emit_get_fp(&emit)))
+ if (!vp || !fp)
return false;
+ /* figure out whether we need to disable LRZ write for binning
+ * pass using draw pass's fp:
+ */
+ emit.no_lrz_write = fp->writes_pos || fp->has_kill;
+
emit.key.binning_pass = false;
emit.dirty = dirty;
@@ -174,6 +181,86 @@ static bool is_z32(enum pipe_format format)
}
}
+static void
+fd5_clear_lrz(struct fd_batch *batch, struct fd_resource *zsbuf, double depth)
+{
+ struct fd_ringbuffer *ring;
+ uint32_t clear = util_pack_z(PIPE_FORMAT_Z16_UNORM, depth);
+
+ // TODO mid-frame clears (ie. app doing crazy stuff)?? Maybe worth
+ // splitting both clear and lrz clear out into their own rb's. And
+ // just throw away any draws prior to clear. (Anything not fullscreen
+ // clear, just fallback to generic path that treats it as a normal
+ // draw
+
+ if (!batch->lrz_clear) {
+ batch->lrz_clear = fd_ringbuffer_new(batch->ctx->screen->pipe, 0x1000);
+ fd_ringbuffer_set_parent(batch->lrz_clear, batch->gmem);
+ }
+
+ ring = batch->lrz_clear;
+
+ OUT_WFI5(ring);
+
+ OUT_PKT4(ring, REG_A5XX_RB_CCU_CNTL, 1);
+ OUT_RING(ring, 0x10000000);
+
+ OUT_PKT4(ring, REG_A5XX_HLSQ_UPDATE_CNTL, 1);
+ OUT_RING(ring, 0x20fffff);
+
+ OUT_PKT4(ring, REG_A5XX_GRAS_SU_CNTL, 1);
+ OUT_RING(ring, A5XX_GRAS_SU_CNTL_LINEHALFWIDTH(0.0));
+
+ OUT_PKT4(ring, REG_A5XX_GRAS_CNTL, 1);
+ OUT_RING(ring, 0x00000000);
+
+ OUT_PKT4(ring, REG_A5XX_GRAS_CL_CNTL, 1);
+ OUT_RING(ring, 0x00000181);
+
+ OUT_PKT4(ring, REG_A5XX_GRAS_LRZ_CNTL, 1);
+ OUT_RING(ring, 0x00000000);
+
+ OUT_PKT4(ring, REG_A5XX_RB_MRT_BUF_INFO(0), 5);
+ OUT_RING(ring, A5XX_RB_MRT_BUF_INFO_COLOR_FORMAT(RB5_R16_UNORM) |
+ A5XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(TILE5_LINEAR) |
+ A5XX_RB_MRT_BUF_INFO_COLOR_SWAP(WZYX));
+ OUT_RING(ring, A5XX_RB_MRT_PITCH(zsbuf->lrz_pitch * 2));
+ OUT_RING(ring, A5XX_RB_MRT_ARRAY_PITCH(fd_bo_size(zsbuf->lrz)));
+ OUT_RELOCW(ring, zsbuf->lrz, 0x1000, 0, 0);
+
+ OUT_PKT4(ring, REG_A5XX_RB_RENDER_CNTL, 1);
+ OUT_RING(ring, 0x00000000);
+
+ OUT_PKT4(ring, REG_A5XX_RB_DEST_MSAA_CNTL, 1);
+ OUT_RING(ring, A5XX_RB_DEST_MSAA_CNTL_SAMPLES(MSAA_ONE));
+
+ OUT_PKT4(ring, REG_A5XX_RB_BLIT_CNTL, 1);
+ OUT_RING(ring, A5XX_RB_BLIT_CNTL_BUF(BLIT_MRT0));
+
+ OUT_PKT4(ring, REG_A5XX_RB_CLEAR_CNTL, 1);
+ OUT_RING(ring, A5XX_RB_CLEAR_CNTL_FAST_CLEAR |
+ A5XX_RB_CLEAR_CNTL_MASK(0xf));
+
+ OUT_PKT4(ring, REG_A5XX_RB_CLEAR_COLOR_DW0, 1);
+ OUT_RING(ring, clear); /* RB_CLEAR_COLOR_DW0 */
+
+ OUT_PKT4(ring, REG_A5XX_VSC_RESOLVE_CNTL, 2);
+ OUT_RING(ring, A5XX_VSC_RESOLVE_CNTL_X(zsbuf->lrz_width) |
+ A5XX_VSC_RESOLVE_CNTL_Y(zsbuf->lrz_height));
+ OUT_RING(ring, 0x00000000); // XXX UNKNOWN_0CDE
+
+ OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1);
+ OUT_RING(ring, A5XX_RB_CNTL_BYPASS);
+
+ OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_1, 2);
+ OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_1_X(0) |
+ A5XX_RB_RESOLVE_CNTL_1_Y(0));
+ OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(zsbuf->lrz_width - 1) |
+ A5XX_RB_RESOLVE_CNTL_2_Y(zsbuf->lrz_height - 1));
+
+ fd5_emit_blit(batch->ctx, ring);
+}
+
static bool
fd5_clear(struct fd_context *ctx, unsigned buffers,
const union pipe_color_union *color, double depth, unsigned stencil)
@@ -186,8 +273,6 @@ fd5_clear(struct fd_context *ctx, unsigned buffers,
is_z32(pfb->zsbuf->format))
return false;
- /* TODO handle scissor.. or fallback to slow-clear? */
-
ctx->batch->max_scissor.minx = MIN2(ctx->batch->max_scissor.minx, scissor->minx);
ctx->batch->max_scissor.miny = MIN2(ctx->batch->max_scissor.miny, scissor->miny);
ctx->batch->max_scissor.maxx = MAX2(ctx->batch->max_scissor.maxx, scissor->maxx);
@@ -283,6 +368,14 @@ fd5_clear(struct fd_context *ctx, unsigned buffers,
OUT_RING(ring, clear); /* RB_CLEAR_COLOR_DW0 */
fd5_emit_blit(ctx, ring);
+
+ if (pfb->zsbuf && (buffers & PIPE_CLEAR_DEPTH)) {
+ struct fd_resource *zsbuf = fd_resource(pfb->zsbuf->texture);
+ if (zsbuf->lrz) {
+ zsbuf->lrz_valid = true;
+ fd5_clear_lrz(ctx->batch, zsbuf, depth);
+ }
+ }
}
/* disable fast clear to not interfere w/ gmem->mem, etc.. */