From be01d7a905d827c3c0c222cab2430c6d4575429a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 20 Dec 2013 20:48:18 -0500 Subject: [PATCH] freedreno: prepare for hw binning Actually assign VSC_PIPE's properly, which will be needed for tiling. And introduce fd_tile for per-tile state (including the assignment of tile to VSC_PIPE). This gives us the proper pipe setup that we'll need for hw binning pass, and also cleans things up a bit by not having to pass so many parameters around. And will also make it easier to introduce different tiling patterns (since we may no longer render tiles in a simple left-to-right top-to-bottom pattern). Signed-off-by: Rob Clark --- src/gallium/drivers/freedreno/a2xx/fd2_gmem.c | 38 +++---- .../drivers/freedreno/a3xx/fd3_context.c | 4 - .../drivers/freedreno/a3xx/fd3_context.h | 7 +- src/gallium/drivers/freedreno/a3xx/fd3_gmem.c | 73 ++++++-------- .../drivers/freedreno/a3xx/fd3_program.c | 27 +---- .../drivers/freedreno/freedreno_context.c | 8 ++ .../drivers/freedreno/freedreno_context.h | 24 ++--- .../drivers/freedreno/freedreno_gmem.c | 98 +++++++++++++------ .../drivers/freedreno/freedreno_gmem.h | 22 +++++ 9 files changed, 159 insertions(+), 142 deletions(-) diff --git a/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c b/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c index 1fcb76638f3..c494bf153e0 100644 --- a/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c +++ b/src/gallium/drivers/freedreno/a2xx/fd2_gmem.c @@ -95,8 +95,7 @@ emit_gmem2mem_surf(struct fd_context *ctx, uint32_t base, } static void -fd2_emit_tile_gmem2mem(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h) +fd2_emit_tile_gmem2mem(struct fd_context *ctx, struct fd_tile *tile) { struct fd2_context *fd2_ctx = fd2_context(ctx); struct fd_ringbuffer *ring = ctx->ring; @@ -157,11 +156,11 @@ fd2_emit_tile_gmem2mem(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_RB_COPY_DEST_OFFSET)); - OUT_RING(ring, A2XX_RB_COPY_DEST_OFFSET_X(xoff) | - A2XX_RB_COPY_DEST_OFFSET_Y(yoff)); + OUT_RING(ring, A2XX_RB_COPY_DEST_OFFSET_X(tile->xoff) | + A2XX_RB_COPY_DEST_OFFSET_Y(tile->yoff)); if (ctx->resolve & (FD_BUFFER_DEPTH | FD_BUFFER_STENCIL)) - emit_gmem2mem_surf(ctx, bin_w * bin_h, pfb->zsbuf); + emit_gmem2mem_surf(ctx, tile->bin_w * tile->bin_h, pfb->zsbuf); if (ctx->resolve & FD_BUFFER_COLOR) emit_gmem2mem_surf(ctx, 0, pfb->cbufs[0]); @@ -218,12 +217,13 @@ emit_mem2gmem_surf(struct fd_context *ctx, uint32_t base, } static void -fd2_emit_tile_mem2gmem(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h) +fd2_emit_tile_mem2gmem(struct fd_context *ctx, struct fd_tile *tile) { struct fd2_context *fd2_ctx = fd2_context(ctx); struct fd_ringbuffer *ring = ctx->ring; struct pipe_framebuffer_state *pfb = &ctx->framebuffer; + unsigned bin_w = tile->bin_w; + unsigned bin_h = tile->bin_h; float x0, y0, x1, y1; fd2_emit_vertex_bufs(ring, 0x9c, (struct fd2_vertex_buf[]) { @@ -232,10 +232,10 @@ fd2_emit_tile_mem2gmem(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, }, 2); /* write texture coordinates to vertexbuf: */ - x0 = ((float)xoff) / ((float)pfb->width); - x1 = ((float)xoff + bin_w) / ((float)pfb->width); - y0 = ((float)yoff) / ((float)pfb->height); - y1 = ((float)yoff + bin_h) / ((float)pfb->height); + x0 = ((float)tile->xoff) / ((float)pfb->width); + x1 = ((float)tile->xoff + bin_w) / ((float)pfb->width); + y0 = ((float)tile->yoff) / ((float)pfb->height); + y1 = ((float)tile->yoff + bin_h) / ((float)pfb->height); OUT_PKT3(ring, CP_MEM_WRITE, 9); OUT_RELOC(ring, fd_resource(fd2_ctx->solid_vertexbuf)->bo, 0x60, 0, 0); OUT_RING(ring, fui(x0)); @@ -349,8 +349,7 @@ fd2_emit_tile_init(struct fd_context *ctx) /* before mem2gmem */ static void -fd2_emit_tile_prep(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h) +fd2_emit_tile_prep(struct fd_context *ctx, struct fd_tile *tile) { struct fd_ringbuffer *ring = ctx->ring; struct pipe_framebuffer_state *pfb = &ctx->framebuffer; @@ -364,14 +363,15 @@ fd2_emit_tile_prep(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, /* setup screen scissor for current tile (same for mem2gmem): */ OUT_PKT3(ring, CP_SET_CONSTANT, 3); OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_SCREEN_SCISSOR_TL)); - OUT_RING(ring, xy2d(0,0)); /* PA_SC_SCREEN_SCISSOR_TL */ - OUT_RING(ring, xy2d(bin_w, bin_h)); /* PA_SC_SCREEN_SCISSOR_BR */ + OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_TL_X(0) | + A2XX_PA_SC_SCREEN_SCISSOR_TL_Y(0)); + OUT_RING(ring, A2XX_PA_SC_SCREEN_SCISSOR_BR_X(tile->bin_w) | + A2XX_PA_SC_SCREEN_SCISSOR_BR_Y(tile->bin_h)); } /* before IB to rendering cmds: */ static void -fd2_emit_tile_renderprep(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h) +fd2_emit_tile_renderprep(struct fd_context *ctx, struct fd_tile *tile) { struct fd_ringbuffer *ring = ctx->ring; struct pipe_framebuffer_state *pfb = &ctx->framebuffer; @@ -387,8 +387,8 @@ fd2_emit_tile_renderprep(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, */ OUT_PKT3(ring, CP_SET_CONSTANT, 2); OUT_RING(ring, CP_REG(REG_A2XX_PA_SC_WINDOW_OFFSET)); - OUT_RING(ring, A2XX_PA_SC_WINDOW_OFFSET_X(-xoff) | - A2XX_PA_SC_WINDOW_OFFSET_Y(-yoff)); + OUT_RING(ring, A2XX_PA_SC_WINDOW_OFFSET_X(-tile->xoff) | + A2XX_PA_SC_WINDOW_OFFSET_Y(-tile->yoff)); } void diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_context.c b/src/gallium/drivers/freedreno/a3xx/fd3_context.c index 13f91e9de0c..23467193d43 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_context.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_context.c @@ -47,7 +47,6 @@ fd3_context_destroy(struct pipe_context *pctx) fd_bo_del(fd3_ctx->vs_pvt_mem); fd_bo_del(fd3_ctx->fs_pvt_mem); fd_bo_del(fd3_ctx->vsc_size_mem); - fd_bo_del(fd3_ctx->vsc_pipe_mem); pipe_resource_reference(&fd3_ctx->solid_vbuf, NULL); pipe_resource_reference(&fd3_ctx->blit_texcoord_vbuf, NULL); @@ -129,9 +128,6 @@ fd3_context_create(struct pipe_screen *pscreen, void *priv) fd3_ctx->vsc_size_mem = fd_bo_new(screen->dev, 0x1000, DRM_FREEDRENO_GEM_TYPE_KMEM); - fd3_ctx->vsc_pipe_mem = fd_bo_new(screen->dev, 0x40000, - DRM_FREEDRENO_GEM_TYPE_KMEM); - fd3_ctx->solid_vbuf = create_solid_vertexbuf(pctx); fd3_ctx->blit_texcoord_vbuf = create_blit_texcoord_vertexbuf(pctx); diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_context.h b/src/gallium/drivers/freedreno/a3xx/fd3_context.h index 3829ab52675..3599fe1bb08 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_context.h +++ b/src/gallium/drivers/freedreno/a3xx/fd3_context.h @@ -38,14 +38,11 @@ struct fd3_context { struct fd_bo *vs_pvt_mem, *fs_pvt_mem; - /* not sure how big this actually needs to be.. the blob driver - * combines it w/ the solid_vertexbuf, we could probably do the - * same to save an extra bo allocation.. + /* This only needs to be 4 * num_of_pipes bytes (ie. 32 bytes). We + * could combine it with another allocation. */ struct fd_bo *vsc_size_mem; - struct fd_bo *vsc_pipe_mem; - /* vertex buf used for clear/gmem->mem vertices, and mem->gmem * vertices: */ diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_gmem.c b/src/gallium/drivers/freedreno/a3xx/fd3_gmem.c index 7be0b6881ce..4a5a241bac9 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_gmem.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_gmem.c @@ -134,8 +134,7 @@ emit_gmem2mem_surf(struct fd_context *ctx, } static void -fd3_emit_tile_gmem2mem(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h) +fd3_emit_tile_gmem2mem(struct fd_context *ctx, struct fd_tile *tile) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_ringbuffer *ring = ctx->ring; @@ -256,21 +255,22 @@ emit_mem2gmem_surf(struct fd_context *ctx, uint32_t base, } static void -fd3_emit_tile_mem2gmem(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h) +fd3_emit_tile_mem2gmem(struct fd_context *ctx, struct fd_tile *tile) { struct fd3_context *fd3_ctx = fd3_context(ctx); struct fd_gmem_stateobj *gmem = &ctx->gmem; struct fd_ringbuffer *ring = ctx->ring; struct pipe_framebuffer_state *pfb = &ctx->framebuffer; float x0, y0, x1, y1; + unsigned bin_w = tile->bin_w; + unsigned bin_h = tile->bin_h; unsigned i; /* write texture coordinates to vertexbuf: */ - x0 = ((float)xoff) / ((float)pfb->width); - x1 = ((float)xoff + bin_w) / ((float)pfb->width); - y0 = ((float)yoff) / ((float)pfb->height); - y1 = ((float)yoff + bin_h) / ((float)pfb->height); + x0 = ((float)tile->xoff) / ((float)pfb->width); + x1 = ((float)tile->xoff + bin_w) / ((float)pfb->width); + y0 = ((float)tile->yoff) / ((float)pfb->height); + y1 = ((float)tile->yoff + bin_h) / ((float)pfb->height); OUT_PKT3(ring, CP_MEM_WRITE, 5); OUT_RELOC(ring, fd_resource(fd3_ctx->blit_texcoord_vbuf)->bo, 0, 0, 0); @@ -384,29 +384,23 @@ static void update_vsc_pipe(struct fd_context *ctx) { struct fd_ringbuffer *ring = ctx->ring; - struct fd_gmem_stateobj *gmem = &ctx->gmem; - struct fd_bo *bo = fd3_context(ctx)->vsc_pipe_mem; int i; - /* since we aren't using binning, just try to assign all bins - * to same pipe for now: - */ - OUT_PKT0(ring, REG_A3XX_VSC_PIPE(0), 3); - OUT_RING(ring, A3XX_VSC_PIPE_CONFIG_X(0) | - A3XX_VSC_PIPE_CONFIG_Y(0) | - A3XX_VSC_PIPE_CONFIG_W(gmem->nbins_x) | - A3XX_VSC_PIPE_CONFIG_H(gmem->nbins_y)); - OUT_RELOC(ring, bo, 0, 0, 0); /* VSC_PIPE[0].DATA_ADDRESS */ - OUT_RING(ring, fd_bo_size(bo) - 32); /* VSC_PIPE[0].DATA_LENGTH */ - - for (i = 1; i < 8; i++) { - OUT_PKT0(ring, REG_A3XX_VSC_PIPE(i), 3); - OUT_RING(ring, A3XX_VSC_PIPE_CONFIG_X(0) | - A3XX_VSC_PIPE_CONFIG_Y(0) | - A3XX_VSC_PIPE_CONFIG_W(0) | - A3XX_VSC_PIPE_CONFIG_H(0)); - OUT_RING(ring, 0x00000000); /* VSC_PIPE[i].DATA_ADDRESS */ - OUT_RING(ring, 0x00000000); /* VSC_PIPE[i].DATA_LENGTH */ + for (i = 0; i < 8; i++) { + struct fd_vsc_pipe *pipe = &ctx->pipe[i]; + + if (!pipe->bo) { + pipe->bo = fd_bo_new(ctx->screen->dev, 0x40000, + DRM_FREEDRENO_GEM_TYPE_KMEM); + } + + OUT_PKT0(ring, REG_A3XX_VSC_PIPE(0), 3); + OUT_RING(ring, A3XX_VSC_PIPE_CONFIG_X(pipe->x) | + A3XX_VSC_PIPE_CONFIG_Y(pipe->y) | + A3XX_VSC_PIPE_CONFIG_W(pipe->w) | + A3XX_VSC_PIPE_CONFIG_H(pipe->h)); + OUT_RELOC(ring, pipe->bo, 0, 0, 0); /* VSC_PIPE[i].DATA_ADDRESS */ + OUT_RING(ring, fd_bo_size(pipe->bo) - 32); /* VSC_PIPE[i].DATA_LENGTH */ } } @@ -465,16 +459,12 @@ fd3_emit_tile_init(struct fd_context *ctx) OUT_RING(ring, A3XX_VSC_BIN_SIZE_WIDTH(gmem->bin_w) | A3XX_VSC_BIN_SIZE_HEIGHT(gmem->bin_h)); - /* TODO we only need to do this if gmem stateobj changes.. or in - * particular if the # of bins changes.. - */ update_vsc_pipe(ctx); } /* before mem2gmem */ static void -fd3_emit_tile_prep(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h) +fd3_emit_tile_prep(struct fd_context *ctx, struct fd_tile *tile) { struct fd_ringbuffer *ring = ctx->ring; struct pipe_framebuffer_state *pfb = &ctx->framebuffer; @@ -506,17 +496,16 @@ fd3_emit_tile_prep(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, /* before IB to rendering cmds: */ static void -fd3_emit_tile_renderprep(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h) +fd3_emit_tile_renderprep(struct fd_context *ctx, struct fd_tile *tile) { struct fd_ringbuffer *ring = ctx->ring; struct fd_gmem_stateobj *gmem = &ctx->gmem; struct pipe_framebuffer_state *pfb = &ctx->framebuffer; - uint32_t x1 = xoff; - uint32_t y1 = yoff; - uint32_t x2 = xoff + bin_w - 1; - uint32_t y2 = yoff + bin_h - 1; + uint32_t x1 = tile->xoff; + uint32_t y1 = tile->yoff; + uint32_t x2 = tile->xoff + tile->bin_w - 1; + uint32_t y2 = tile->yoff + tile->bin_h - 1; OUT_PKT3(ring, CP_SET_BIN, 3); OUT_RING(ring, 0x00000000); @@ -531,8 +520,8 @@ fd3_emit_tile_renderprep(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, /* setup scissor/offset for current tile: */ OUT_PKT0(ring, REG_A3XX_RB_WINDOW_OFFSET, 1); - OUT_RING(ring, A3XX_RB_WINDOW_OFFSET_X(xoff) | - A3XX_RB_WINDOW_OFFSET_Y(yoff)); + OUT_RING(ring, A3XX_RB_WINDOW_OFFSET_X(tile->xoff) | + A3XX_RB_WINDOW_OFFSET_Y(tile->yoff)); OUT_PKT0(ring, REG_A3XX_GRAS_SC_SCREEN_SCISSOR_TL, 2); OUT_RING(ring, A3XX_GRAS_SC_SCREEN_SCISSOR_TL_X(x1) | diff --git a/src/gallium/drivers/freedreno/a3xx/fd3_program.c b/src/gallium/drivers/freedreno/a3xx/fd3_program.c index 17659af373f..c02b14cba39 100644 --- a/src/gallium/drivers/freedreno/a3xx/fd3_program.c +++ b/src/gallium/drivers/freedreno/a3xx/fd3_program.c @@ -266,17 +266,6 @@ fd3_program_emit(struct fd_ringbuffer *ring, // XXX sometimes 0, sometimes 1: A3XX_SP_SP_CTRL_REG_LOMODE(1)); - /* emit unknown sequence of perfcounter disables that the blob - * emits as part of the program state.. - */ - for (i = 0; i < 6; i++) { - OUT_PKT0(ring, REG_A3XX_SP_PERFCOUNTER0_SELECT, 1); - OUT_RING(ring, 0x00000000); /* SP_PERFCOUNTER0_SELECT */ - - OUT_PKT0(ring, REG_A3XX_SP_PERFCOUNTER4_SELECT, 1); - OUT_RING(ring, 0x00000000); /* SP_PERFCOUNTER4_SELECT */ - } - OUT_PKT0(ring, REG_A3XX_SP_VS_LENGTH_REG, 1); OUT_RING(ring, A3XX_SP_VS_LENGTH_REG_SHADERLENGTH(vp->instrlen)); @@ -329,22 +318,10 @@ fd3_program_emit(struct fd_ringbuffer *ring, OUT_RING(ring, reg); } -#if 0 - /* for some reason, when I write SP_{VS,FS}_OBJ_START_REG I get: -[ 666.663665] kgsl kgsl-3d0: |a3xx_err_callback| RBBM | AHB bus error | READ | addr=201 | ports=1:3 -[ 666.664001] kgsl kgsl-3d0: |a3xx_err_callback| ringbuffer AHB error interrupt -[ 670.680909] kgsl kgsl-3d0: |adreno_idle| spun too long waiting for RB to idle -[ 670.681062] kgsl kgsl-3d0: |kgsl-3d0| Dump Started -[ 670.681123] kgsl kgsl-3d0: POWER: FLAGS = 00000007 | ACTIVE POWERLEVEL = 00000001 -[ 670.681214] kgsl kgsl-3d0: POWER: INTERVAL TIMEOUT = 0000000A -[ 670.681367] kgsl kgsl-3d0: GRP_CLK = 325000000 -[ 670.681489] kgsl kgsl-3d0: BUS CLK = 0 - */ OUT_PKT0(ring, REG_A3XX_SP_VS_OBJ_OFFSET_REG, 2); OUT_RING(ring, A3XX_SP_VS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(0) | A3XX_SP_VS_OBJ_OFFSET_REG_SHADEROBJOFFSET(0)); OUT_RELOC(ring, vp->bo, 0, 0, 0); /* SP_VS_OBJ_START_REG */ -#endif OUT_PKT0(ring, REG_A3XX_SP_FS_LENGTH_REG, 1); OUT_RING(ring, A3XX_SP_FS_LENGTH_REG_SHADERLENGTH(fp->instrlen)); @@ -364,12 +341,10 @@ fd3_program_emit(struct fd_ringbuffer *ring, A3XX_SP_FS_CTRL_REG1_CONSTFOOTPRINT(MAX2(fsi->max_const, 0)) | A3XX_SP_FS_CTRL_REG1_HALFPRECVAROFFSET(63)); -#if 0 OUT_PKT0(ring, REG_A3XX_SP_FS_OBJ_OFFSET_REG, 2); OUT_RING(ring, A3XX_SP_FS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET(128) | - A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(128 - fp->instrlen)); + A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(0)); OUT_RELOC(ring, fp->bo, 0, 0, 0); /* SP_FS_OBJ_START_REG */ -#endif OUT_PKT0(ring, REG_A3XX_SP_FS_FLAT_SHAD_MODE_REG_0, 2); OUT_RING(ring, 0x00000000); /* SP_FS_FLAT_SHAD_MODE_REG_0 */ diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index ddb8a0b78fb..c959ccfcc89 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -117,6 +117,7 @@ void fd_context_destroy(struct pipe_context *pctx) { struct fd_context *ctx = fd_context(pctx); + unsigned i; DBG(""); @@ -130,6 +131,13 @@ fd_context_destroy(struct pipe_context *pctx) fd_ringmarker_del(ctx->draw_end); fd_ringbuffer_del(ctx->ring); + for (i = 0; i < ARRAY_SIZE(ctx->pipe); i++) { + struct fd_vsc_pipe *pipe = &ctx->pipe[i]; + if (!pipe->bo) + break; + fd_bo_del(pipe->bo); + } + FREE(ctx); } diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index d3a01fcb84b..db37f9cb8a3 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -37,6 +37,7 @@ #include "util/u_string.h" #include "freedreno_screen.h" +#include "freedreno_gmem.h" struct fd_vertex_stateobj; @@ -80,15 +81,6 @@ struct fd_vertex_stateobj { unsigned num_elements; }; -struct fd_gmem_stateobj { - struct pipe_scissor_state scissor; - uint cpp; - uint16_t minx, miny; - uint16_t bin_h, nbins_y; - uint16_t bin_w, nbins_x; - uint16_t width, height; -}; - struct fd_context { struct pipe_context base; @@ -176,6 +168,8 @@ struct fd_context { * if out of date with current maximal-scissor/cpp: */ struct fd_gmem_stateobj gmem; + struct fd_vsc_pipe pipe[8]; + struct fd_tile tile[64]; /* which state objects need to be re-emit'd: */ enum { @@ -221,14 +215,10 @@ struct fd_context { /* GMEM/tile handling fxns: */ void (*emit_tile_init)(struct fd_context *ctx); - void (*emit_tile_prep)(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h); - void (*emit_tile_mem2gmem)(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h); - void (*emit_tile_renderprep)(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h); - void (*emit_tile_gmem2mem)(struct fd_context *ctx, uint32_t xoff, uint32_t yoff, - uint32_t bin_w, uint32_t bin_h); + void (*emit_tile_prep)(struct fd_context *ctx, struct fd_tile *tile); + void (*emit_tile_mem2gmem)(struct fd_context *ctx, struct fd_tile *tile); + void (*emit_tile_renderprep)(struct fd_context *ctx, struct fd_tile *tile); + void (*emit_tile_gmem2mem)(struct fd_context *ctx, struct fd_tile *tile); /* optional, for GMEM bypass: */ void (*emit_sysmem_prep)(struct fd_context *ctx); diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.c b/src/gallium/drivers/freedreno/freedreno_gmem.c index 8455b73ccbe..68b4eb607a6 100644 --- a/src/gallium/drivers/freedreno/freedreno_gmem.c +++ b/src/gallium/drivers/freedreno/freedreno_gmem.c @@ -78,6 +78,7 @@ calculate_tiles(struct fd_context *ctx) uint32_t bin_w, bin_h; uint32_t max_width = 992; uint32_t cpp = 4; + uint32_t i, j, t, p, n, xoff, yoff; if (pfb->cbufs[0]) cpp = util_format_get_blocksize(pfb->cbufs[0]->format); @@ -129,57 +130,96 @@ calculate_tiles(struct fd_context *ctx) gmem->scissor = *scissor; gmem->cpp = cpp; - gmem->minx = minx; - gmem->miny = miny; gmem->bin_h = bin_h; gmem->bin_w = bin_w; gmem->nbins_x = nbins_x; gmem->nbins_y = nbins_y; gmem->width = width; gmem->height = height; -} -static void -render_tiles(struct fd_context *ctx) -{ - struct fd_gmem_stateobj *gmem = &ctx->gmem; - uint32_t i, yoff = gmem->miny; + /* Assign tiles and pipes: + * NOTE we currently take a rather simplistic approach of + * mapping rows of tiles to a pipe. At some point it might + * be worth playing with different strategies and seeing if + * that makes much impact on performance. + */ + t = p = n = 0; + yoff = miny; + for (i = 0; i < nbins_y; i++) { + struct fd_vsc_pipe *pipe = &ctx->pipe[p]; + uint32_t bw, bh; - ctx->emit_tile_init(ctx); + assert(p < ARRAY_SIZE(ctx->pipe)); - for (i = 0; i < gmem->nbins_y; i++) { - uint32_t j, xoff = gmem->minx; - uint32_t bh = gmem->bin_h; + xoff = minx; /* clip bin height: */ - bh = MIN2(bh, gmem->miny + gmem->height - yoff); + bh = MIN2(bin_h, miny + height - yoff); + + for (j = 0; j < nbins_x; j++) { + struct fd_tile *tile = &ctx->tile[t]; - for (j = 0; j < gmem->nbins_x; j++) { - uint32_t bw = gmem->bin_w; + assert(t < ARRAY_SIZE(ctx->tile)); /* clip bin width: */ - bw = MIN2(bw, gmem->minx + gmem->width - xoff); + bw = MIN2(bin_w, minx + width - xoff); - DBG("bin_h=%d, yoff=%d, bin_w=%d, xoff=%d", - bh, yoff, bw, xoff); + tile->n = n++; + tile->p = p; + tile->bin_w = bw; + tile->bin_h = bh; + tile->xoff = xoff; + tile->yoff = yoff; - ctx->emit_tile_prep(ctx, xoff, yoff, bw, bh); + t++; - if (ctx->restore) - ctx->emit_tile_mem2gmem(ctx, xoff, yoff, bw, bh); + xoff += bw; + } - ctx->emit_tile_renderprep(ctx, xoff, yoff, bw, bh); + /* one pipe per row: */ + pipe->x = 0; + pipe->y = i; + pipe->w = nbins_x; + pipe->h = 1; - /* emit IB to drawcmds: */ - OUT_IB(ctx->ring, ctx->draw_start, ctx->draw_end); + p++; + n = 0; - /* emit gmem2mem to transfer tile back to system memory: */ - ctx->emit_tile_gmem2mem(ctx, xoff, yoff, bw, bh); + yoff += bh; + } - xoff += bw; - } + for (; p < ARRAY_SIZE(ctx->pipe); p++) { + struct fd_vsc_pipe *pipe = &ctx->pipe[p]; + pipe->x = pipe->y = pipe->w = pipe->h = 0; + } +} - yoff += bh; +static void +render_tiles(struct fd_context *ctx) +{ + struct fd_gmem_stateobj *gmem = &ctx->gmem; + int i; + + ctx->emit_tile_init(ctx); + + for (i = 0; i < (gmem->nbins_x * gmem->nbins_y); i++) { + struct fd_tile *tile = &ctx->tile[i]; + + DBG("bin_h=%d, yoff=%d, bin_w=%d, xoff=%d", + tile->bin_h, tile->yoff, tile->bin_w, tile->xoff); + + ctx->emit_tile_prep(ctx, tile); + + if (ctx->restore) + ctx->emit_tile_mem2gmem(ctx, tile); + + ctx->emit_tile_renderprep(ctx, tile); + + /* emit IB to drawcmds: */ + OUT_IB(ctx->ring, ctx->draw_start, ctx->draw_end); + + /* emit gmem2mem to transfer tile back to system memory: */ + ctx->emit_tile_gmem2mem(ctx, tile); } } diff --git a/src/gallium/drivers/freedreno/freedreno_gmem.h b/src/gallium/drivers/freedreno/freedreno_gmem.h index 0c978a4d0a0..1082d542a91 100644 --- a/src/gallium/drivers/freedreno/freedreno_gmem.h +++ b/src/gallium/drivers/freedreno/freedreno_gmem.h @@ -31,6 +31,28 @@ #include "pipe/p_context.h" +/* per-pipe configuration for hw binning: */ +struct fd_vsc_pipe { + struct fd_bo *bo; + uint8_t x, y, w, h; /* VSC_PIPE[p].CONFIG */ +}; + +/* per-tile configuration for hw binning: */ +struct fd_tile { + uint8_t p; /* index into vsc_pipe[]s */ + uint8_t n; /* slot within pipe */ + uint16_t bin_w, bin_h; + uint16_t xoff, yoff; +}; + +struct fd_gmem_stateobj { + struct pipe_scissor_state scissor; + uint cpp; + uint16_t bin_h, nbins_y; + uint16_t bin_w, nbins_x; + uint16_t width, height; +}; + void fd_gmem_render_tiles(struct pipe_context *pctx); #endif /* FREEDRENO_GMEM_H_ */ -- 2.30.2