diff options
Diffstat (limited to 'src/gallium/drivers/freedreno/a5xx/fd5_draw.c')
-rw-r--r-- | src/gallium/drivers/freedreno/a5xx/fd5_draw.c | 99 |
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.. */ |