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++) {
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);
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