diff options
Diffstat (limited to 'src/gallium/drivers/freedreno/a5xx/fd5_gmem.c')
-rw-r--r-- | src/gallium/drivers/freedreno/a5xx/fd5_gmem.c | 151 |
1 files changed, 143 insertions, 8 deletions
diff --git a/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c b/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c index b80a04fd2d2..1a451811451 100644 --- a/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c +++ b/src/gallium/drivers/freedreno/a5xx/fd5_gmem.c @@ -207,6 +207,15 @@ emit_zs(struct fd_ringbuffer *ring, struct pipe_surface *zsbuf, } } +static bool +use_hw_binning(struct fd_batch *batch) +{ + struct fd_gmem_stateobj *gmem = &batch->ctx->gmem; + + return fd_binning_enabled && ((gmem->nbins_x * gmem->nbins_y) > 2) && + (batch->num_draws > 0); +} + static void patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode) { @@ -218,6 +227,113 @@ patch_draws(struct fd_batch *batch, enum pc_di_vis_cull_mode vismode) util_dynarray_resize(&batch->draw_patches, 0); } +static void +update_vsc_pipe(struct fd_batch *batch) +{ + struct fd_context *ctx = batch->ctx; + struct fd5_context *fd5_ctx = fd5_context(ctx); + struct fd_gmem_stateobj *gmem = &batch->ctx->gmem; + struct fd_ringbuffer *ring = batch->gmem; + int i; + + OUT_PKT4(ring, REG_A5XX_VSC_BIN_SIZE, 3); + OUT_RING(ring, A5XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) | + A5XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h)); + OUT_RELOCW(ring, fd5_ctx->vsc_size_mem, 0, 0, 0); /* VSC_SIZE_ADDRESS_LO/HI */ + + OUT_PKT4(ring, REG_A5XX_UNKNOWN_0BC5, 2); + OUT_RING(ring, 0x00000000); /* UNKNOWN_0BC5 */ + OUT_RING(ring, 0x00000000); /* UNKNOWN_0BC6 */ + + OUT_PKT4(ring, REG_A5XX_VSC_PIPE_CONFIG_REG(0), 16); + for (i = 0; i < 16; i++) { + struct fd_vsc_pipe *pipe = &ctx->pipe[i]; + OUT_RING(ring, A5XX_VSC_PIPE_CONFIG_REG_X(pipe->x) | + A5XX_VSC_PIPE_CONFIG_REG_Y(pipe->y) | + A5XX_VSC_PIPE_CONFIG_REG_W(pipe->w) | + A5XX_VSC_PIPE_CONFIG_REG_H(pipe->h)); + } + + OUT_PKT4(ring, REG_A5XX_VSC_PIPE_DATA_ADDRESS_LO(0), 32); + for (i = 0; i < 16; i++) { + struct fd_vsc_pipe *pipe = &ctx->pipe[i]; + if (!pipe->bo) { + pipe->bo = fd_bo_new(ctx->dev, 0x20000, + DRM_FREEDRENO_GEM_TYPE_KMEM); + } + OUT_RELOCW(ring, pipe->bo, 0, 0, 0); /* VSC_PIPE_DATA_ADDRESS[i].LO/HI */ + } + + OUT_PKT4(ring, REG_A5XX_VSC_PIPE_DATA_LENGTH_REG(0), 16); + for (i = 0; i < 16; i++) { + struct fd_vsc_pipe *pipe = &ctx->pipe[i]; + OUT_RING(ring, fd_bo_size(pipe->bo) - 32); /* VSC_PIPE_DATA_LENGTH[i] */ + } +} + +static void +emit_binning_pass(struct fd_batch *batch) +{ + struct fd_context *ctx = batch->ctx; + struct fd_ringbuffer *ring = batch->gmem; + struct fd_gmem_stateobj *gmem = &batch->ctx->gmem; + + uint32_t x1 = gmem->minx; + uint32_t y1 = gmem->miny; + uint32_t x2 = gmem->minx + gmem->width - 1; + uint32_t y2 = gmem->miny + gmem->height - 1; + + fd5_set_render_mode(batch->ctx, ring, BINNING); + + OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1); + OUT_RING(ring, A5XX_RB_CNTL_WIDTH(gmem->bin_w) | + A5XX_RB_CNTL_HEIGHT(gmem->bin_h)); + + OUT_PKT4(ring, REG_A5XX_GRAS_SC_WINDOW_SCISSOR_TL, 2); + OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_TL_X(x1) | + A5XX_GRAS_SC_WINDOW_SCISSOR_TL_Y(y1)); + OUT_RING(ring, A5XX_GRAS_SC_WINDOW_SCISSOR_BR_X(x2) | + A5XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(y2)); + + OUT_PKT4(ring, REG_A5XX_RB_RESOLVE_CNTL_1, 2); + OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_1_X(x1) | + A5XX_RB_RESOLVE_CNTL_1_Y(y1)); + OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(x2) | + A5XX_RB_RESOLVE_CNTL_2_Y(y2)); + + update_vsc_pipe(batch); + + OUT_PKT4(ring, REG_A5XX_VPC_MODE_CNTL, 1); + OUT_RING(ring, A5XX_VPC_MODE_CNTL_BINNING_PASS); + + OUT_PKT7(ring, CP_EVENT_WRITE, 1); + OUT_RING(ring, UNK_2C); + + OUT_PKT4(ring, REG_A5XX_RB_WINDOW_OFFSET, 1); + OUT_RING(ring, A5XX_RB_WINDOW_OFFSET_X(0) | + A5XX_RB_WINDOW_OFFSET_Y(0)); + + /* emit IB to binning drawcmds: */ + ctx->emit_ib(ring, batch->binning); + + fd_reset_wfi(batch); + + OUT_PKT7(ring, CP_EVENT_WRITE, 1); + OUT_RING(ring, UNK_2D); + + OUT_PKT7(ring, CP_EVENT_WRITE, 4); + OUT_RING(ring, CACHE_FLUSH_TS); + OUT_RELOCW(ring, fd5_context(ctx)->blit_mem, 0, 0, 0); /* ADDR_LO/HI */ + OUT_RING(ring, 0x00000000); + + // TODO CP_COND_WRITE's for all the vsc buffers (check for overflow??) + + fd_wfi(batch, ring); + + OUT_PKT4(ring, REG_A5XX_VPC_MODE_CNTL, 1); + OUT_RING(ring, 0x0); +} + /* before first tile */ static void fd5_emit_tile_init(struct fd_batch *batch) @@ -243,9 +359,12 @@ fd5_emit_tile_init(struct fd_batch *batch) OUT_PKT4(ring, REG_A5XX_RB_CCU_CNTL, 1); OUT_RING(ring, 0x7c13c080); /* RB_CCU_CNTL */ -/* -opcode: CP_PREEMPT_ENABLE_LOCAL (6a) (2 dwords) - */ + if (use_hw_binning(batch)) { + emit_binning_pass(batch); + patch_draws(batch, USE_VISIBILITY); + } else { + patch_draws(batch, IGNORE_VISIBILITY); + } fd5_set_render_mode(batch->ctx, ring, GMEM); } @@ -254,6 +373,8 @@ opcode: CP_PREEMPT_ENABLE_LOCAL (6a) (2 dwords) static void fd5_emit_tile_prep(struct fd_batch *batch, struct fd_tile *tile) { + struct fd_context *ctx = batch->ctx; + struct fd5_context *fd5_ctx = fd5_context(ctx); struct fd_ringbuffer *ring = batch->gmem; uint32_t x1 = tile->xoff; @@ -273,6 +394,25 @@ fd5_emit_tile_prep(struct fd_batch *batch, struct fd_tile *tile) OUT_RING(ring, A5XX_RB_RESOLVE_CNTL_2_X(x2) | A5XX_RB_RESOLVE_CNTL_2_Y(y2)); + if (use_hw_binning(batch)) { + struct fd_vsc_pipe *pipe = &ctx->pipe[tile->p]; + + OUT_PKT7(ring, CP_WAIT_FOR_ME, 0); + + OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1); + OUT_RING(ring, 0x0); + + OUT_PKT7(ring, CP_SET_BIN_DATA5, 5); + OUT_RING(ring, CP_SET_BIN_DATA5_0_VSC_SIZE(pipe->w * pipe->h) | + CP_SET_BIN_DATA5_0_VSC_N(tile->n)); + OUT_RELOC(ring, pipe->bo, 0, 0, 0); /* VSC_PIPE[p].DATA_ADDRESS */ + OUT_RELOC(ring, fd5_ctx->vsc_size_mem, /* VSC_SIZE_ADDRESS + (p * 4) */ + (tile->p * 4), 0, 0); + } else { + OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1); + OUT_RING(ring, 0x1); + } + OUT_PKT4(ring, REG_A5XX_RB_WINDOW_OFFSET, 1); OUT_RING(ring, A5XX_RB_WINDOW_OFFSET_X(x1) | A5XX_RB_WINDOW_OFFSET_Y(y1)); @@ -383,15 +523,10 @@ fd5_emit_tile_renderprep(struct fd_batch *batch, struct fd_tile *tile) struct fd_gmem_stateobj *gmem = &batch->ctx->gmem; struct pipe_framebuffer_state *pfb = &batch->framebuffer; - OUT_PKT7(ring, CP_SET_VISIBILITY_OVERRIDE, 1); - OUT_RING(ring, 0x1); - OUT_PKT4(ring, REG_A5XX_RB_CNTL, 1); OUT_RING(ring, A5XX_RB_CNTL_WIDTH(gmem->bin_w) | A5XX_RB_CNTL_HEIGHT(gmem->bin_h)); - patch_draws(batch, IGNORE_VISIBILITY); - emit_zs(ring, pfb->zsbuf, gmem); emit_mrt(ring, pfb->nr_cbufs, pfb->cbufs, gmem); |