freedreno: track batch/blit types
Add a bit of extra book-keeping about blits and back-blits (from resource shadowing). If the app uploads all mipmap levels, as opposed to uploading the first level and then glGenerateMipmap(), we can discard the back-blit (as opposed to being naive and shadowing the resource for each mipmap level). Also, after a normal blit, we might as well flush the batch immediately, since there is not likely to be further rendering to the surface. Signed-off-by: Rob Clark <robdclark@gmail.com>
This commit is contained in:
parent
7f8fd02dc7
commit
c44163876a
|
@ -93,7 +93,9 @@ struct fd_batch {
|
|||
FD_BUFFER_ALL = FD_BUFFER_COLOR | FD_BUFFER_DEPTH | FD_BUFFER_STENCIL,
|
||||
} cleared, partial_cleared, restore, resolve;
|
||||
|
||||
bool needs_flush;
|
||||
bool needs_flush : 1;
|
||||
bool blit : 1;
|
||||
bool back_blit : 1; /* only blit so far is resource shadowing back-blit */
|
||||
|
||||
/* To decide whether to render to system memory, keep track of the
|
||||
* number of draws, and whether any of them require multisample,
|
||||
|
|
|
@ -161,16 +161,27 @@ struct fd_context {
|
|||
*/
|
||||
struct fd_batch *batch;
|
||||
|
||||
/* Are we in process of shadowing a resource? Used to detect recursion
|
||||
* in transfer_map, and skip unneeded synchronization.
|
||||
*/
|
||||
bool in_shadow : 1;
|
||||
|
||||
/* Ie. in blit situation where we no longer care about previous framebuffer
|
||||
* contents. Main point is to eliminate blits from fd_try_shadow_resource().
|
||||
* For example, in case of texture upload + gen-mipmaps.
|
||||
*/
|
||||
bool in_blit : 1;
|
||||
|
||||
/* Keep track if WAIT_FOR_IDLE is needed for registers we need
|
||||
* to update via RMW:
|
||||
*/
|
||||
bool needs_wfi;
|
||||
bool needs_wfi : 1;
|
||||
|
||||
/* Do we need to re-emit RB_FRAME_BUFFER_DIMENSION? At least on a3xx
|
||||
* it is not a banked context register, so it needs a WFI to update.
|
||||
* Keep track if it has actually changed, to avoid unneeded WFI.
|
||||
* */
|
||||
bool needs_rb_fbd;
|
||||
bool needs_rb_fbd : 1;
|
||||
|
||||
struct pipe_scissor_state scissor;
|
||||
|
||||
|
@ -244,17 +255,6 @@ struct fd_context {
|
|||
bool cond_cond; /* inverted rendering condition */
|
||||
uint cond_mode;
|
||||
|
||||
/* Are we in process of shadowing a resource? Used to detect recursion
|
||||
* in transfer_map, and skip unneeded synchronization.
|
||||
*/
|
||||
bool in_shadow;
|
||||
|
||||
/* Ie. in blit situation where we no longer care about previous framebuffer
|
||||
* contents. Main point is to eliminate blits from fd_try_shadow_resource().
|
||||
* For example, in case of texture upload + gen-mipmaps.
|
||||
*/
|
||||
bool discard;
|
||||
|
||||
struct pipe_debug_callback debug;
|
||||
|
||||
/* GMEM/tile handling fxns: */
|
||||
|
|
|
@ -84,15 +84,19 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
|
|||
return;
|
||||
}
|
||||
|
||||
if (ctx->discard) {
|
||||
fd_batch_reset(ctx->batch);
|
||||
ctx->discard = false;
|
||||
if (ctx->in_blit) {
|
||||
fd_batch_reset(batch);
|
||||
ctx->dirty = ~0;
|
||||
}
|
||||
|
||||
batch->blit = ctx->in_blit;
|
||||
batch->back_blit = ctx->in_shadow;
|
||||
|
||||
/* NOTE: needs to be before resource_written(batch->query_buf), otherwise
|
||||
* query_buf may not be created yet.
|
||||
*/
|
||||
fd_hw_query_set_stage(batch, batch->draw, FD_STAGE_DRAW);
|
||||
|
||||
/*
|
||||
* Figure out the buffers/features we need:
|
||||
*/
|
||||
|
@ -219,9 +223,9 @@ fd_clear(struct pipe_context *pctx, unsigned buffers,
|
|||
if (!fd_render_condition_check(pctx))
|
||||
return;
|
||||
|
||||
if (ctx->discard) {
|
||||
fd_batch_reset(ctx->batch);
|
||||
ctx->discard = false;
|
||||
if (ctx->in_blit) {
|
||||
fd_batch_reset(batch);
|
||||
ctx->dirty = ~0;
|
||||
}
|
||||
|
||||
/* for bookkeeping about which buffers have been cleared (and thus
|
||||
|
|
|
@ -487,6 +487,12 @@ fd_resource_transfer_map(struct pipe_context *pctx,
|
|||
* to wait.
|
||||
*/
|
||||
} else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
|
||||
if ((usage & PIPE_TRANSFER_WRITE) && rsc->write_batch &&
|
||||
rsc->write_batch->back_blit) {
|
||||
/* if only thing pending is a back-blit, we can discard it: */
|
||||
fd_batch_reset(rsc->write_batch);
|
||||
}
|
||||
|
||||
/* If the GPU is writing to the resource, or if it is reading from the
|
||||
* resource and we're trying to write to it, flush the renders.
|
||||
*/
|
||||
|
@ -1057,7 +1063,7 @@ fd_blitter_pipe_begin(struct fd_context *ctx, bool render_cond, bool discard)
|
|||
if (ctx->batch)
|
||||
fd_hw_query_set_stage(ctx->batch, ctx->batch->draw, FD_STAGE_BLIT);
|
||||
|
||||
ctx->discard = discard;
|
||||
ctx->in_blit = discard;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1065,6 +1071,7 @@ fd_blitter_pipe_end(struct fd_context *ctx)
|
|||
{
|
||||
if (ctx->batch)
|
||||
fd_hw_query_set_stage(ctx->batch, ctx->batch->draw, FD_STAGE_NULL);
|
||||
ctx->in_blit = false;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -119,13 +119,28 @@ fd_set_framebuffer_state(struct pipe_context *pctx,
|
|||
struct pipe_framebuffer_state *cso;
|
||||
|
||||
if (ctx->screen->reorder) {
|
||||
struct fd_batch *batch;
|
||||
if (likely(ctx->batch))
|
||||
fd_hw_query_set_stage(ctx->batch, ctx->batch->draw, FD_STAGE_NULL);
|
||||
struct fd_batch *batch, *old_batch = NULL;
|
||||
|
||||
fd_batch_reference(&old_batch, ctx->batch);
|
||||
|
||||
if (likely(old_batch))
|
||||
fd_hw_query_set_stage(old_batch, old_batch->draw, FD_STAGE_NULL);
|
||||
|
||||
batch = fd_batch_from_fb(&ctx->screen->batch_cache, ctx, framebuffer);
|
||||
fd_batch_reference(&ctx->batch, NULL);
|
||||
ctx->batch = batch;
|
||||
ctx->dirty = ~0;
|
||||
|
||||
if (old_batch && old_batch->blit && !old_batch->back_blit) {
|
||||
/* for blits, there is not really much point in hanging on
|
||||
* to the uncommitted batch (ie. you probably don't blit
|
||||
* multiple times to the same surface), so we might as
|
||||
* well go ahead and flush this one:
|
||||
*/
|
||||
fd_batch_flush(old_batch);
|
||||
}
|
||||
|
||||
fd_batch_reference(&old_batch, NULL);
|
||||
} else {
|
||||
DBG("%d: cbufs[0]=%p, zsbuf=%p", ctx->batch->needs_flush,
|
||||
framebuffer->cbufs[0], framebuffer->zsbuf);
|
||||
|
|
Loading…
Reference in New Issue