From d47d77d49d59cb25656480c745977f35a0f55d70 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 19 Nov 2018 10:24:40 -0500 Subject: [PATCH] freedreno/a6xx: set guardband clip On older gens, the CLIP_ADJ bitfields were actually 3.6 fixed point. Which might make more sense. Although this formula comes up with values pretty close to what blob does for various viewport sizes (for at least a5xx and a6xx), and seems to work. Signed-off-by: Rob Clark --- src/gallium/drivers/freedreno/a6xx/fd6_emit.c | 22 +++++++++----- .../drivers/freedreno/freedreno_context.h | 1 + .../drivers/freedreno/freedreno_state.c | 29 +++++++++++++++++++ .../drivers/freedreno/freedreno_util.h | 12 ++++++++ 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c index 4697b2f6b9a..70b93340e77 100644 --- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c +++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c @@ -677,12 +677,6 @@ fd6_emit_state(struct fd_ringbuffer *ring, struct fd6_emit *emit) OUT_RING(ring, A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_X(scissor->maxx - 1) | A6XX_GRAS_SC_SCREEN_SCISSOR_TL_0_Y(scissor->maxy - 1)); - OUT_PKT4(ring, REG_A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0, 2); - OUT_RING(ring, A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(scissor->minx) | - A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(scissor->miny)); - OUT_RING(ring, A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(scissor->maxx - 1) | - A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(scissor->maxy - 1)); - 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); @@ -690,7 +684,8 @@ fd6_emit_state(struct fd_ringbuffer *ring, struct fd6_emit *emit) } if (dirty & FD_DIRTY_VIEWPORT) { - fd_wfi(ctx->batch, ring); + struct pipe_scissor_state *scissor = &ctx->viewport_scissor; + OUT_PKT4(ring, REG_A6XX_GRAS_CL_VPORT_XOFFSET_0, 6); OUT_RING(ring, A6XX_GRAS_CL_VPORT_XOFFSET_0(ctx->viewport.translate[0])); OUT_RING(ring, A6XX_GRAS_CL_VPORT_XSCALE_0(ctx->viewport.scale[0])); @@ -698,6 +693,19 @@ fd6_emit_state(struct fd_ringbuffer *ring, struct fd6_emit *emit) OUT_RING(ring, A6XX_GRAS_CL_VPORT_YSCALE_0(ctx->viewport.scale[1])); OUT_RING(ring, A6XX_GRAS_CL_VPORT_ZOFFSET_0(ctx->viewport.translate[2])); OUT_RING(ring, A6XX_GRAS_CL_VPORT_ZSCALE_0(ctx->viewport.scale[2])); + + OUT_PKT4(ring, REG_A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0, 2); + OUT_RING(ring, A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(scissor->minx) | + A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(scissor->miny)); + OUT_RING(ring, A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_X(scissor->maxx - 1) | + A6XX_GRAS_SC_VIEWPORT_SCISSOR_TL_0_Y(scissor->maxy - 1)); + + unsigned guardband_x = fd_calc_guardband(scissor->maxx - scissor->minx); + unsigned guardband_y = fd_calc_guardband(scissor->maxy - scissor->miny); + + OUT_PKT4(ring, REG_A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ, 1); + OUT_RING(ring, A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ_HORZ(guardband_x) | + A6XX_GRAS_CL_GUARDBAND_CLIP_ADJ_VERT(guardband_y)); } if (dirty & FD_DIRTY_PROG) { diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index 8914489d8be..3a03845b4ab 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -289,6 +289,7 @@ struct fd_context { struct pipe_framebuffer_state framebuffer; struct pipe_poly_stipple stipple; struct pipe_viewport_state viewport; + struct pipe_scissor_state viewport_scissor; struct fd_constbuf_stateobj constbuf[PIPE_SHADER_TYPES]; struct fd_shaderbuf_stateobj shaderbuf[PIPE_SHADER_TYPES]; struct fd_shaderimg_stateobj shaderimg[PIPE_SHADER_TYPES]; diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index 76b54a56044..1b67cc35f14 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -288,7 +288,36 @@ fd_set_viewport_states(struct pipe_context *pctx, const struct pipe_viewport_state *viewport) { struct fd_context *ctx = fd_context(pctx); + struct pipe_scissor_state *scissor = &ctx->viewport_scissor; + float minx, miny, maxx, maxy; + ctx->viewport = *viewport; + + /* see si_get_scissor_from_viewport(): */ + + /* Convert (-1, -1) and (1, 1) from clip space into window space. */ + minx = -viewport->scale[0] + viewport->translate[0]; + miny = -viewport->scale[1] + viewport->translate[1]; + maxx = viewport->scale[0] + viewport->translate[0]; + maxy = viewport->scale[1] + viewport->translate[1]; + + /* Handle inverted viewports. */ + if (minx > maxx) { + swap(minx, maxx); + } + if (miny > maxy) { + swap(miny, maxy); + } + + debug_assert(miny >= 0); + debug_assert(maxy >= 0); + + /* Convert to integer and round up the max bounds. */ + scissor->minx = minx; + scissor->miny = miny; + scissor->maxx = ceilf(maxx); + scissor->maxy = ceilf(maxy); + ctx->dirty |= FD_DIRTY_VIEWPORT; } diff --git a/src/gallium/drivers/freedreno/freedreno_util.h b/src/gallium/drivers/freedreno/freedreno_util.h index e03f37dd627..125ad83523c 100644 --- a/src/gallium/drivers/freedreno/freedreno_util.h +++ b/src/gallium/drivers/freedreno/freedreno_util.h @@ -194,6 +194,18 @@ fd_half_precision(struct pipe_framebuffer_state *pfb) return true; } +/* Note sure if this is same on all gens, but seems to be same on the later + * gen's + */ +static inline unsigned +fd_calc_guardband(unsigned x) +{ + float l = log2(x); + if (l <= 8) + return 511; + return 511 - ((l - 8) * 65); +} + #define LOG_DWORDS 0 static inline void emit_marker(struct fd_ringbuffer *ring, int scratch_idx); -- 2.30.2