summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2018-07-23 13:56:40 -0700
committerEric Anholt <[email protected]>2018-07-26 11:02:25 -0700
commit301c32caf4c656731006409720d521f4709e60ac (patch)
treebd59f95c4c3296eac42f17f1e6c8a4a3168e4c1c
parentceecddfe77cb611fd8b788f819a1d71b7f371a0d (diff)
v3d: Rework the ordering of how we clear things.
First, figure out if we can just sneak the clear into the TLB clear, even if drawing has already happened (since we have job->load and job->clear to tell us), taking into account GFXH-1461. For any pieces we can't TLB clear, fall back to drawing a quad without flushing the scene. Fixes extra scene flushes in glmark2 due to GFXH-1461.
-rw-r--r--src/gallium/drivers/v3d/v3dx_draw.c85
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