summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/vc4/vc4_job.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/vc4/vc4_job.c')
-rw-r--r--src/gallium/drivers/vc4/vc4_job.c276
1 files changed, 245 insertions, 31 deletions
diff --git a/src/gallium/drivers/vc4/vc4_job.c b/src/gallium/drivers/vc4/vc4_job.c
index cb20853fa49..d39472ef131 100644
--- a/src/gallium/drivers/vc4/vc4_job.c
+++ b/src/gallium/drivers/vc4/vc4_job.c
@@ -28,49 +28,239 @@
#include <xf86drm.h>
#include "vc4_context.h"
+#include "util/hash_table.h"
-void
-vc4_job_init(struct vc4_job *job)
+static void
+remove_from_ht(struct hash_table *ht, void *key)
{
- vc4_init_cl(job, &job->bcl);
- vc4_init_cl(job, &job->shader_rec);
- vc4_init_cl(job, &job->uniforms);
- vc4_init_cl(job, &job->bo_handles);
- vc4_init_cl(job, &job->bo_pointers);
- vc4_job_reset(job);
+ struct hash_entry *entry = _mesa_hash_table_search(ht, key);
+ _mesa_hash_table_remove(ht, entry);
}
-void
-vc4_job_reset(struct vc4_job *job)
+static void
+vc4_job_free(struct vc4_context *vc4, struct vc4_job *job)
{
struct vc4_bo **referenced_bos = job->bo_pointers.base;
for (int i = 0; i < cl_offset(&job->bo_handles) / 4; i++) {
vc4_bo_unreference(&referenced_bos[i]);
}
- vc4_reset_cl(&job->bcl);
- vc4_reset_cl(&job->shader_rec);
- vc4_reset_cl(&job->uniforms);
- vc4_reset_cl(&job->bo_handles);
- vc4_reset_cl(&job->bo_pointers);
- job->shader_rec_count = 0;
- job->needs_flush = false;
- job->draw_calls_queued = 0;
+ remove_from_ht(vc4->jobs, &job->key);
- job->resolve = 0;
- job->cleared = 0;
+ if (job->color_write) {
+ remove_from_ht(vc4->write_jobs, job->color_write->texture);
+ pipe_surface_reference(&job->color_write, NULL);
+ }
+ if (job->msaa_color_write) {
+ remove_from_ht(vc4->write_jobs, job->msaa_color_write->texture);
+ pipe_surface_reference(&job->msaa_color_write, NULL);
+ }
+ if (job->zs_write) {
+ remove_from_ht(vc4->write_jobs, job->zs_write->texture);
+ pipe_surface_reference(&job->zs_write, NULL);
+ }
+ if (job->msaa_zs_write) {
+ remove_from_ht(vc4->write_jobs, job->msaa_zs_write->texture);
+ pipe_surface_reference(&job->msaa_zs_write, NULL);
+ }
+
+ pipe_surface_reference(&job->color_read, NULL);
+ pipe_surface_reference(&job->zs_read, NULL);
+
+ if (vc4->job == job)
+ vc4->job = NULL;
+
+ ralloc_free(job);
+}
+
+static struct vc4_job *
+vc4_job_create(struct vc4_context *vc4)
+{
+ struct vc4_job *job = rzalloc(vc4, struct vc4_job);
+
+ vc4_init_cl(job, &job->bcl);
+ vc4_init_cl(job, &job->shader_rec);
+ vc4_init_cl(job, &job->uniforms);
+ vc4_init_cl(job, &job->bo_handles);
+ vc4_init_cl(job, &job->bo_pointers);
job->draw_min_x = ~0;
job->draw_min_y = ~0;
job->draw_max_x = 0;
job->draw_max_y = 0;
- pipe_surface_reference(&job->color_write, NULL);
- pipe_surface_reference(&job->color_read, NULL);
- pipe_surface_reference(&job->msaa_color_write, NULL);
- pipe_surface_reference(&job->zs_write, NULL);
- pipe_surface_reference(&job->zs_read, NULL);
- pipe_surface_reference(&job->msaa_zs_write, NULL);
+ return job;
+}
+
+void
+vc4_flush_jobs_writing_resource(struct vc4_context *vc4,
+ struct pipe_resource *prsc)
+{
+ struct hash_entry *entry = _mesa_hash_table_search(vc4->write_jobs,
+ prsc);
+ if (entry) {
+ struct vc4_job *job = entry->data;
+ vc4_job_submit(vc4, job);
+ }
+}
+
+void
+vc4_flush_jobs_reading_resource(struct vc4_context *vc4,
+ struct pipe_resource *prsc)
+{
+ struct vc4_resource *rsc = vc4_resource(prsc);
+
+ vc4_flush_jobs_writing_resource(vc4, prsc);
+
+ struct hash_entry *entry;
+ hash_table_foreach(vc4->jobs, entry) {
+ struct vc4_job *job = entry->data;
+
+ 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] == rsc->bo) {
+ vc4_job_submit(vc4, job);
+ continue;
+ }
+ }
+
+ /* Also check for the Z/color buffers, since the references to
+ * those are only added immediately before submit.
+ */
+ if (job->color_read && !(job->cleared & PIPE_CLEAR_COLOR)) {
+ struct vc4_resource *ctex =
+ vc4_resource(job->color_read->texture);
+ if (ctex->bo == rsc->bo) {
+ vc4_job_submit(vc4, job);
+ continue;
+ }
+ }
+
+ if (job->zs_read && !(job->cleared &
+ (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL))) {
+ struct vc4_resource *ztex =
+ vc4_resource(job->zs_read->texture);
+ if (ztex->bo == rsc->bo) {
+ vc4_job_submit(vc4, job);
+ continue;
+ }
+ }
+ }
+}
+
+/**
+ * Returns a vc4_job struture for tracking V3D rendering to a particular FBO.
+ *
+ * If we've already started rendering to this FBO, then return old same job,
+ * otherwise make a new one. If we're beginning rendering to an FBO, make
+ * sure that any previous reads of the FBO (or writes to its color/Z surfaces)
+ * have been flushed.
+ */
+struct vc4_job *
+vc4_get_job(struct vc4_context *vc4,
+ struct pipe_surface *cbuf, struct pipe_surface *zsbuf)
+{
+ /* Return the existing job for this FBO if we have one */
+ struct vc4_job_key local_key = {.cbuf = cbuf, .zsbuf = zsbuf};
+ struct hash_entry *entry = _mesa_hash_table_search(vc4->jobs,
+ &local_key);
+ if (entry)
+ return entry->data;
+
+ /* Creating a new job. Make sure that any previous jobs reading or
+ * writing these buffers are flushed.
+ */
+ if (cbuf)
+ vc4_flush_jobs_reading_resource(vc4, cbuf->texture);
+ if (zsbuf)
+ vc4_flush_jobs_reading_resource(vc4, zsbuf->texture);
+
+ struct vc4_job *job = vc4_job_create(vc4);
+
+ if (cbuf) {
+ if (cbuf->texture->nr_samples > 1) {
+ job->msaa = true;
+ pipe_surface_reference(&job->msaa_color_write, cbuf);
+ } else {
+ pipe_surface_reference(&job->color_write, cbuf);
+ }
+ }
+
+ if (zsbuf) {
+ if (zsbuf->texture->nr_samples > 1) {
+ job->msaa = true;
+ pipe_surface_reference(&job->msaa_zs_write, zsbuf);
+ } else {
+ pipe_surface_reference(&job->zs_write, zsbuf);
+ }
+ }
+
+ if (job->msaa) {
+ job->tile_width = 32;
+ job->tile_height = 32;
+ } else {
+ job->tile_width = 64;
+ job->tile_height = 64;
+ }
+
+ if (cbuf)
+ _mesa_hash_table_insert(vc4->write_jobs, cbuf->texture, job);
+ if (zsbuf)
+ _mesa_hash_table_insert(vc4->write_jobs, zsbuf->texture, job);
+
+ job->key.cbuf = cbuf;
+ job->key.zsbuf = zsbuf;
+ _mesa_hash_table_insert(vc4->jobs, &job->key, job);
+
+ return job;
+}
+
+struct vc4_job *
+vc4_get_job_for_fbo(struct vc4_context *vc4)
+{
+ if (vc4->job)
+ return vc4->job;
+
+ struct pipe_surface *cbuf = vc4->framebuffer.cbufs[0];
+ struct pipe_surface *zsbuf = vc4->framebuffer.zsbuf;
+ struct vc4_job *job = vc4_get_job(vc4, cbuf, zsbuf);
+
+ /* The dirty flags are tracking what's been updated while vc4->job has
+ * been bound, so set them all to ~0 when switching between jobs. We
+ * also need to reset all state at the start of rendering.
+ */
+ vc4->dirty = ~0;
+
+ /* Set up the read surfaces in the job. If they aren't actually
+ * getting read (due to a clear starting the frame), job->cleared will
+ * mask out the read.
+ */
+ pipe_surface_reference(&job->color_read, cbuf);
+ pipe_surface_reference(&job->zs_read, zsbuf);
+
+ /* If we're binding to uninitialized buffers, no need to load their
+ * contents before drawing.
+ */
+ if (cbuf) {
+ struct vc4_resource *rsc = vc4_resource(cbuf->texture);
+ if (!rsc->writes)
+ job->cleared |= PIPE_CLEAR_COLOR0;
+ }
+
+ if (zsbuf) {
+ struct vc4_resource *rsc = vc4_resource(zsbuf->texture);
+ if (!rsc->writes)
+ job->cleared |= PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL;
+ }
+
+ job->draw_tiles_x = DIV_ROUND_UP(vc4->framebuffer.width,
+ job->tile_width);
+ job->draw_tiles_y = DIV_ROUND_UP(vc4->framebuffer.height,
+ job->tile_height);
+
+ vc4->job = job;
+
+ return job;
}
static void
@@ -166,15 +356,14 @@ void
vc4_job_submit(struct vc4_context *vc4, struct vc4_job *job)
{
if (!job->needs_flush)
- return;
+ goto done;
/* The RCL setup would choke if the draw bounds cause no drawing, so
* just drop the drawing if that's the case.
*/
if (job->draw_max_x <= job->draw_min_x ||
job->draw_max_y <= job->draw_min_y) {
- vc4_job_reset(job);
- return;
+ goto done;
}
if (vc4_debug & VC4_DEBUG_CL) {
@@ -275,7 +464,7 @@ vc4_job_submit(struct vc4_context *vc4, struct vc4_job *job)
#ifndef USE_VC4_SIMULATOR
ret = drmIoctl(vc4->fd, DRM_IOCTL_VC4_SUBMIT_CL, &submit);
#else
- ret = vc4_simulator_flush(vc4, &submit);
+ ret = vc4_simulator_flush(vc4, &submit, job);
#endif
static bool warned = false;
if (ret && !warned) {
@@ -304,5 +493,30 @@ vc4_job_submit(struct vc4_context *vc4, struct vc4_job *job)
}
}
- vc4_job_reset(vc4->job);
+done:
+ vc4_job_free(vc4, job);
+}
+
+static bool
+vc4_job_compare(const void *a, const void *b)
+{
+ return memcmp(a, b, sizeof(struct vc4_job_key)) == 0;
+}
+
+static uint32_t
+vc4_job_hash(const void *key)
+{
+ return _mesa_hash_data(key, sizeof(struct vc4_job_key));
+}
+
+void
+vc4_job_init(struct vc4_context *vc4)
+{
+ vc4->jobs = _mesa_hash_table_create(vc4,
+ vc4_job_hash,
+ vc4_job_compare);
+ vc4->write_jobs = _mesa_hash_table_create(vc4,
+ _mesa_hash_pointer,
+ _mesa_key_pointer_equal);
}
+