diff options
author | Eric Anholt <[email protected]> | 2016-09-08 12:56:11 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2016-09-14 06:25:41 +0100 |
commit | f597ac3966405934e13a9aaa18c73211b5a40c7c (patch) | |
tree | f7f09bead790e4cdd210e1ed0ca4c4b150dbe35e /src/gallium/drivers/vc4/vc4_context.c | |
parent | f473348468ae1c68e7ef8eaf29f2cc51d17fbec7 (diff) |
vc4: Implement job shuffling
Track rendering to each FBO independently and flush rendering only when
necessary. This lets us avoid the overhead of storing and loading the
frame when an application momentarily switches to rendering to some other
texture in order to continue rendering the main scene.
Improves glmark -b desktop:effect=shadow:windows=4 by 27%
Improves glmark -b
desktop:blur-radius=5:effect=blur:passes=1:separable=true:windows=4
by 17%
While I haven't tested other apps, this should help X rendering a lot, and
I've heard GLBenchmark needed it too.
Diffstat (limited to 'src/gallium/drivers/vc4/vc4_context.c')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_context.c | 101 |
1 files changed, 15 insertions, 86 deletions
diff --git a/src/gallium/drivers/vc4/vc4_context.c b/src/gallium/drivers/vc4/vc4_context.c index 37b002d5cba..3863e4432a9 100644 --- a/src/gallium/drivers/vc4/vc4_context.c +++ b/src/gallium/drivers/vc4/vc4_context.c @@ -41,38 +41,12 @@ void vc4_flush(struct pipe_context *pctx) { struct vc4_context *vc4 = vc4_context(pctx); - struct pipe_surface *cbuf = vc4->framebuffer.cbufs[0]; - struct pipe_surface *zsbuf = vc4->framebuffer.zsbuf; - struct vc4_job *job = vc4->job; - - if (cbuf && (job->resolve & PIPE_CLEAR_COLOR0)) { - if (cbuf->texture->nr_samples > 1) { - pipe_surface_reference(&job->msaa_color_write, cbuf); - } else { - pipe_surface_reference(&job->color_write, cbuf); - } - - pipe_surface_reference(&job->color_read, cbuf); - } - - if (zsbuf && (job->resolve & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) { - if (zsbuf->texture->nr_samples > 1) { - pipe_surface_reference(&job->msaa_zs_write, zsbuf); - } else { - pipe_surface_reference(&job->zs_write, zsbuf); - } - pipe_surface_reference(&job->zs_read, zsbuf); + struct hash_entry *entry; + hash_table_foreach(vc4->jobs, entry) { + struct vc4_job *job = entry->data; + vc4_job_submit(vc4, job); } - - vc4_job_submit(vc4, job); - - /* We have no hardware context saved between our draw calls, so we - * need to flag the next draw as needing all state emitted. Emitting - * all state at the start of our draws is also what ensures that we - * return to the state we need after a previous tile has finished. - */ - vc4->dirty = ~0; } static void @@ -92,64 +66,18 @@ vc4_pipe_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, } } -/** - * Flushes the current command lists if they reference the given BO. - * - * This helps avoid flushing the command buffers when unnecessary. - */ -bool -vc4_cl_references_bo(struct pipe_context *pctx, struct vc4_bo *bo, - bool include_reads) -{ - struct vc4_context *vc4 = vc4_context(pctx); - struct vc4_job *job = vc4->job; - - if (!job->needs_flush) - return false; - - /* Walk all the referenced BOs in the drawing command list to see if - * they match. - */ - if (include_reads) { - struct vc4_bo **referenced_bos = job->bo_pointers.base; - for (int i = 0; i < cl_offset(&job->bo_handles) / 4; i++) { - if (referenced_bos[i] == bo) { - return true; - } - } - } - - /* Also check for the Z/color buffers, since the references to those - * are only added immediately before submit. - */ - struct vc4_surface *csurf = vc4_surface(vc4->framebuffer.cbufs[0]); - if (csurf) { - struct vc4_resource *ctex = vc4_resource(csurf->base.texture); - if (ctex->bo == bo) { - return true; - } - } - - struct vc4_surface *zsurf = vc4_surface(vc4->framebuffer.zsbuf); - if (zsurf) { - struct vc4_resource *ztex = - vc4_resource(zsurf->base.texture); - if (ztex->bo == bo) { - return true; - } - } - - return false; -} - static void vc4_invalidate_resource(struct pipe_context *pctx, struct pipe_resource *prsc) { struct vc4_context *vc4 = vc4_context(pctx); - struct pipe_surface *zsurf = vc4->framebuffer.zsbuf; - - if (zsurf && zsurf->texture == prsc) - vc4->job->resolve &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL); + struct hash_entry *entry = _mesa_hash_table_search(vc4->write_jobs, + prsc); + if (!entry) + return; + + struct vc4_job *job = entry->data; + if (job->key.zsbuf && job->key.zsbuf->texture == prsc) + job->resolve &= ~(PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL); } static void @@ -157,6 +85,8 @@ vc4_context_destroy(struct pipe_context *pctx) { struct vc4_context *vc4 = vc4_context(pctx); + vc4_flush(pctx); + if (vc4->blitter) util_blitter_destroy(vc4->blitter); @@ -205,8 +135,7 @@ vc4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) vc4_query_init(pctx); vc4_resource_context_init(pctx); - vc4->job = rzalloc(vc4, struct vc4_job); - vc4_job_init(vc4->job); + vc4_job_init(vc4); vc4->fd = screen->fd; |