diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/v3d/v3dx_draw.c | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index e64f2c314e0..6aa58ceaafe 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -622,50 +622,58 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) v3d_flush(pctx); } -/* GFXH-1461: If we were to emit a load of just depth or just stencil, then - * the clear for the other may get lost. Just fall back to drawing a quad in - * that case. +/** + * Implements gallium's clear() hook (glClear()) by drawing a pair of triangles. */ -static bool -v3d_gfxh1461_clear_workaround(struct v3d_context *v3d, - unsigned buffers, double depth, unsigned stencil) +static void +v3d_draw_clear(struct v3d_context *v3d, + unsigned buffers, + const union pipe_color_union *color, + double depth, unsigned stencil) { - unsigned zsclear = buffers & PIPE_CLEAR_DEPTHSTENCIL; - if (!zsclear || zsclear == PIPE_CLEAR_DEPTHSTENCIL) - return false; - static const union pipe_color_union dummy_color = {}; + /* The blitter util dereferences the color regardless, even though the + * gallium clear API may not pass one in when only Z/S are cleared. + */ + if (!color) + color = &dummy_color; + v3d_blitter_save(v3d); util_blitter_clear(v3d->blitter, v3d->framebuffer.width, v3d->framebuffer.height, - 1, - zsclear, - &dummy_color, depth, stencil); - return true; + util_framebuffer_get_num_layers(&v3d->framebuffer), + buffers, color, depth, stencil); } -static void -v3d_clear(struct pipe_context *pctx, unsigned buffers, - const union pipe_color_union *color, double depth, unsigned stencil) +/** + * Attempts to perform the GL clear by using the TLB's fast clear at the start + * of the frame. + */ +static unsigned +v3d_tlb_clear(struct v3d_job *job, unsigned buffers, + const union pipe_color_union *color, + double depth, unsigned stencil) { - struct v3d_context *v3d = v3d_context(pctx); - struct v3d_job *job = v3d_get_job_for_fbo(v3d); - - if (v3d_gfxh1461_clear_workaround(v3d, buffers, depth, stencil)) - buffers &= ~PIPE_CLEAR_DEPTHSTENCIL; + struct v3d_context *v3d = job->v3d; - if (!buffers) - return; + if (job->draw_calls_queued) { + /* If anything in the CL has drawn using the buffer, then the + * TLB clear we're trying to add now would happen before that + * drawing. + */ + buffers &= ~(job->load | job->store); + } - /* We can't flag new buffers for clearing once we've queued draws. We - * could avoid this by using the 3d engine to clear. + /* GFXH-1461: If we were to emit a load of just depth or just stencil, + * then the clear for the other may get lost. We need to decide now + * if it would be possible to need to emit a load of just one after + * we've set up our TLB clears. */ - if (job->draw_calls_queued) { - perf_debug("Flushing rendering to process new clear.\n"); - v3d_job_submit(v3d, job); - job = v3d_get_job_for_fbo(v3d); + unsigned zsclear = buffers & PIPE_CLEAR_DEPTHSTENCIL; + if (zsclear && zsclear != PIPE_CLEAR_DEPTHSTENCIL) { + buffers &= ~zsclear; } for (int i = 0; i < VC5_MAX_DRAW_BUFFERS; i++) { @@ -724,7 +732,7 @@ v3d_clear(struct pipe_context *pctx, unsigned buffers, rsc->initialized_buffers |= bit; } - unsigned zsclear = buffers & PIPE_CLEAR_DEPTHSTENCIL; + zsclear = buffers & PIPE_CLEAR_DEPTHSTENCIL; if (zsclear) { struct v3d_resource *rsc = v3d_resource(v3d->framebuffer.zsbuf->texture); @@ -745,6 +753,21 @@ v3d_clear(struct pipe_context *pctx, unsigned buffers, job->store |= buffers; v3d_start_draw(v3d); + + return buffers; +} + +static void +v3d_clear(struct pipe_context *pctx, unsigned buffers, + const union pipe_color_union *color, double depth, unsigned stencil) +{ + struct v3d_context *v3d = v3d_context(pctx); + struct v3d_job *job = v3d_get_job_for_fbo(v3d); + + buffers &= ~v3d_tlb_clear(job, buffers, color, depth, stencil); + + if (buffers) + v3d_draw_clear(v3d, buffers, color, depth, stencil); } static void |