summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose Maria Casanova Crespo <jmcasanova@igalia.com>2019-11-11 01:46:24 +0100
committerDylan Baker <dylan@pnwbakers.com>2020-02-25 08:53:12 -0800
commite1dc5cc75724317cbc6d2b467b6504e6a561dab7 (patch)
tree6eb4ac8c74bc6029909a22b2fb3aec94c9406b23
parent312a81ec61f719be46ad1ac6a36fd84916d109de (diff)
v3d: Sync on last CS when non-compute stage uses resource written by CS
When a resource is written by a compute shader and then used by a non-compute stage we sync on last compute job to guarantee that the resource has been completely written when the next stage reads resources. In the other cases how flushes are done guarantee the serialization of the writes and reads. To reproduce the failure the following tests should be executed in batch as last test don't fail when run isolated: KHR-GLES31.core.shader_image_load_store.basic-allFormats-load-fs KHR-GLES31.core.shader_image_load_store.basic-allFormats-loadStoreComputeStage KHR-GLES31.core.shader_image_load_store.basic-allTargets-load-cs KHR-GLES31.core.shader_image_load_store.advanced-sync-vertexArray v2: Use fence dep instead of bo_wait (Eric Anholt) v3: Rename struct names (Iago Toral) Document why is not needed on graphics->compute case. (Iago Toral) Follow same code pattern of the other update of in_sync_bcl. v4: Fixed comments style. (Iago Toral) Fixes KHR-GLES31.core.shader_image_load_store.advanced-sync-vertexArray Reviewed-by: Iago Toral Quiroga <itoral@igalia.com> CC: 19.3 20.0 <mesa-stable@lists.freedesktop.org> Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2700> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2700> (cherry picked from commit 01496e3d1ea0370af03e6645dbd2b864c2ace94c)
-rw-r--r--.pick_status.json2
-rw-r--r--src/gallium/drivers/v3d/v3d_blit.c8
-rw-r--r--src/gallium/drivers/v3d/v3d_context.h12
-rw-r--r--src/gallium/drivers/v3d/v3d_job.c30
-rw-r--r--src/gallium/drivers/v3d/v3d_resource.c14
-rw-r--r--src/gallium/drivers/v3d/v3d_resource.h5
-rw-r--r--src/gallium/drivers/v3d/v3dx_draw.c32
7 files changed, 77 insertions, 26 deletions
diff --git a/.pick_status.json b/.pick_status.json
index b6cab30e5af..60091dfca91 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -4,7 +4,7 @@
"description": "v3d: Sync on last CS when non-compute stage uses resource written by CS",
"nominated": true,
"nomination_type": 0,
- "resolution": 0,
+ "resolution": 1,
"master_sha": null,
"because_sha": null
},
diff --git a/src/gallium/drivers/v3d/v3d_blit.c b/src/gallium/drivers/v3d/v3d_blit.c
index 6c69f00b704..2a743a1a954 100644
--- a/src/gallium/drivers/v3d/v3d_blit.c
+++ b/src/gallium/drivers/v3d/v3d_blit.c
@@ -128,7 +128,7 @@ v3d_tile_blit(struct pipe_context *pctx, const struct pipe_blit_info *info)
struct pipe_surface *src_surf =
v3d_get_blit_surface(pctx, info->src.resource, info->src.level);
- v3d_flush_jobs_reading_resource(v3d, info->src.resource);
+ v3d_flush_jobs_reading_resource(v3d, info->src.resource, false);
struct v3d_job *job = v3d_get_job(v3d, dst_surf, NULL);
pipe_surface_reference(&job->color_read, src_surf);
@@ -380,8 +380,8 @@ v3d_tfu(struct pipe_context *pctx,
if (dst_base_slice->tiling == VC5_TILING_RASTER)
return false;
- v3d_flush_jobs_writing_resource(v3d, psrc, V3D_FLUSH_DEFAULT);
- v3d_flush_jobs_reading_resource(v3d, pdst, V3D_FLUSH_DEFAULT);
+ v3d_flush_jobs_writing_resource(v3d, psrc, V3D_FLUSH_DEFAULT, false);
+ v3d_flush_jobs_reading_resource(v3d, pdst, V3D_FLUSH_DEFAULT, false);
struct drm_v3d_submit_tfu tfu = {
.ios = (height << 16) | width,
@@ -538,5 +538,5 @@ v3d_blit(struct pipe_context *pctx, const struct pipe_blit_info *blit_info)
* texture uploads before using the textures.
*/
v3d_flush_jobs_writing_resource(v3d, info.dst.resource,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT, false);
}
diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h
index ecedbaf9efb..2bf9c41fd92 100644
--- a/src/gallium/drivers/v3d/v3d_context.h
+++ b/src/gallium/drivers/v3d/v3d_context.h
@@ -511,6 +511,12 @@ struct v3d_context {
bool active_queries;
+ /**
+ * If a compute job writes a resource read by a non-compute stage we
+ * should sync on the last compute job.
+ */
+ bool sync_on_last_compute_job;
+
uint32_t tf_prims_generated;
uint32_t prims_generated;
@@ -644,10 +650,12 @@ 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,
- enum v3d_flush_cond flush_cond);
+ enum v3d_flush_cond flush_cond,
+ bool is_compute_pipeline);
void v3d_flush_jobs_reading_resource(struct v3d_context *v3d,
struct pipe_resource *prsc,
- enum v3d_flush_cond flush_cond);
+ enum v3d_flush_cond flush_cond,
+ bool is_compute_pipeline);
void v3d_update_compiled_shaders(struct v3d_context *v3d, uint8_t prim_mode);
void v3d_update_compiled_cs(struct v3d_context *v3d);
diff --git a/src/gallium/drivers/v3d/v3d_job.c b/src/gallium/drivers/v3d/v3d_job.c
index 0acd8b033c2..31a6683151e 100644
--- a/src/gallium/drivers/v3d/v3d_job.c
+++ b/src/gallium/drivers/v3d/v3d_job.c
@@ -184,10 +184,23 @@ v3d_job_writes_resource_from_tf(struct v3d_job *job,
void
v3d_flush_jobs_writing_resource(struct v3d_context *v3d,
struct pipe_resource *prsc,
- enum v3d_flush_cond flush_cond)
+ enum v3d_flush_cond flush_cond,
+ bool is_compute_pipeline)
{
struct hash_entry *entry = _mesa_hash_table_search(v3d->write_jobs,
prsc);
+ struct v3d_resource *rsc = v3d_resource(prsc);
+
+ /* We need to sync if graphics pipeline reads a resource written
+ * by the compute pipeline. The same would be needed for the case of
+ * graphics-compute dependency but nowadays all compute jobs
+ * are serialized with the previous submitted job.
+ */
+ if (!is_compute_pipeline && rsc->bo != NULL && rsc->compute_written) {
+ v3d->sync_on_last_compute_job = true;
+ rsc->compute_written = false;
+ }
+
if (!entry)
return;
@@ -220,7 +233,8 @@ v3d_flush_jobs_writing_resource(struct v3d_context *v3d,
void
v3d_flush_jobs_reading_resource(struct v3d_context *v3d,
struct pipe_resource *prsc,
- enum v3d_flush_cond flush_cond)
+ enum v3d_flush_cond flush_cond,
+ bool is_compute_pipeline)
{
struct v3d_resource *rsc = v3d_resource(prsc);
@@ -230,7 +244,8 @@ v3d_flush_jobs_reading_resource(struct v3d_context *v3d,
* 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, flush_cond);
+ v3d_flush_jobs_writing_resource(v3d, prsc, flush_cond,
+ is_compute_pipeline);
hash_table_foreach(v3d->jobs, entry) {
struct v3d_job *job = entry->data;
@@ -329,7 +344,8 @@ v3d_get_job(struct v3d_context *v3d,
for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) {
if (cbufs[i]) {
v3d_flush_jobs_reading_resource(v3d, cbufs[i]->texture,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT,
+ false);
pipe_surface_reference(&job->cbufs[i], cbufs[i]);
if (cbufs[i]->texture->nr_samples > 1)
@@ -338,7 +354,8 @@ v3d_get_job(struct v3d_context *v3d,
}
if (zsbuf) {
v3d_flush_jobs_reading_resource(v3d, zsbuf->texture,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT,
+ false);
pipe_surface_reference(&job->zsbuf, zsbuf);
if (zsbuf->texture->nr_samples > 1)
job->msaa = true;
@@ -356,7 +373,8 @@ v3d_get_job(struct v3d_context *v3d,
if (rsc->separate_stencil) {
v3d_flush_jobs_reading_resource(v3d,
&rsc->separate_stencil->base,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT,
+ false);
_mesa_hash_table_insert(v3d->write_jobs,
&rsc->separate_stencil->base,
job);
diff --git a/src/gallium/drivers/v3d/v3d_resource.c b/src/gallium/drivers/v3d/v3d_resource.c
index c2590fac1e5..90608434eef 100644
--- a/src/gallium/drivers/v3d/v3d_resource.c
+++ b/src/gallium/drivers/v3d/v3d_resource.c
@@ -170,19 +170,23 @@ v3d_map_usage_prep(struct pipe_context *pctx,
* don't violate any syncing requirements.
*/
v3d_flush_jobs_reading_resource(v3d, prsc,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT,
+ false);
}
} else if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
/* If we're writing and the buffer is being used by the CL, we
* have to flush the CL first. If we're only reading, we need
* to flush if the CL has written our buffer.
*/
- if (usage & PIPE_TRANSFER_WRITE)
+ if (usage & PIPE_TRANSFER_WRITE) {
v3d_flush_jobs_reading_resource(v3d, prsc,
- V3D_FLUSH_ALWAYS);
- else
+ V3D_FLUSH_ALWAYS,
+ false);
+ } else {
v3d_flush_jobs_writing_resource(v3d, prsc,
- V3D_FLUSH_ALWAYS);
+ V3D_FLUSH_ALWAYS,
+ false);
+ }
}
if (usage & PIPE_TRANSFER_WRITE) {
diff --git a/src/gallium/drivers/v3d/v3d_resource.h b/src/gallium/drivers/v3d/v3d_resource.h
index f0b7c26e048..812131dddf2 100644
--- a/src/gallium/drivers/v3d/v3d_resource.h
+++ b/src/gallium/drivers/v3d/v3d_resource.h
@@ -130,6 +130,11 @@ struct v3d_resource {
bool tiled;
/**
+ * Indicates if the CS has written the resource
+ */
+ bool compute_written;
+
+ /**
* Number of times the resource has been written to.
*
* This is used to track whether we need to load the surface on first
diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c
index 3a5b1171020..91ae5ba4911 100644
--- a/src/gallium/drivers/v3d/v3dx_draw.c
+++ b/src/gallium/drivers/v3d/v3dx_draw.c
@@ -157,7 +157,8 @@ v3d_predraw_check_stage_inputs(struct pipe_context *pctx,
v3d_update_shadow_texture(pctx, &view->base);
v3d_flush_jobs_writing_resource(v3d, view->texture,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT,
+ s == PIPE_SHADER_COMPUTE);
}
/* Flush writes to UBOs. */
@@ -165,7 +166,8 @@ v3d_predraw_check_stage_inputs(struct pipe_context *pctx,
struct pipe_constant_buffer *cb = &v3d->constbuf[s].cb[i];
if (cb->buffer) {
v3d_flush_jobs_writing_resource(v3d, cb->buffer,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT,
+ s == PIPE_SHADER_COMPUTE);
}
}
@@ -174,7 +176,8 @@ v3d_predraw_check_stage_inputs(struct pipe_context *pctx,
struct pipe_shader_buffer *sb = &v3d->ssbo[s].sb[i];
if (sb->buffer) {
v3d_flush_jobs_reading_resource(v3d, sb->buffer,
- V3D_FLUSH_NOT_CURRENT_JOB);
+ V3D_FLUSH_NOT_CURRENT_JOB,
+ s == PIPE_SHADER_COMPUTE);
}
}
@@ -183,7 +186,8 @@ v3d_predraw_check_stage_inputs(struct pipe_context *pctx,
struct v3d_image_view *view = &v3d->shaderimg[s].si[i];
v3d_flush_jobs_reading_resource(v3d, view->base.resource,
- V3D_FLUSH_NOT_CURRENT_JOB);
+ V3D_FLUSH_NOT_CURRENT_JOB,
+ s == PIPE_SHADER_COMPUTE);
}
/* Flush writes to our vertex buffers (i.e. from transform feedback) */
@@ -192,7 +196,8 @@ v3d_predraw_check_stage_inputs(struct pipe_context *pctx,
struct pipe_vertex_buffer *vb = &v3d->vertexbuf.vb[i];
v3d_flush_jobs_writing_resource(v3d, vb->buffer.resource,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT,
+ false);
}
}
}
@@ -213,7 +218,8 @@ v3d_predraw_check_outputs(struct pipe_context *pctx)
const struct pipe_stream_output_target *target =
so->targets[i];
v3d_flush_jobs_reading_resource(v3d, target->buffer,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT,
+ false);
}
}
}
@@ -667,7 +673,7 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
if (info->indirect) {
v3d_flush_jobs_writing_resource(v3d, info->indirect->buffer,
- V3D_FLUSH_DEFAULT);
+ V3D_FLUSH_DEFAULT, false);
}
v3d_predraw_check_outputs(pctx);
@@ -699,6 +705,14 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
job->submit.in_sync_bcl = v3d->out_sync;
}
+ /* We also need to ensure that compute is complete when render depends
+ * on resources written by it.
+ */
+ if (v3d->sync_on_last_compute_job) {
+ job->submit.in_sync_bcl = v3d->out_sync;
+ v3d->sync_on_last_compute_job = false;
+ }
+
/* Mark SSBOs and images as being written. We don't actually know
* which ones are read vs written, so just assume the worst.
*/
@@ -1114,13 +1128,15 @@ v3d_launch_grid(struct pipe_context *pctx, const struct pipe_grid_info *info)
foreach_bit(i, v3d->ssbo[PIPE_SHADER_COMPUTE].enabled_mask) {
struct v3d_resource *rsc = v3d_resource(
v3d->ssbo[PIPE_SHADER_COMPUTE].sb[i].buffer);
- rsc->writes++; /* XXX */
+ rsc->writes++;
+ rsc->compute_written = true;
}
foreach_bit(i, v3d->shaderimg[PIPE_SHADER_COMPUTE].enabled_mask) {
struct v3d_resource *rsc = v3d_resource(
v3d->shaderimg[PIPE_SHADER_COMPUTE].si[i].base.resource);
rsc->writes++;
+ rsc->compute_written = true;
}
v3d_bo_unreference(&uniforms.bo);