if (dst_base_slice->tiling == VC5_TILING_RASTER)
return false;
- v3d_flush_jobs_writing_resource(v3d, psrc);
+ v3d_flush_jobs_writing_resource(v3d, psrc, false);
v3d_flush_jobs_reading_resource(v3d, pdst);
struct drm_v3d_submit_tfu tfu = {
* run into unexpected OOMs when blits are used for a large series of
* texture uploads before using the textures.
*/
- v3d_flush_jobs_writing_resource(v3d, info.dst.resource);
+ v3d_flush_jobs_writing_resource(v3d, info.dst.resource, false);
}
void v3d_job_submit(struct v3d_context *v3d, struct v3d_job *job);
void v3d_flush_jobs_using_bo(struct v3d_context *v3d, struct v3d_bo *bo);
void v3d_flush_jobs_writing_resource(struct v3d_context *v3d,
- struct pipe_resource *prsc);
+ struct pipe_resource *prsc,
+ bool always_flush);
void v3d_flush_jobs_reading_resource(struct v3d_context *v3d,
struct pipe_resource *prsc);
void v3d_update_compiled_shaders(struct v3d_context *v3d, uint8_t prim_mode);
_mesa_set_add(job->tf_write_prscs, prsc);
}
+static bool
+v3d_job_writes_resource_from_tf(struct v3d_job *job,
+ struct pipe_resource *prsc)
+{
+ if (!job->tf_enabled)
+ return false;
+
+ if (!job->tf_write_prscs)
+ return false;
+
+ return _mesa_set_search(job->tf_write_prscs, prsc) != NULL;
+}
+
void
v3d_flush_jobs_writing_resource(struct v3d_context *v3d,
- struct pipe_resource *prsc)
+ struct pipe_resource *prsc,
+ bool always_flush)
{
struct hash_entry *entry = _mesa_hash_table_search(v3d->write_jobs,
prsc);
- if (entry) {
- struct v3d_job *job = entry->data;
- v3d_job_submit(v3d, job);
+ if (!entry)
+ return;
+
+ struct v3d_job *job = entry->data;
+
+ /* For writes from TF in the same job we use the "Wait for TF"
+ * feature provided by the hardware so we don't want to flush.
+ * The exception to this is when the caller is about to map the
+ * resource since in that case we don't have a 'Wait for TF' command
+ * the in command stream. In this scenario the caller is expected
+ * to set 'always_flush' to True.
+ */
+ bool needs_flush;
+ if (always_flush) {
+ needs_flush = true;
+ } else if (!v3d->job || v3d->job != job) {
+ /* Write from a different job: always flush */
+ needs_flush = true;
+ } else {
+ /* Write from currrent job: flush if not TF */
+ needs_flush = !v3d_job_writes_resource_from_tf(job, prsc);
}
+
+ if (needs_flush)
+ v3d_job_submit(v3d, job);
}
void
{
struct v3d_resource *rsc = v3d_resource(prsc);
- v3d_flush_jobs_writing_resource(v3d, prsc);
+ /* We only need to force the flush on TF writes, which is the only
+ * case where we might skip the flush to use the 'Wait for TF'
+ * command. Here we are flushing for a read, which means that the
+ * caller intends to write to the resource, so we don't care if
+ * there was a previous TF write to it.
+ */
+ v3d_flush_jobs_writing_resource(v3d, prsc, false);
hash_table_foreach(v3d->jobs, entry) {
struct v3d_job *job = entry->data;
if (usage & PIPE_TRANSFER_WRITE)
v3d_flush_jobs_reading_resource(v3d, prsc);
else
- v3d_flush_jobs_writing_resource(v3d, prsc);
+ v3d_flush_jobs_writing_resource(v3d, prsc, true);
}
if (usage & PIPE_TRANSFER_WRITE) {
{
struct v3d_context *v3d = v3d_context(pctx);
- /* XXX perf: If we're reading from the output of TF in this job, we
- * should instead be using the wait for transform feedback
- * functionality.
- */
-
/* Flush writes to textures we're sampling. */
for (int i = 0; i < v3d->tex[s].num_textures; i++) {
struct pipe_sampler_view *pview = v3d->tex[s].textures[i];
view->base.format != PIPE_FORMAT_X32_S8X24_UINT)
v3d_update_shadow_texture(pctx, &view->base);
- v3d_flush_jobs_writing_resource(v3d, view->texture);
+ v3d_flush_jobs_writing_resource(v3d, view->texture, false);
}
/* Flush writes to UBOs. */
foreach_bit(i, v3d->constbuf[s].enabled_mask) {
struct pipe_constant_buffer *cb = &v3d->constbuf[s].cb[i];
if (cb->buffer)
- v3d_flush_jobs_writing_resource(v3d, cb->buffer);
+ v3d_flush_jobs_writing_resource(v3d, cb->buffer, false);
}
/* Flush writes to our image views */
foreach_bit(i, v3d->shaderimg[s].enabled_mask) {
struct v3d_image_view *view = &v3d->shaderimg[s].si[i];
- v3d_flush_jobs_writing_resource(v3d, view->base.resource);
+ v3d_flush_jobs_writing_resource(v3d, view->base.resource,
+ false);
}
/* Flush writes to our vertex buffers (i.e. from transform feedback) */
foreach_bit(i, v3d->vertexbuf.enabled_mask) {
struct pipe_vertex_buffer *vb = &v3d->vertexbuf.vb[i];
- v3d_flush_jobs_writing_resource(v3d, vb->buffer.resource);
+ v3d_flush_jobs_writing_resource(v3d, vb->buffer.resource,
+ false);
}
}
}
for (int s = 0; s < PIPE_SHADER_COMPUTE; s++)
v3d_predraw_check_stage_inputs(pctx, s);
- if (info->indirect)
- v3d_flush_jobs_writing_resource(v3d, info->indirect->buffer);
+ if (info->indirect) {
+ v3d_flush_jobs_writing_resource(v3d, info->indirect->buffer,
+ false);
+ }
v3d_predraw_check_outputs(pctx);