Module: Mesa
Branch: staging/22.3
Commit: 9254827da8cd71118f8e11cafa6aa6ee680b0e4e
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=9254827da8cd71118f8e11cafa6aa6ee680b0e4e

Author: Iago Toral Quiroga <[email protected]>
Date:   Thu Dec  1 11:02:12 2022 +0100

v3dv: fix job serialization for single sync path

The idea in the single sync path is that we serialize any job that
needs to wait, however, our ANY queue syncobj only tracks the last job
submitted to any hardware queue, so in practice when we wait on this
we are only serializing against the queue to which we have submitted
the last job, which is not correct.

Fix that by accumulating the last job sync into the ANY queue synbcobj
to ensure that waiting on this syncobj effectively waits on all
hardware queues.

Reviewed-by: Alejandro PiƱeiro <[email protected]>
cc: mesa-stable

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20078>
(cherry picked from commit 4276ec9f2af33da270ca9cf6a6a9a62b2a4d060a)

---

 .pick_status.json                |  2 +-
 src/broadcom/vulkan/v3dv_queue.c | 58 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/.pick_status.json b/.pick_status.json
index ea09b230d80..d2a8dc5ed82 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -103,7 +103,7 @@
         "description": "v3dv: fix job serialization for single sync path",
         "nominated": true,
         "nomination_type": 0,
-        "resolution": 0,
+        "resolution": 1,
         "main_sha": null,
         "because_sha": null
     },
diff --git a/src/broadcom/vulkan/v3dv_queue.c b/src/broadcom/vulkan/v3dv_queue.c
index d7ae326fc42..db2aae1dcef 100644
--- a/src/broadcom/vulkan/v3dv_queue.c
+++ b/src/broadcom/vulkan/v3dv_queue.c
@@ -407,6 +407,12 @@ handle_csd_indirect_cpu_job(struct v3dv_queue *queue,
    return VK_SUCCESS;
 }
 
+/**
+ * This handles semaphore waits for the single sync path by accumulating
+ * wait semaphores into the QUEUE_ANY syncobj. Notice this is only required
+ * to ensure we accumulate any *external* semaphores (since for anything else
+ * we are already accumulating out syncs with each submission to the kernel).
+ */
 static VkResult
 process_singlesync_waits(struct v3dv_queue *queue,
                          uint32_t count, struct vk_sync_wait *waits)
@@ -671,6 +677,43 @@ fail:
    return;
 }
 
+/* This must be called after every submission in the single-sync path to
+ * accumulate the out_sync into the QUEUE_ANY sync so we can serialize
+ * jobs by waiting on the QUEUE_ANY sync.
+ */
+static int
+update_any_queue_sync(struct v3dv_queue *queue, uint32_t out_sync)
+{
+   struct v3dv_device *device = queue->device;
+   assert(!device->pdevice->caps.multisync);
+
+   int render_fd = device->pdevice->render_fd;
+   int fd_any = -1, fd_out_sync = -1;
+   int err;
+   err  = drmSyncobjExportSyncFile(render_fd,
+                                   queue->last_job_syncs.syncs[V3DV_QUEUE_ANY],
+                                   &fd_any);
+   if (err)
+      goto fail;
+
+   err = drmSyncobjExportSyncFile(render_fd, out_sync, &fd_out_sync);
+   if (err)
+      goto fail;
+
+   err = sync_accumulate("v3dv", &fd_any, fd_out_sync);
+   if (err)
+      goto fail;
+
+   err = drmSyncobjImportSyncFile(render_fd,
+                                  queue->last_job_syncs.syncs[V3DV_QUEUE_ANY],
+                                  fd_any);
+
+fail:
+   close(fd_any);
+   close(fd_out_sync);
+   return err;
+}
+
 static VkResult
 handle_cl_job(struct v3dv_queue *queue,
               struct v3dv_job *job,
@@ -787,7 +830,7 @@ handle_cl_job(struct v3dv_queue *queue,
       uint32_t last_job_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_ANY];
       submit.in_sync_bcl = needs_bcl_sync ? last_job_sync : 0;
       submit.in_sync_rcl = needs_rcl_sync ? last_job_sync : 0;
-      submit.out_sync = last_job_sync;
+      submit.out_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_CL];
    }
 
    v3dv_clif_dump(device, job, &submit);
@@ -801,6 +844,9 @@ handle_cl_job(struct v3dv_queue *queue,
       warned = true;
    }
 
+   if (!device->pdevice->caps.multisync && ret == 0)
+      ret = update_any_queue_sync(queue, submit.out_sync);
+
    free(bo_handles);
    multisync_free(device, &ms);
 
@@ -840,11 +886,14 @@ handle_tfu_job(struct v3dv_queue *queue,
    } else {
       uint32_t last_job_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_ANY];
       job->tfu.in_sync = needs_sync ? last_job_sync : 0;
-      job->tfu.out_sync = last_job_sync;
+      job->tfu.out_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_TFU];
    }
    int ret = v3dv_ioctl(device->pdevice->render_fd,
                         DRM_IOCTL_V3D_SUBMIT_TFU, &job->tfu);
 
+   if (!device->pdevice->caps.multisync && ret == 0)
+      ret = update_any_queue_sync(queue, job->tfu.out_sync);
+
    multisync_free(device, &ms);
    queue->last_job_syncs.first[V3DV_QUEUE_TFU] = false;
 
@@ -907,7 +956,7 @@ handle_csd_job(struct v3dv_queue *queue,
    } else {
       uint32_t last_job_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_ANY];
       submit->in_sync = needs_sync ? last_job_sync : 0;
-      submit->out_sync = last_job_sync;
+      submit->out_sync = queue->last_job_syncs.syncs[V3DV_QUEUE_CSD];
    }
    submit->perfmon_id = job->perf ?
       job->perf->kperfmon_ids[counter_pass_idx] : 0;
@@ -922,6 +971,9 @@ handle_csd_job(struct v3dv_queue *queue,
       warned = true;
    }
 
+   if (!device->pdevice->caps.multisync && ret == 0)
+      ret = update_any_queue_sync(queue, submit->out_sync);
+
    free(bo_handles);
 
    multisync_free(device, &ms);

Reply via email to