xref: /aosp_15_r20/external/mesa3d/src/broadcom/vulkan/v3dv_queue.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2019 Raspberry Pi Ltd
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "v3dv_private.h"
25*61046927SAndroid Build Coastguard Worker #include "drm-uapi/v3d_drm.h"
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #include "broadcom/clif/clif_dump.h"
28*61046927SAndroid Build Coastguard Worker #include "util/libsync.h"
29*61046927SAndroid Build Coastguard Worker #include "util/os_time.h"
30*61046927SAndroid Build Coastguard Worker #include "vk_drm_syncobj.h"
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker #include <errno.h>
33*61046927SAndroid Build Coastguard Worker #include <time.h>
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker static void
v3dv_clif_dump(struct v3dv_device * device,struct v3dv_job * job,struct drm_v3d_submit_cl * submit)36*61046927SAndroid Build Coastguard Worker v3dv_clif_dump(struct v3dv_device *device,
37*61046927SAndroid Build Coastguard Worker                struct v3dv_job *job,
38*61046927SAndroid Build Coastguard Worker                struct drm_v3d_submit_cl *submit)
39*61046927SAndroid Build Coastguard Worker {
40*61046927SAndroid Build Coastguard Worker    if (!(V3D_DBG(CL) ||
41*61046927SAndroid Build Coastguard Worker          V3D_DBG(CL_NO_BIN) ||
42*61046927SAndroid Build Coastguard Worker          V3D_DBG(CLIF)))
43*61046927SAndroid Build Coastguard Worker       return;
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker    struct clif_dump *clif = clif_dump_init(&device->devinfo,
46*61046927SAndroid Build Coastguard Worker                                            stderr,
47*61046927SAndroid Build Coastguard Worker                                            V3D_DBG(CL) ||
48*61046927SAndroid Build Coastguard Worker                                            V3D_DBG(CL_NO_BIN),
49*61046927SAndroid Build Coastguard Worker                                            V3D_DBG(CL_NO_BIN));
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker    set_foreach(job->bos, entry) {
52*61046927SAndroid Build Coastguard Worker       struct v3dv_bo *bo = (void *)entry->key;
53*61046927SAndroid Build Coastguard Worker       char *name = ralloc_asprintf(NULL, "%s_0x%x",
54*61046927SAndroid Build Coastguard Worker                                    bo->name, bo->offset);
55*61046927SAndroid Build Coastguard Worker 
56*61046927SAndroid Build Coastguard Worker       bool ok = v3dv_bo_map(device, bo, bo->size);
57*61046927SAndroid Build Coastguard Worker       if (!ok) {
58*61046927SAndroid Build Coastguard Worker          fprintf(stderr, "failed to map BO for clif_dump.\n");
59*61046927SAndroid Build Coastguard Worker          ralloc_free(name);
60*61046927SAndroid Build Coastguard Worker          goto free_clif;
61*61046927SAndroid Build Coastguard Worker       }
62*61046927SAndroid Build Coastguard Worker       clif_dump_add_bo(clif, name, bo->offset, bo->size, bo->map);
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker       ralloc_free(name);
65*61046927SAndroid Build Coastguard Worker    }
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker    clif_dump(clif, submit);
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker  free_clif:
70*61046927SAndroid Build Coastguard Worker    clif_dump_destroy(clif);
71*61046927SAndroid Build Coastguard Worker }
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker static VkResult
queue_wait_idle(struct v3dv_queue * queue,struct v3dv_submit_sync_info * sync_info)74*61046927SAndroid Build Coastguard Worker queue_wait_idle(struct v3dv_queue *queue,
75*61046927SAndroid Build Coastguard Worker                 struct v3dv_submit_sync_info *sync_info)
76*61046927SAndroid Build Coastguard Worker {
77*61046927SAndroid Build Coastguard Worker    int ret = drmSyncobjWait(queue->device->pdevice->render_fd,
78*61046927SAndroid Build Coastguard Worker                             queue->last_job_syncs.syncs, 4,
79*61046927SAndroid Build Coastguard Worker                             INT64_MAX, DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL,
80*61046927SAndroid Build Coastguard Worker                             NULL);
81*61046927SAndroid Build Coastguard Worker    if (ret)
82*61046927SAndroid Build Coastguard Worker       return vk_errorf(queue, VK_ERROR_DEVICE_LOST, "syncobj wait failed: %m");
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    bool first = true;
85*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < 4; i++) {
86*61046927SAndroid Build Coastguard Worker       if (!queue->last_job_syncs.first[i])
87*61046927SAndroid Build Coastguard Worker          first = false;
88*61046927SAndroid Build Coastguard Worker    }
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker    /* If we're not the first job, that means we're waiting on some
91*61046927SAndroid Build Coastguard Worker     * per-queue-type syncobj which transitively waited on the semaphores
92*61046927SAndroid Build Coastguard Worker     * so we can skip the semaphore wait.
93*61046927SAndroid Build Coastguard Worker     */
94*61046927SAndroid Build Coastguard Worker    if (first) {
95*61046927SAndroid Build Coastguard Worker       VkResult result = vk_sync_wait_many(&queue->device->vk,
96*61046927SAndroid Build Coastguard Worker                                           sync_info->wait_count,
97*61046927SAndroid Build Coastguard Worker                                           sync_info->waits,
98*61046927SAndroid Build Coastguard Worker                                           VK_SYNC_WAIT_COMPLETE,
99*61046927SAndroid Build Coastguard Worker                                           UINT64_MAX);
100*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
101*61046927SAndroid Build Coastguard Worker          return result;
102*61046927SAndroid Build Coastguard Worker    }
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < 4; i++)
105*61046927SAndroid Build Coastguard Worker       queue->last_job_syncs.first[i] = false;
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
108*61046927SAndroid Build Coastguard Worker }
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker static void
multisync_free(struct v3dv_device * device,struct drm_v3d_multi_sync * ms)111*61046927SAndroid Build Coastguard Worker multisync_free(struct v3dv_device *device,
112*61046927SAndroid Build Coastguard Worker                struct drm_v3d_multi_sync *ms)
113*61046927SAndroid Build Coastguard Worker {
114*61046927SAndroid Build Coastguard Worker    vk_free(&device->vk.alloc, (void *)(uintptr_t)ms->out_syncs);
115*61046927SAndroid Build Coastguard Worker    vk_free(&device->vk.alloc, (void *)(uintptr_t)ms->in_syncs);
116*61046927SAndroid Build Coastguard Worker }
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker static struct drm_v3d_sem *
set_in_syncs(struct v3dv_queue * queue,struct v3dv_job * job,enum v3dv_queue_type queue_sync,uint32_t * count,struct vk_sync_wait * waits,unsigned wait_count,struct v3dv_submit_sync_info * sync_info)119*61046927SAndroid Build Coastguard Worker set_in_syncs(struct v3dv_queue *queue,
120*61046927SAndroid Build Coastguard Worker              struct v3dv_job *job,
121*61046927SAndroid Build Coastguard Worker              enum v3dv_queue_type queue_sync,
122*61046927SAndroid Build Coastguard Worker              uint32_t *count,
123*61046927SAndroid Build Coastguard Worker              struct vk_sync_wait *waits,
124*61046927SAndroid Build Coastguard Worker              unsigned wait_count,
125*61046927SAndroid Build Coastguard Worker              struct v3dv_submit_sync_info *sync_info)
126*61046927SAndroid Build Coastguard Worker {
127*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
128*61046927SAndroid Build Coastguard Worker    uint32_t n_syncs = 0;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker    /* If this is the first job submitted to a given GPU queue in this cmd buf
131*61046927SAndroid Build Coastguard Worker     * batch, it has to wait on wait semaphores (if any) before running.
132*61046927SAndroid Build Coastguard Worker     */
133*61046927SAndroid Build Coastguard Worker    if (queue->last_job_syncs.first[queue_sync])
134*61046927SAndroid Build Coastguard Worker       n_syncs = sync_info->wait_count;
135*61046927SAndroid Build Coastguard Worker 
136*61046927SAndroid Build Coastguard Worker    /* If the serialize flag is set the job needs to be serialized in the
137*61046927SAndroid Build Coastguard Worker     * corresponding queues. Notice that we may implement transfer operations
138*61046927SAndroid Build Coastguard Worker     * as both CL or TFU jobs.
139*61046927SAndroid Build Coastguard Worker     *
140*61046927SAndroid Build Coastguard Worker     * FIXME: maybe we could track more precisely if the source of a transfer
141*61046927SAndroid Build Coastguard Worker     * barrier is a CL and/or a TFU job.
142*61046927SAndroid Build Coastguard Worker     */
143*61046927SAndroid Build Coastguard Worker    bool sync_csd  = job->serialize & V3DV_BARRIER_COMPUTE_BIT;
144*61046927SAndroid Build Coastguard Worker    bool sync_tfu  = job->serialize & V3DV_BARRIER_TRANSFER_BIT;
145*61046927SAndroid Build Coastguard Worker    bool sync_cl   = job->serialize & (V3DV_BARRIER_GRAPHICS_BIT |
146*61046927SAndroid Build Coastguard Worker                                       V3DV_BARRIER_TRANSFER_BIT);
147*61046927SAndroid Build Coastguard Worker    bool sync_cpu  = job->serialize & V3DV_BARRIER_CPU_BIT;
148*61046927SAndroid Build Coastguard Worker 
149*61046927SAndroid Build Coastguard Worker    *count = n_syncs;
150*61046927SAndroid Build Coastguard Worker    if (sync_cl)
151*61046927SAndroid Build Coastguard Worker       (*count)++;
152*61046927SAndroid Build Coastguard Worker    if (sync_tfu)
153*61046927SAndroid Build Coastguard Worker       (*count)++;
154*61046927SAndroid Build Coastguard Worker    if (sync_csd)
155*61046927SAndroid Build Coastguard Worker       (*count)++;
156*61046927SAndroid Build Coastguard Worker    if (sync_cpu)
157*61046927SAndroid Build Coastguard Worker       (*count)++;
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker    *count += wait_count;
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker    if (!*count)
162*61046927SAndroid Build Coastguard Worker       return NULL;
163*61046927SAndroid Build Coastguard Worker 
164*61046927SAndroid Build Coastguard Worker    struct drm_v3d_sem *syncs =
165*61046927SAndroid Build Coastguard Worker       vk_zalloc(&device->vk.alloc, *count * sizeof(struct drm_v3d_sem),
166*61046927SAndroid Build Coastguard Worker                 8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
167*61046927SAndroid Build Coastguard Worker 
168*61046927SAndroid Build Coastguard Worker    if (!syncs)
169*61046927SAndroid Build Coastguard Worker       return NULL;
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < n_syncs; i++) {
172*61046927SAndroid Build Coastguard Worker       syncs[i].handle =
173*61046927SAndroid Build Coastguard Worker          vk_sync_as_drm_syncobj(sync_info->waits[i].sync)->syncobj;
174*61046927SAndroid Build Coastguard Worker    }
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < wait_count; i++) {
177*61046927SAndroid Build Coastguard Worker       syncs[n_syncs++].handle =
178*61046927SAndroid Build Coastguard Worker          vk_sync_as_drm_syncobj(waits[i].sync)->syncobj;
179*61046927SAndroid Build Coastguard Worker    }
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    if (sync_cl)
182*61046927SAndroid Build Coastguard Worker       syncs[n_syncs++].handle = queue->last_job_syncs.syncs[V3DV_QUEUE_CL];
183*61046927SAndroid Build Coastguard Worker 
184*61046927SAndroid Build Coastguard Worker    if (sync_csd)
185*61046927SAndroid Build Coastguard Worker       syncs[n_syncs++].handle = queue->last_job_syncs.syncs[V3DV_QUEUE_CSD];
186*61046927SAndroid Build Coastguard Worker 
187*61046927SAndroid Build Coastguard Worker    if (sync_tfu)
188*61046927SAndroid Build Coastguard Worker       syncs[n_syncs++].handle = queue->last_job_syncs.syncs[V3DV_QUEUE_TFU];
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker    if (sync_cpu)
191*61046927SAndroid Build Coastguard Worker       syncs[n_syncs++].handle = queue->last_job_syncs.syncs[V3DV_QUEUE_CPU];
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker    assert(n_syncs == *count);
194*61046927SAndroid Build Coastguard Worker    return syncs;
195*61046927SAndroid Build Coastguard Worker }
196*61046927SAndroid Build Coastguard Worker 
197*61046927SAndroid Build Coastguard Worker static struct drm_v3d_sem *
set_out_syncs(struct v3dv_queue * queue,struct v3dv_job * job,enum v3dv_queue_type queue_sync,uint32_t * count,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)198*61046927SAndroid Build Coastguard Worker set_out_syncs(struct v3dv_queue *queue,
199*61046927SAndroid Build Coastguard Worker               struct v3dv_job *job,
200*61046927SAndroid Build Coastguard Worker               enum v3dv_queue_type queue_sync,
201*61046927SAndroid Build Coastguard Worker               uint32_t *count,
202*61046927SAndroid Build Coastguard Worker               struct v3dv_submit_sync_info *sync_info,
203*61046927SAndroid Build Coastguard Worker               bool signal_syncs)
204*61046927SAndroid Build Coastguard Worker {
205*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
206*61046927SAndroid Build Coastguard Worker 
207*61046927SAndroid Build Coastguard Worker    uint32_t n_vk_syncs = signal_syncs ? sync_info->signal_count : 0;
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker    /* We always signal the syncobj from `device->last_job_syncs` related to
210*61046927SAndroid Build Coastguard Worker     * this v3dv_queue_type to track the last job submitted to this queue.
211*61046927SAndroid Build Coastguard Worker     */
212*61046927SAndroid Build Coastguard Worker    (*count) = n_vk_syncs + 1;
213*61046927SAndroid Build Coastguard Worker 
214*61046927SAndroid Build Coastguard Worker    struct drm_v3d_sem *syncs =
215*61046927SAndroid Build Coastguard Worker       vk_zalloc(&device->vk.alloc, *count * sizeof(struct drm_v3d_sem),
216*61046927SAndroid Build Coastguard Worker                 8, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
217*61046927SAndroid Build Coastguard Worker 
218*61046927SAndroid Build Coastguard Worker    if (!syncs)
219*61046927SAndroid Build Coastguard Worker       return NULL;
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker    if (n_vk_syncs) {
222*61046927SAndroid Build Coastguard Worker       for (unsigned i = 0; i < n_vk_syncs; i++) {
223*61046927SAndroid Build Coastguard Worker          syncs[i].handle =
224*61046927SAndroid Build Coastguard Worker             vk_sync_as_drm_syncobj(sync_info->signals[i].sync)->syncobj;
225*61046927SAndroid Build Coastguard Worker       }
226*61046927SAndroid Build Coastguard Worker    }
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    syncs[n_vk_syncs].handle = queue->last_job_syncs.syncs[queue_sync];
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker    return syncs;
231*61046927SAndroid Build Coastguard Worker }
232*61046927SAndroid Build Coastguard Worker 
233*61046927SAndroid Build Coastguard Worker static void
set_ext(struct drm_v3d_extension * ext,struct drm_v3d_extension * next,uint32_t id,uintptr_t flags)234*61046927SAndroid Build Coastguard Worker set_ext(struct drm_v3d_extension *ext,
235*61046927SAndroid Build Coastguard Worker 	struct drm_v3d_extension *next,
236*61046927SAndroid Build Coastguard Worker 	uint32_t id,
237*61046927SAndroid Build Coastguard Worker 	uintptr_t flags)
238*61046927SAndroid Build Coastguard Worker {
239*61046927SAndroid Build Coastguard Worker    ext->next = (uintptr_t)(void *)next;
240*61046927SAndroid Build Coastguard Worker    ext->id = id;
241*61046927SAndroid Build Coastguard Worker    ext->flags = flags;
242*61046927SAndroid Build Coastguard Worker }
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker /* This function sets the extension for multiple in/out syncobjs. When it is
245*61046927SAndroid Build Coastguard Worker  * successful, it sets the extension id to DRM_V3D_EXT_ID_MULTI_SYNC.
246*61046927SAndroid Build Coastguard Worker  * Otherwise, the extension id is 0, which means an out-of-memory error.
247*61046927SAndroid Build Coastguard Worker  */
248*61046927SAndroid Build Coastguard Worker static void
set_multisync(struct drm_v3d_multi_sync * ms,struct v3dv_submit_sync_info * sync_info,struct vk_sync_wait * waits,unsigned wait_count,struct drm_v3d_extension * next,struct v3dv_device * device,struct v3dv_job * job,enum v3dv_queue_type in_queue_sync,enum v3dv_queue_type out_queue_sync,enum v3d_queue wait_stage,bool signal_syncs)249*61046927SAndroid Build Coastguard Worker set_multisync(struct drm_v3d_multi_sync *ms,
250*61046927SAndroid Build Coastguard Worker               struct v3dv_submit_sync_info *sync_info,
251*61046927SAndroid Build Coastguard Worker               struct vk_sync_wait *waits,
252*61046927SAndroid Build Coastguard Worker               unsigned wait_count,
253*61046927SAndroid Build Coastguard Worker               struct drm_v3d_extension *next,
254*61046927SAndroid Build Coastguard Worker               struct v3dv_device *device,
255*61046927SAndroid Build Coastguard Worker               struct v3dv_job *job,
256*61046927SAndroid Build Coastguard Worker               enum v3dv_queue_type in_queue_sync,
257*61046927SAndroid Build Coastguard Worker               enum v3dv_queue_type out_queue_sync,
258*61046927SAndroid Build Coastguard Worker               enum v3d_queue wait_stage,
259*61046927SAndroid Build Coastguard Worker               bool signal_syncs)
260*61046927SAndroid Build Coastguard Worker {
261*61046927SAndroid Build Coastguard Worker    struct v3dv_queue *queue = &device->queue;
262*61046927SAndroid Build Coastguard Worker    uint32_t out_sync_count = 0, in_sync_count = 0;
263*61046927SAndroid Build Coastguard Worker    struct drm_v3d_sem *out_syncs = NULL, *in_syncs = NULL;
264*61046927SAndroid Build Coastguard Worker 
265*61046927SAndroid Build Coastguard Worker    in_syncs = set_in_syncs(queue, job, in_queue_sync,
266*61046927SAndroid Build Coastguard Worker                            &in_sync_count, waits, wait_count, sync_info);
267*61046927SAndroid Build Coastguard Worker    if (!in_syncs && in_sync_count)
268*61046927SAndroid Build Coastguard Worker       goto fail;
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker    out_syncs = set_out_syncs(queue, job, out_queue_sync,
271*61046927SAndroid Build Coastguard Worker                              &out_sync_count, sync_info, signal_syncs);
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker    assert(out_sync_count > 0);
274*61046927SAndroid Build Coastguard Worker 
275*61046927SAndroid Build Coastguard Worker    if (!out_syncs)
276*61046927SAndroid Build Coastguard Worker       goto fail;
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker    set_ext(&ms->base, next, DRM_V3D_EXT_ID_MULTI_SYNC, 0);
279*61046927SAndroid Build Coastguard Worker    ms->wait_stage = wait_stage;
280*61046927SAndroid Build Coastguard Worker    ms->out_sync_count = out_sync_count;
281*61046927SAndroid Build Coastguard Worker    ms->out_syncs = (uintptr_t)(void *)out_syncs;
282*61046927SAndroid Build Coastguard Worker    ms->in_sync_count = in_sync_count;
283*61046927SAndroid Build Coastguard Worker    ms->in_syncs = (uintptr_t)(void *)in_syncs;
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker    return;
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker fail:
288*61046927SAndroid Build Coastguard Worker    if (in_syncs)
289*61046927SAndroid Build Coastguard Worker       vk_free(&device->vk.alloc, in_syncs);
290*61046927SAndroid Build Coastguard Worker    assert(!out_syncs);
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker    return;
293*61046927SAndroid Build Coastguard Worker }
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker static VkResult
handle_reset_query_cpu_job(struct v3dv_queue * queue,struct v3dv_job * job,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)296*61046927SAndroid Build Coastguard Worker handle_reset_query_cpu_job(struct v3dv_queue *queue,
297*61046927SAndroid Build Coastguard Worker                            struct v3dv_job *job,
298*61046927SAndroid Build Coastguard Worker                            struct v3dv_submit_sync_info *sync_info,
299*61046927SAndroid Build Coastguard Worker                            bool signal_syncs)
300*61046927SAndroid Build Coastguard Worker {
301*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
302*61046927SAndroid Build Coastguard Worker    struct v3dv_reset_query_cpu_job_info *info = &job->cpu.query_reset;
303*61046927SAndroid Build Coastguard Worker    assert(info->pool);
304*61046927SAndroid Build Coastguard Worker 
305*61046927SAndroid Build Coastguard Worker    assert(info->pool->query_type != VK_QUERY_TYPE_OCCLUSION);
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker    if (device->pdevice->caps.cpu_queue) {
308*61046927SAndroid Build Coastguard Worker       assert(info->first + info->count <= info->pool->query_count);
309*61046927SAndroid Build Coastguard Worker 
310*61046927SAndroid Build Coastguard Worker       struct drm_v3d_submit_cpu submit = {0};
311*61046927SAndroid Build Coastguard Worker       struct drm_v3d_multi_sync ms = {0};
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker       uint32_t *syncs = (uint32_t *) malloc(sizeof(uint32_t) * info->count);
314*61046927SAndroid Build Coastguard Worker       uintptr_t *kperfmon_ids = NULL;
315*61046927SAndroid Build Coastguard Worker 
316*61046927SAndroid Build Coastguard Worker       if (info->pool->query_type == VK_QUERY_TYPE_TIMESTAMP) {
317*61046927SAndroid Build Coastguard Worker          submit.bo_handle_count = 1;
318*61046927SAndroid Build Coastguard Worker          submit.bo_handles = (uintptr_t)(void *)&info->pool->timestamp.bo->handle;
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker          struct drm_v3d_reset_timestamp_query reset = {0};
321*61046927SAndroid Build Coastguard Worker 
322*61046927SAndroid Build Coastguard Worker          set_ext(&reset.base, NULL, DRM_V3D_EXT_ID_CPU_RESET_TIMESTAMP_QUERY, 0);
323*61046927SAndroid Build Coastguard Worker 
324*61046927SAndroid Build Coastguard Worker          reset.count = info->count;
325*61046927SAndroid Build Coastguard Worker          reset.offset = info->pool->queries[info->first].timestamp.offset;
326*61046927SAndroid Build Coastguard Worker 
327*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; i < info->count; i++) {
328*61046927SAndroid Build Coastguard Worker             struct v3dv_query *query = &info->pool->queries[info->first + i];
329*61046927SAndroid Build Coastguard Worker             syncs[i] = vk_sync_as_drm_syncobj(query->timestamp.sync)->syncobj;
330*61046927SAndroid Build Coastguard Worker          }
331*61046927SAndroid Build Coastguard Worker 
332*61046927SAndroid Build Coastguard Worker          reset.syncs = (uintptr_t)(void *)syncs;
333*61046927SAndroid Build Coastguard Worker 
334*61046927SAndroid Build Coastguard Worker          set_multisync(&ms, sync_info, NULL, 0, (void *)&reset, device, job,
335*61046927SAndroid Build Coastguard Worker                        V3DV_QUEUE_CPU, V3DV_QUEUE_CPU, V3D_CPU, signal_syncs);
336*61046927SAndroid Build Coastguard Worker          if (!ms.base.id)
337*61046927SAndroid Build Coastguard Worker             return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
338*61046927SAndroid Build Coastguard Worker       } else {
339*61046927SAndroid Build Coastguard Worker          assert(info->pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
340*61046927SAndroid Build Coastguard Worker          struct drm_v3d_reset_performance_query reset = {0};
341*61046927SAndroid Build Coastguard Worker 
342*61046927SAndroid Build Coastguard Worker          set_ext(&reset.base, NULL, DRM_V3D_EXT_ID_CPU_RESET_PERFORMANCE_QUERY, 0);
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker          struct vk_sync_wait waits[info->count];
345*61046927SAndroid Build Coastguard Worker          unsigned wait_count = 0;
346*61046927SAndroid Build Coastguard Worker          for (int i = 0; i < info->count; i++) {
347*61046927SAndroid Build Coastguard Worker             struct v3dv_query *query = &info->pool->queries[info->first + i];
348*61046927SAndroid Build Coastguard Worker             /* Only wait for a query if we've used it otherwise we will be
349*61046927SAndroid Build Coastguard Worker              * waiting forever for the fence to become signaled.
350*61046927SAndroid Build Coastguard Worker              */
351*61046927SAndroid Build Coastguard Worker             if (query->maybe_available) {
352*61046927SAndroid Build Coastguard Worker                waits[wait_count] = (struct vk_sync_wait){
353*61046927SAndroid Build Coastguard Worker                   .sync = query->perf.last_job_sync
354*61046927SAndroid Build Coastguard Worker                };
355*61046927SAndroid Build Coastguard Worker                wait_count++;
356*61046927SAndroid Build Coastguard Worker             };
357*61046927SAndroid Build Coastguard Worker          }
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker          reset.count = info->count;
360*61046927SAndroid Build Coastguard Worker          reset.nperfmons = info->pool->perfmon.nperfmons;
361*61046927SAndroid Build Coastguard Worker 
362*61046927SAndroid Build Coastguard Worker          kperfmon_ids = (uintptr_t *) malloc(sizeof(uintptr_t) * info->count);
363*61046927SAndroid Build Coastguard Worker 
364*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; i < info->count; i++) {
365*61046927SAndroid Build Coastguard Worker             struct v3dv_query *query = &info->pool->queries[info->first + i];
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker             syncs[i] = vk_sync_as_drm_syncobj(query->perf.last_job_sync)->syncobj;
368*61046927SAndroid Build Coastguard Worker             kperfmon_ids[i] = (uintptr_t)(void *)query->perf.kperfmon_ids;
369*61046927SAndroid Build Coastguard Worker          }
370*61046927SAndroid Build Coastguard Worker 
371*61046927SAndroid Build Coastguard Worker          reset.syncs = (uintptr_t)(void *)syncs;
372*61046927SAndroid Build Coastguard Worker          reset.kperfmon_ids = (uintptr_t)(void *)kperfmon_ids;
373*61046927SAndroid Build Coastguard Worker 
374*61046927SAndroid Build Coastguard Worker          set_multisync(&ms, sync_info, waits, wait_count, (void *)&reset, device, job,
375*61046927SAndroid Build Coastguard Worker                        V3DV_QUEUE_CPU, V3DV_QUEUE_CPU, V3D_CPU, signal_syncs);
376*61046927SAndroid Build Coastguard Worker          if (!ms.base.id)
377*61046927SAndroid Build Coastguard Worker             return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
378*61046927SAndroid Build Coastguard Worker       }
379*61046927SAndroid Build Coastguard Worker 
380*61046927SAndroid Build Coastguard Worker       submit.flags |= DRM_V3D_SUBMIT_EXTENSION;
381*61046927SAndroid Build Coastguard Worker       submit.extensions = (uintptr_t)(void *)&ms;
382*61046927SAndroid Build Coastguard Worker 
383*61046927SAndroid Build Coastguard Worker       /* From the Vulkan spec for vkCmdResetQueryPool:
384*61046927SAndroid Build Coastguard Worker        *
385*61046927SAndroid Build Coastguard Worker        *    "This command defines an execution dependency between other query commands
386*61046927SAndroid Build Coastguard Worker        *     that reference the same query.
387*61046927SAndroid Build Coastguard Worker        *     ...
388*61046927SAndroid Build Coastguard Worker        *     The second synchronization scope includes all commands which reference the
389*61046927SAndroid Build Coastguard Worker        *     queries in queryPool indicated by firstQuery and queryCount that occur later
390*61046927SAndroid Build Coastguard Worker        *     in submission order."
391*61046927SAndroid Build Coastguard Worker        *
392*61046927SAndroid Build Coastguard Worker        * This means we should ensure that any timestamps after a reset don't execute before
393*61046927SAndroid Build Coastguard Worker        * the reset, however, for timestamps queries in particular we don't have to do
394*61046927SAndroid Build Coastguard Worker        * anything special because timestamp queries have to wait for all previously
395*61046927SAndroid Build Coastguard Worker        * submitted work to complete before executing (which we accomplish by using
396*61046927SAndroid Build Coastguard Worker        * V3DV_BARRIER_ALL on them) and that includes reset jobs submitted to the CPU queue.
397*61046927SAndroid Build Coastguard Worker        */
398*61046927SAndroid Build Coastguard Worker       int ret = v3dv_ioctl(device->pdevice->render_fd,
399*61046927SAndroid Build Coastguard Worker                            DRM_IOCTL_V3D_SUBMIT_CPU, &submit);
400*61046927SAndroid Build Coastguard Worker 
401*61046927SAndroid Build Coastguard Worker       free(syncs);
402*61046927SAndroid Build Coastguard Worker       free(kperfmon_ids);
403*61046927SAndroid Build Coastguard Worker       multisync_free(device, &ms);
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker       queue->last_job_syncs.first[V3DV_QUEUE_CPU] = false;
406*61046927SAndroid Build Coastguard Worker 
407*61046927SAndroid Build Coastguard Worker       if (ret)
408*61046927SAndroid Build Coastguard Worker          return vk_queue_set_lost(&queue->vk, "V3D_SUBMIT_CPU failed: %m");
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
411*61046927SAndroid Build Coastguard Worker    }
412*61046927SAndroid Build Coastguard Worker 
413*61046927SAndroid Build Coastguard Worker    /* We are about to reset query counters in user-space so we need to make
414*61046927SAndroid Build Coastguard Worker     * sure that the GPU is not using them.
415*61046927SAndroid Build Coastguard Worker     */
416*61046927SAndroid Build Coastguard Worker    if (info->pool->query_type == VK_QUERY_TYPE_TIMESTAMP) {
417*61046927SAndroid Build Coastguard Worker       VkResult result = queue_wait_idle(queue, sync_info);
418*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
419*61046927SAndroid Build Coastguard Worker          return result;
420*61046927SAndroid Build Coastguard Worker 
421*61046927SAndroid Build Coastguard Worker       v3dv_bo_wait(job->device, info->pool->timestamp.bo, OS_TIMEOUT_INFINITE);
422*61046927SAndroid Build Coastguard Worker    }
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker    if (info->pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR) {
425*61046927SAndroid Build Coastguard Worker       struct vk_sync_wait waits[info->count];
426*61046927SAndroid Build Coastguard Worker       unsigned wait_count = 0;
427*61046927SAndroid Build Coastguard Worker       for (int i = 0; i < info->count; i++) {
428*61046927SAndroid Build Coastguard Worker          struct v3dv_query *query = &info->pool->queries[info->first + i];
429*61046927SAndroid Build Coastguard Worker          /* Only wait for a query if we've used it otherwise we will be
430*61046927SAndroid Build Coastguard Worker           * waiting forever for the fence to become signaled.
431*61046927SAndroid Build Coastguard Worker           */
432*61046927SAndroid Build Coastguard Worker          if (query->maybe_available) {
433*61046927SAndroid Build Coastguard Worker             waits[wait_count] = (struct vk_sync_wait){
434*61046927SAndroid Build Coastguard Worker                .sync = query->perf.last_job_sync
435*61046927SAndroid Build Coastguard Worker             };
436*61046927SAndroid Build Coastguard Worker             wait_count++;
437*61046927SAndroid Build Coastguard Worker          };
438*61046927SAndroid Build Coastguard Worker       }
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker       VkResult result = vk_sync_wait_many(&job->device->vk, wait_count, waits,
441*61046927SAndroid Build Coastguard Worker                                           VK_SYNC_WAIT_COMPLETE, UINT64_MAX);
442*61046927SAndroid Build Coastguard Worker 
443*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
444*61046927SAndroid Build Coastguard Worker          return result;
445*61046927SAndroid Build Coastguard Worker    }
446*61046927SAndroid Build Coastguard Worker 
447*61046927SAndroid Build Coastguard Worker    v3dv_reset_query_pool_cpu(job->device, info->pool, info->first, info->count);
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
450*61046927SAndroid Build Coastguard Worker }
451*61046927SAndroid Build Coastguard Worker 
452*61046927SAndroid Build Coastguard Worker static VkResult
export_perfmon_last_job_sync(struct v3dv_queue * queue,struct v3dv_job * job,int * fd)453*61046927SAndroid Build Coastguard Worker export_perfmon_last_job_sync(struct v3dv_queue *queue, struct v3dv_job *job, int *fd)
454*61046927SAndroid Build Coastguard Worker {
455*61046927SAndroid Build Coastguard Worker    int err;
456*61046927SAndroid Build Coastguard Worker    static const enum v3dv_queue_type queues_to_sync[] = {
457*61046927SAndroid Build Coastguard Worker       V3DV_QUEUE_CL,
458*61046927SAndroid Build Coastguard Worker       V3DV_QUEUE_CSD,
459*61046927SAndroid Build Coastguard Worker    };
460*61046927SAndroid Build Coastguard Worker 
461*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < ARRAY_SIZE(queues_to_sync); i++) {
462*61046927SAndroid Build Coastguard Worker       enum v3dv_queue_type queue_type = queues_to_sync[i];
463*61046927SAndroid Build Coastguard Worker       int tmp_fd = -1;
464*61046927SAndroid Build Coastguard Worker 
465*61046927SAndroid Build Coastguard Worker       err = drmSyncobjExportSyncFile(job->device->pdevice->render_fd,
466*61046927SAndroid Build Coastguard Worker                                      queue->last_job_syncs.syncs[queue_type],
467*61046927SAndroid Build Coastguard Worker                                      &tmp_fd);
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker       if (err) {
470*61046927SAndroid Build Coastguard Worker          close(*fd);
471*61046927SAndroid Build Coastguard Worker          return vk_errorf(&job->device->queue, VK_ERROR_UNKNOWN,
472*61046927SAndroid Build Coastguard Worker                           "sync file export failed: %m");
473*61046927SAndroid Build Coastguard Worker       }
474*61046927SAndroid Build Coastguard Worker 
475*61046927SAndroid Build Coastguard Worker       err = sync_accumulate("v3dv", fd, tmp_fd);
476*61046927SAndroid Build Coastguard Worker 
477*61046927SAndroid Build Coastguard Worker       if (err) {
478*61046927SAndroid Build Coastguard Worker          close(tmp_fd);
479*61046927SAndroid Build Coastguard Worker          close(*fd);
480*61046927SAndroid Build Coastguard Worker          return vk_errorf(&job->device->queue, VK_ERROR_UNKNOWN,
481*61046927SAndroid Build Coastguard Worker                           "failed to accumulate sync files: %m");
482*61046927SAndroid Build Coastguard Worker       }
483*61046927SAndroid Build Coastguard Worker    }
484*61046927SAndroid Build Coastguard Worker 
485*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
486*61046927SAndroid Build Coastguard Worker }
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker static VkResult
handle_end_query_cpu_job(struct v3dv_job * job,uint32_t counter_pass_idx)489*61046927SAndroid Build Coastguard Worker handle_end_query_cpu_job(struct v3dv_job *job, uint32_t counter_pass_idx)
490*61046927SAndroid Build Coastguard Worker {
491*61046927SAndroid Build Coastguard Worker    VkResult result = VK_SUCCESS;
492*61046927SAndroid Build Coastguard Worker 
493*61046927SAndroid Build Coastguard Worker    mtx_lock(&job->device->query_mutex);
494*61046927SAndroid Build Coastguard Worker 
495*61046927SAndroid Build Coastguard Worker    struct v3dv_end_query_info *info = &job->cpu.query_end;
496*61046927SAndroid Build Coastguard Worker    struct v3dv_queue *queue = &job->device->queue;
497*61046927SAndroid Build Coastguard Worker 
498*61046927SAndroid Build Coastguard Worker    int err = 0;
499*61046927SAndroid Build Coastguard Worker    int fd = -1;
500*61046927SAndroid Build Coastguard Worker 
501*61046927SAndroid Build Coastguard Worker    assert(info->pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
502*61046927SAndroid Build Coastguard Worker 
503*61046927SAndroid Build Coastguard Worker    if (info->pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR) {
504*61046927SAndroid Build Coastguard Worker       result = export_perfmon_last_job_sync(queue, job, &fd);
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
507*61046927SAndroid Build Coastguard Worker          goto fail;
508*61046927SAndroid Build Coastguard Worker 
509*61046927SAndroid Build Coastguard Worker       assert(fd >= 0);
510*61046927SAndroid Build Coastguard Worker    }
511*61046927SAndroid Build Coastguard Worker 
512*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < info->count; i++) {
513*61046927SAndroid Build Coastguard Worker       assert(info->query + i < info->pool->query_count);
514*61046927SAndroid Build Coastguard Worker       struct v3dv_query *query = &info->pool->queries[info->query + i];
515*61046927SAndroid Build Coastguard Worker 
516*61046927SAndroid Build Coastguard Worker       if (info->pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR) {
517*61046927SAndroid Build Coastguard Worker          uint32_t syncobj = vk_sync_as_drm_syncobj(query->perf.last_job_sync)->syncobj;
518*61046927SAndroid Build Coastguard Worker          err = drmSyncobjImportSyncFile(job->device->pdevice->render_fd,
519*61046927SAndroid Build Coastguard Worker                                         syncobj, fd);
520*61046927SAndroid Build Coastguard Worker 
521*61046927SAndroid Build Coastguard Worker          if (err) {
522*61046927SAndroid Build Coastguard Worker             result = vk_errorf(queue, VK_ERROR_UNKNOWN,
523*61046927SAndroid Build Coastguard Worker                                "sync file import failed: %m");
524*61046927SAndroid Build Coastguard Worker             goto fail;
525*61046927SAndroid Build Coastguard Worker          }
526*61046927SAndroid Build Coastguard Worker       }
527*61046927SAndroid Build Coastguard Worker 
528*61046927SAndroid Build Coastguard Worker       query->maybe_available = true;
529*61046927SAndroid Build Coastguard Worker    }
530*61046927SAndroid Build Coastguard Worker 
531*61046927SAndroid Build Coastguard Worker fail:
532*61046927SAndroid Build Coastguard Worker    if (info->pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR)
533*61046927SAndroid Build Coastguard Worker       close(fd);
534*61046927SAndroid Build Coastguard Worker 
535*61046927SAndroid Build Coastguard Worker    cnd_broadcast(&job->device->query_ended);
536*61046927SAndroid Build Coastguard Worker    mtx_unlock(&job->device->query_mutex);
537*61046927SAndroid Build Coastguard Worker 
538*61046927SAndroid Build Coastguard Worker    return result;
539*61046927SAndroid Build Coastguard Worker }
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker static VkResult
handle_copy_query_results_cpu_job(struct v3dv_queue * queue,struct v3dv_job * job,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)542*61046927SAndroid Build Coastguard Worker handle_copy_query_results_cpu_job(struct v3dv_queue *queue,
543*61046927SAndroid Build Coastguard Worker                                   struct v3dv_job *job,
544*61046927SAndroid Build Coastguard Worker                                   struct v3dv_submit_sync_info *sync_info,
545*61046927SAndroid Build Coastguard Worker                                   bool signal_syncs)
546*61046927SAndroid Build Coastguard Worker {
547*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
548*61046927SAndroid Build Coastguard Worker    struct v3dv_copy_query_results_cpu_job_info *info =
549*61046927SAndroid Build Coastguard Worker       &job->cpu.query_copy_results;
550*61046927SAndroid Build Coastguard Worker 
551*61046927SAndroid Build Coastguard Worker    assert(info->pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR ||
552*61046927SAndroid Build Coastguard Worker           info->pool->query_type == VK_QUERY_TYPE_TIMESTAMP);
553*61046927SAndroid Build Coastguard Worker 
554*61046927SAndroid Build Coastguard Worker    assert(info->dst && info->dst->mem && info->dst->mem->bo);
555*61046927SAndroid Build Coastguard Worker    struct v3dv_bo *bo = info->dst->mem->bo;
556*61046927SAndroid Build Coastguard Worker 
557*61046927SAndroid Build Coastguard Worker    if (device->pdevice->caps.cpu_queue) {
558*61046927SAndroid Build Coastguard Worker       struct drm_v3d_submit_cpu submit = {0};
559*61046927SAndroid Build Coastguard Worker       struct drm_v3d_multi_sync ms = {0};
560*61046927SAndroid Build Coastguard Worker 
561*61046927SAndroid Build Coastguard Worker       uint32_t *offsets = (uint32_t *) malloc(sizeof(uint32_t) * info->count);
562*61046927SAndroid Build Coastguard Worker       uint32_t *syncs = (uint32_t *) malloc(sizeof(uint32_t) * info->count);
563*61046927SAndroid Build Coastguard Worker       uint32_t *bo_handles = NULL;
564*61046927SAndroid Build Coastguard Worker       uintptr_t *kperfmon_ids = NULL;
565*61046927SAndroid Build Coastguard Worker 
566*61046927SAndroid Build Coastguard Worker       if (info->pool->query_type == VK_QUERY_TYPE_TIMESTAMP) {
567*61046927SAndroid Build Coastguard Worker          submit.bo_handle_count = 2;
568*61046927SAndroid Build Coastguard Worker 
569*61046927SAndroid Build Coastguard Worker          bo_handles = (uint32_t *)
570*61046927SAndroid Build Coastguard Worker             malloc(sizeof(uint32_t) * submit.bo_handle_count);
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker          bo_handles[0] = bo->handle;
573*61046927SAndroid Build Coastguard Worker          bo_handles[1] = info->pool->timestamp.bo->handle;
574*61046927SAndroid Build Coastguard Worker          submit.bo_handles = (uintptr_t)(void *)bo_handles;
575*61046927SAndroid Build Coastguard Worker 
576*61046927SAndroid Build Coastguard Worker          struct drm_v3d_copy_timestamp_query copy = {0};
577*61046927SAndroid Build Coastguard Worker 
578*61046927SAndroid Build Coastguard Worker          set_ext(&copy.base, NULL, DRM_V3D_EXT_ID_CPU_COPY_TIMESTAMP_QUERY, 0);
579*61046927SAndroid Build Coastguard Worker 
580*61046927SAndroid Build Coastguard Worker          copy.do_64bit = info->flags & VK_QUERY_RESULT_64_BIT;
581*61046927SAndroid Build Coastguard Worker          copy.do_partial = info->flags & VK_QUERY_RESULT_PARTIAL_BIT;
582*61046927SAndroid Build Coastguard Worker          copy.availability_bit = info->flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
583*61046927SAndroid Build Coastguard Worker          copy.offset = info->offset + info->dst->mem_offset;
584*61046927SAndroid Build Coastguard Worker          copy.stride = info->stride;
585*61046927SAndroid Build Coastguard Worker          copy.count = info->count;
586*61046927SAndroid Build Coastguard Worker 
587*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; i < info->count; i++) {
588*61046927SAndroid Build Coastguard Worker             assert(info->first < info->pool->query_count);
589*61046927SAndroid Build Coastguard Worker             assert(info->first + info->count <= info->pool->query_count);
590*61046927SAndroid Build Coastguard Worker             struct v3dv_query *query = &info->pool->queries[info->first + i];
591*61046927SAndroid Build Coastguard Worker 
592*61046927SAndroid Build Coastguard Worker             offsets[i] = query->timestamp.offset;
593*61046927SAndroid Build Coastguard Worker             syncs[i] = vk_sync_as_drm_syncobj(query->timestamp.sync)->syncobj;
594*61046927SAndroid Build Coastguard Worker          }
595*61046927SAndroid Build Coastguard Worker 
596*61046927SAndroid Build Coastguard Worker          copy.offsets = (uintptr_t)(void *)offsets;
597*61046927SAndroid Build Coastguard Worker          copy.syncs = (uintptr_t)(void *)syncs;
598*61046927SAndroid Build Coastguard Worker 
599*61046927SAndroid Build Coastguard Worker          set_multisync(&ms, sync_info, NULL, 0, (void *)&copy, device, job,
600*61046927SAndroid Build Coastguard Worker                        V3DV_QUEUE_CPU, V3DV_QUEUE_CPU, V3D_CPU, signal_syncs);
601*61046927SAndroid Build Coastguard Worker          if (!ms.base.id)
602*61046927SAndroid Build Coastguard Worker             return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
603*61046927SAndroid Build Coastguard Worker       } else {
604*61046927SAndroid Build Coastguard Worker          assert(info->pool->query_type == VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR);
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker          submit.bo_handle_count = 1;
607*61046927SAndroid Build Coastguard Worker          submit.bo_handles = (uintptr_t)(void *)&bo->handle;
608*61046927SAndroid Build Coastguard Worker 
609*61046927SAndroid Build Coastguard Worker          struct drm_v3d_copy_performance_query copy = {0};
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker          set_ext(&copy.base, NULL, DRM_V3D_EXT_ID_CPU_COPY_PERFORMANCE_QUERY, 0);
612*61046927SAndroid Build Coastguard Worker 
613*61046927SAndroid Build Coastguard Worker 	 /* If the queryPool was created with VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR,
614*61046927SAndroid Build Coastguard Worker 	  * results for each query are written as an array of the type indicated
615*61046927SAndroid Build Coastguard Worker 	  * by VkPerformanceCounterKHR::storage for the counter being queried.
616*61046927SAndroid Build Coastguard Worker 	  * For v3dv, VkPerformanceCounterKHR::storage is
617*61046927SAndroid Build Coastguard Worker 	  * VK_PERFORMANCE_COUNTER_STORAGE_UINT64_KHR.
618*61046927SAndroid Build Coastguard Worker 	  */
619*61046927SAndroid Build Coastguard Worker          copy.do_64bit = true;
620*61046927SAndroid Build Coastguard Worker          copy.do_partial = info->flags & VK_QUERY_RESULT_PARTIAL_BIT;
621*61046927SAndroid Build Coastguard Worker          copy.availability_bit = info->flags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
622*61046927SAndroid Build Coastguard Worker          copy.offset = info->offset + info->dst->mem_offset;
623*61046927SAndroid Build Coastguard Worker          copy.stride = info->stride;
624*61046927SAndroid Build Coastguard Worker          copy.count = info->count;
625*61046927SAndroid Build Coastguard Worker          copy.nperfmons = info->pool->perfmon.nperfmons;
626*61046927SAndroid Build Coastguard Worker          copy.ncounters = info->pool->perfmon.ncounters;
627*61046927SAndroid Build Coastguard Worker 
628*61046927SAndroid Build Coastguard Worker          kperfmon_ids = (uintptr_t *) malloc(sizeof(uintptr_t) * info->count);
629*61046927SAndroid Build Coastguard Worker 
630*61046927SAndroid Build Coastguard Worker          struct vk_sync_wait waits[info->count];
631*61046927SAndroid Build Coastguard Worker          unsigned wait_count = 0;
632*61046927SAndroid Build Coastguard Worker 
633*61046927SAndroid Build Coastguard Worker          for (uint32_t i = 0; i < info->count; i++) {
634*61046927SAndroid Build Coastguard Worker             assert(info->first < info->pool->query_count);
635*61046927SAndroid Build Coastguard Worker             assert(info->first + info->count <= info->pool->query_count);
636*61046927SAndroid Build Coastguard Worker             struct v3dv_query *query = &info->pool->queries[info->first + i];
637*61046927SAndroid Build Coastguard Worker 
638*61046927SAndroid Build Coastguard Worker             syncs[i] = vk_sync_as_drm_syncobj(query->perf.last_job_sync)->syncobj;
639*61046927SAndroid Build Coastguard Worker             kperfmon_ids[i] = (uintptr_t)(void *)query->perf.kperfmon_ids;
640*61046927SAndroid Build Coastguard Worker 
641*61046927SAndroid Build Coastguard Worker             if (info->flags & VK_QUERY_RESULT_WAIT_BIT) {
642*61046927SAndroid Build Coastguard Worker                 waits[wait_count] = (struct vk_sync_wait){
643*61046927SAndroid Build Coastguard Worker                    .sync = query->perf.last_job_sync
644*61046927SAndroid Build Coastguard Worker                 };
645*61046927SAndroid Build Coastguard Worker                 wait_count++;
646*61046927SAndroid Build Coastguard Worker             }
647*61046927SAndroid Build Coastguard Worker          }
648*61046927SAndroid Build Coastguard Worker 
649*61046927SAndroid Build Coastguard Worker          copy.syncs = (uintptr_t)(void *)syncs;
650*61046927SAndroid Build Coastguard Worker          copy.kperfmon_ids = (uintptr_t)(void *)kperfmon_ids;
651*61046927SAndroid Build Coastguard Worker 
652*61046927SAndroid Build Coastguard Worker          set_multisync(&ms, sync_info, waits, wait_count, (void *)&copy, device, job,
653*61046927SAndroid Build Coastguard Worker                        V3DV_QUEUE_CPU, V3DV_QUEUE_CPU, V3D_CPU, signal_syncs);
654*61046927SAndroid Build Coastguard Worker          if (!ms.base.id)
655*61046927SAndroid Build Coastguard Worker             return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
656*61046927SAndroid Build Coastguard Worker       }
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker       submit.flags |= DRM_V3D_SUBMIT_EXTENSION;
659*61046927SAndroid Build Coastguard Worker       submit.extensions = (uintptr_t)(void *)&ms;
660*61046927SAndroid Build Coastguard Worker 
661*61046927SAndroid Build Coastguard Worker       int ret = v3dv_ioctl(device->pdevice->render_fd,
662*61046927SAndroid Build Coastguard Worker                            DRM_IOCTL_V3D_SUBMIT_CPU, &submit);
663*61046927SAndroid Build Coastguard Worker 
664*61046927SAndroid Build Coastguard Worker       free(kperfmon_ids);
665*61046927SAndroid Build Coastguard Worker       free(bo_handles);
666*61046927SAndroid Build Coastguard Worker       free(offsets);
667*61046927SAndroid Build Coastguard Worker       free(syncs);
668*61046927SAndroid Build Coastguard Worker       multisync_free(device, &ms);
669*61046927SAndroid Build Coastguard Worker 
670*61046927SAndroid Build Coastguard Worker       queue->last_job_syncs.first[V3DV_QUEUE_CPU] = false;
671*61046927SAndroid Build Coastguard Worker 
672*61046927SAndroid Build Coastguard Worker       if (ret)
673*61046927SAndroid Build Coastguard Worker          return vk_queue_set_lost(&queue->vk, "V3D_SUBMIT_CPU failed: %m");
674*61046927SAndroid Build Coastguard Worker 
675*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
676*61046927SAndroid Build Coastguard Worker    }
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker    /* Map the entire dst buffer for the CPU copy if needed */
679*61046927SAndroid Build Coastguard Worker    assert(!bo->map || bo->map_size == bo->size);
680*61046927SAndroid Build Coastguard Worker    if (!bo->map && !v3dv_bo_map(job->device, bo, bo->size))
681*61046927SAndroid Build Coastguard Worker       return vk_error(job->device, VK_ERROR_OUT_OF_HOST_MEMORY);
682*61046927SAndroid Build Coastguard Worker 
683*61046927SAndroid Build Coastguard Worker    uint8_t *offset = ((uint8_t *) bo->map) +
684*61046927SAndroid Build Coastguard Worker                      info->offset + info->dst->mem_offset;
685*61046927SAndroid Build Coastguard Worker    v3dv_get_query_pool_results_cpu(job->device,
686*61046927SAndroid Build Coastguard Worker                                    info->pool,
687*61046927SAndroid Build Coastguard Worker                                    info->first,
688*61046927SAndroid Build Coastguard Worker                                    info->count,
689*61046927SAndroid Build Coastguard Worker                                    offset,
690*61046927SAndroid Build Coastguard Worker                                    info->stride,
691*61046927SAndroid Build Coastguard Worker                                    info->flags);
692*61046927SAndroid Build Coastguard Worker 
693*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
694*61046927SAndroid Build Coastguard Worker }
695*61046927SAndroid Build Coastguard Worker 
696*61046927SAndroid Build Coastguard Worker static VkResult
handle_timestamp_query_cpu_job(struct v3dv_queue * queue,struct v3dv_job * job,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)697*61046927SAndroid Build Coastguard Worker handle_timestamp_query_cpu_job(struct v3dv_queue *queue,
698*61046927SAndroid Build Coastguard Worker                                struct v3dv_job *job,
699*61046927SAndroid Build Coastguard Worker                                struct v3dv_submit_sync_info *sync_info,
700*61046927SAndroid Build Coastguard Worker                                bool signal_syncs)
701*61046927SAndroid Build Coastguard Worker {
702*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
703*61046927SAndroid Build Coastguard Worker 
704*61046927SAndroid Build Coastguard Worker    assert(job->type == V3DV_JOB_TYPE_CPU_TIMESTAMP_QUERY);
705*61046927SAndroid Build Coastguard Worker    struct v3dv_timestamp_query_cpu_job_info *info = &job->cpu.query_timestamp;
706*61046927SAndroid Build Coastguard Worker 
707*61046927SAndroid Build Coastguard Worker    if (!device->pdevice->caps.cpu_queue) {
708*61046927SAndroid Build Coastguard Worker       /* Wait for completion of all work queued before the timestamp query */
709*61046927SAndroid Build Coastguard Worker       VkResult result = queue_wait_idle(queue, sync_info);
710*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
711*61046927SAndroid Build Coastguard Worker          return result;
712*61046927SAndroid Build Coastguard Worker 
713*61046927SAndroid Build Coastguard Worker       mtx_lock(&job->device->query_mutex);
714*61046927SAndroid Build Coastguard Worker 
715*61046927SAndroid Build Coastguard Worker       /* Compute timestamp */
716*61046927SAndroid Build Coastguard Worker       struct timespec t;
717*61046927SAndroid Build Coastguard Worker       clock_gettime(CLOCK_MONOTONIC, &t);
718*61046927SAndroid Build Coastguard Worker 
719*61046927SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < info->count; i++) {
720*61046927SAndroid Build Coastguard Worker          assert(info->query + i < info->pool->query_count);
721*61046927SAndroid Build Coastguard Worker 	 struct v3dv_query *query = &info->pool->queries[info->query + i];
722*61046927SAndroid Build Coastguard Worker          query->maybe_available = true;
723*61046927SAndroid Build Coastguard Worker 
724*61046927SAndroid Build Coastguard Worker          /* Value */
725*61046927SAndroid Build Coastguard Worker          uint8_t *value_addr =
726*61046927SAndroid Build Coastguard Worker             ((uint8_t *) info->pool->timestamp.bo->map) + query->timestamp.offset;
727*61046927SAndroid Build Coastguard Worker          *((uint64_t*)value_addr) = (i == 0) ? t.tv_sec * 1000000000ull + t.tv_nsec : 0ull;
728*61046927SAndroid Build Coastguard Worker 
729*61046927SAndroid Build Coastguard Worker          /* Availability */
730*61046927SAndroid Build Coastguard Worker          result = vk_sync_signal(&job->device->vk, query->timestamp.sync, 0);
731*61046927SAndroid Build Coastguard Worker       }
732*61046927SAndroid Build Coastguard Worker 
733*61046927SAndroid Build Coastguard Worker       cnd_broadcast(&job->device->query_ended);
734*61046927SAndroid Build Coastguard Worker       mtx_unlock(&job->device->query_mutex);
735*61046927SAndroid Build Coastguard Worker 
736*61046927SAndroid Build Coastguard Worker       return result;
737*61046927SAndroid Build Coastguard Worker    }
738*61046927SAndroid Build Coastguard Worker 
739*61046927SAndroid Build Coastguard Worker    struct drm_v3d_submit_cpu submit = {0};
740*61046927SAndroid Build Coastguard Worker 
741*61046927SAndroid Build Coastguard Worker    submit.bo_handle_count = 1;
742*61046927SAndroid Build Coastguard Worker    submit.bo_handles = (uintptr_t)(void *)&info->pool->timestamp.bo->handle;
743*61046927SAndroid Build Coastguard Worker 
744*61046927SAndroid Build Coastguard Worker    struct drm_v3d_timestamp_query timestamp = {0};
745*61046927SAndroid Build Coastguard Worker 
746*61046927SAndroid Build Coastguard Worker    set_ext(&timestamp.base, NULL, DRM_V3D_EXT_ID_CPU_TIMESTAMP_QUERY, 0);
747*61046927SAndroid Build Coastguard Worker 
748*61046927SAndroid Build Coastguard Worker    timestamp.count = info->count;
749*61046927SAndroid Build Coastguard Worker 
750*61046927SAndroid Build Coastguard Worker    uint32_t *offsets =
751*61046927SAndroid Build Coastguard Worker       (uint32_t *) malloc(sizeof(uint32_t) * info->count);
752*61046927SAndroid Build Coastguard Worker    uint32_t *syncs =
753*61046927SAndroid Build Coastguard Worker       (uint32_t *) malloc(sizeof(uint32_t) * info->count);
754*61046927SAndroid Build Coastguard Worker 
755*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < info->count; i++) {
756*61046927SAndroid Build Coastguard Worker       assert(info->query + i < info->pool->query_count);
757*61046927SAndroid Build Coastguard Worker       struct v3dv_query *query = &info->pool->queries[info->query + i];
758*61046927SAndroid Build Coastguard Worker       query->maybe_available = true;
759*61046927SAndroid Build Coastguard Worker 
760*61046927SAndroid Build Coastguard Worker       offsets[i] = query->timestamp.offset;
761*61046927SAndroid Build Coastguard Worker       syncs[i] = vk_sync_as_drm_syncobj(query->timestamp.sync)->syncobj;
762*61046927SAndroid Build Coastguard Worker    }
763*61046927SAndroid Build Coastguard Worker 
764*61046927SAndroid Build Coastguard Worker    timestamp.offsets = (uintptr_t)(void *)offsets;
765*61046927SAndroid Build Coastguard Worker    timestamp.syncs = (uintptr_t)(void *)syncs;
766*61046927SAndroid Build Coastguard Worker 
767*61046927SAndroid Build Coastguard Worker    struct drm_v3d_multi_sync ms = {0};
768*61046927SAndroid Build Coastguard Worker 
769*61046927SAndroid Build Coastguard Worker    /* The CPU job should be serialized so it only executes after all previously
770*61046927SAndroid Build Coastguard Worker     * submitted work has completed
771*61046927SAndroid Build Coastguard Worker     */
772*61046927SAndroid Build Coastguard Worker    job->serialize = V3DV_BARRIER_ALL;
773*61046927SAndroid Build Coastguard Worker 
774*61046927SAndroid Build Coastguard Worker    set_multisync(&ms, sync_info, NULL, 0, (void *)&timestamp, device, job,
775*61046927SAndroid Build Coastguard Worker 	         V3DV_QUEUE_CPU, V3DV_QUEUE_CPU, V3D_CPU, signal_syncs);
776*61046927SAndroid Build Coastguard Worker    if (!ms.base.id)
777*61046927SAndroid Build Coastguard Worker       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
778*61046927SAndroid Build Coastguard Worker 
779*61046927SAndroid Build Coastguard Worker    submit.flags |= DRM_V3D_SUBMIT_EXTENSION;
780*61046927SAndroid Build Coastguard Worker    submit.extensions = (uintptr_t)(void *)&ms;
781*61046927SAndroid Build Coastguard Worker 
782*61046927SAndroid Build Coastguard Worker    int ret = v3dv_ioctl(device->pdevice->render_fd,
783*61046927SAndroid Build Coastguard Worker 			DRM_IOCTL_V3D_SUBMIT_CPU, &submit);
784*61046927SAndroid Build Coastguard Worker 
785*61046927SAndroid Build Coastguard Worker    free(offsets);
786*61046927SAndroid Build Coastguard Worker    free(syncs);
787*61046927SAndroid Build Coastguard Worker    multisync_free(device, &ms);
788*61046927SAndroid Build Coastguard Worker 
789*61046927SAndroid Build Coastguard Worker    queue->last_job_syncs.first[V3DV_QUEUE_CPU] = false;
790*61046927SAndroid Build Coastguard Worker 
791*61046927SAndroid Build Coastguard Worker    if (ret)
792*61046927SAndroid Build Coastguard Worker       return vk_queue_set_lost(&queue->vk, "V3D_SUBMIT_CPU failed: %m");
793*61046927SAndroid Build Coastguard Worker 
794*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
795*61046927SAndroid Build Coastguard Worker }
796*61046927SAndroid Build Coastguard Worker 
797*61046927SAndroid Build Coastguard Worker static VkResult
handle_csd_indirect_cpu_job(struct v3dv_queue * queue,struct v3dv_job * job,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)798*61046927SAndroid Build Coastguard Worker handle_csd_indirect_cpu_job(struct v3dv_queue *queue,
799*61046927SAndroid Build Coastguard Worker                             struct v3dv_job *job,
800*61046927SAndroid Build Coastguard Worker                             struct v3dv_submit_sync_info *sync_info,
801*61046927SAndroid Build Coastguard Worker                             bool signal_syncs)
802*61046927SAndroid Build Coastguard Worker {
803*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
804*61046927SAndroid Build Coastguard Worker 
805*61046927SAndroid Build Coastguard Worker    assert(job->type == V3DV_JOB_TYPE_CPU_CSD_INDIRECT);
806*61046927SAndroid Build Coastguard Worker    struct v3dv_csd_indirect_cpu_job_info *info = &job->cpu.csd_indirect;
807*61046927SAndroid Build Coastguard Worker    assert(info->csd_job);
808*61046927SAndroid Build Coastguard Worker 
809*61046927SAndroid Build Coastguard Worker    assert(info->buffer && info->buffer->mem && info->buffer->mem->bo);
810*61046927SAndroid Build Coastguard Worker    struct v3dv_bo *bo = info->buffer->mem->bo;
811*61046927SAndroid Build Coastguard Worker 
812*61046927SAndroid Build Coastguard Worker    if (!device->pdevice->caps.cpu_queue) {
813*61046927SAndroid Build Coastguard Worker       /* Make sure the GPU is no longer using the indirect buffer*/
814*61046927SAndroid Build Coastguard Worker       v3dv_bo_wait(queue->device, bo, OS_TIMEOUT_INFINITE);
815*61046927SAndroid Build Coastguard Worker 
816*61046927SAndroid Build Coastguard Worker       /* Map the indirect buffer and read the dispatch parameters */
817*61046927SAndroid Build Coastguard Worker       if (!bo->map && !v3dv_bo_map(job->device, bo, bo->size))
818*61046927SAndroid Build Coastguard Worker          return vk_error(job->device, VK_ERROR_OUT_OF_HOST_MEMORY);
819*61046927SAndroid Build Coastguard Worker       assert(bo->map);
820*61046927SAndroid Build Coastguard Worker 
821*61046927SAndroid Build Coastguard Worker       const uint32_t offset = info->buffer->mem_offset + info->offset;
822*61046927SAndroid Build Coastguard Worker       const uint32_t *group_counts = (uint32_t *) (bo->map + offset);
823*61046927SAndroid Build Coastguard Worker       if (group_counts[0] == 0 || group_counts[1] == 0|| group_counts[2] == 0)
824*61046927SAndroid Build Coastguard Worker          return VK_SUCCESS;
825*61046927SAndroid Build Coastguard Worker 
826*61046927SAndroid Build Coastguard Worker       if (memcmp(group_counts, info->csd_job->csd.wg_count,
827*61046927SAndroid Build Coastguard Worker 		 sizeof(info->csd_job->csd.wg_count)) != 0) {
828*61046927SAndroid Build Coastguard Worker          v3dv_cmd_buffer_rewrite_indirect_csd_job(queue->device, info, group_counts);
829*61046927SAndroid Build Coastguard Worker       }
830*61046927SAndroid Build Coastguard Worker 
831*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
832*61046927SAndroid Build Coastguard Worker    }
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker    struct v3dv_job *csd_job = info->csd_job;
835*61046927SAndroid Build Coastguard Worker 
836*61046927SAndroid Build Coastguard Worker    struct drm_v3d_submit_cpu submit = {0};
837*61046927SAndroid Build Coastguard Worker 
838*61046927SAndroid Build Coastguard Worker    submit.bo_handle_count = 1;
839*61046927SAndroid Build Coastguard Worker    submit.bo_handles = (uintptr_t)(void *)&bo->handle;
840*61046927SAndroid Build Coastguard Worker 
841*61046927SAndroid Build Coastguard Worker    csd_job->csd.submit.bo_handle_count = csd_job->bo_count;
842*61046927SAndroid Build Coastguard Worker    uint32_t *bo_handles = (uint32_t *) malloc(sizeof(uint32_t) * csd_job->bo_count);
843*61046927SAndroid Build Coastguard Worker    uint32_t bo_idx = 0;
844*61046927SAndroid Build Coastguard Worker    set_foreach (csd_job->bos, entry) {
845*61046927SAndroid Build Coastguard Worker       struct v3dv_bo *bo = (struct v3dv_bo *)entry->key;
846*61046927SAndroid Build Coastguard Worker       bo_handles[bo_idx++] = bo->handle;
847*61046927SAndroid Build Coastguard Worker    }
848*61046927SAndroid Build Coastguard Worker    csd_job->csd.submit.bo_handles = (uintptr_t)(void *)bo_handles;
849*61046927SAndroid Build Coastguard Worker 
850*61046927SAndroid Build Coastguard Worker    struct drm_v3d_indirect_csd indirect = {0};
851*61046927SAndroid Build Coastguard Worker 
852*61046927SAndroid Build Coastguard Worker    set_ext(&indirect.base, NULL, DRM_V3D_EXT_ID_CPU_INDIRECT_CSD, 0);
853*61046927SAndroid Build Coastguard Worker 
854*61046927SAndroid Build Coastguard Worker    indirect.submit = csd_job->csd.submit;
855*61046927SAndroid Build Coastguard Worker    indirect.offset = info->buffer->mem_offset + info->offset;
856*61046927SAndroid Build Coastguard Worker    indirect.wg_size = info->wg_size;
857*61046927SAndroid Build Coastguard Worker 
858*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < 3; i++) {
859*61046927SAndroid Build Coastguard Worker       if (info->wg_uniform_offsets[i]) {
860*61046927SAndroid Build Coastguard Worker          assert(info->wg_uniform_offsets[i] >= (uint32_t *) csd_job->indirect.base);
861*61046927SAndroid Build Coastguard Worker          indirect.wg_uniform_offsets[i] = info->wg_uniform_offsets[i] - (uint32_t *) csd_job->indirect.base;
862*61046927SAndroid Build Coastguard Worker       } else {
863*61046927SAndroid Build Coastguard Worker          indirect.wg_uniform_offsets[i] = 0xffffffff; /* No rewrite */
864*61046927SAndroid Build Coastguard Worker       }
865*61046927SAndroid Build Coastguard Worker    }
866*61046927SAndroid Build Coastguard Worker 
867*61046927SAndroid Build Coastguard Worker    indirect.indirect = csd_job->indirect.bo->handle;
868*61046927SAndroid Build Coastguard Worker 
869*61046927SAndroid Build Coastguard Worker    struct drm_v3d_multi_sync ms = {0};
870*61046927SAndroid Build Coastguard Worker 
871*61046927SAndroid Build Coastguard Worker    /* We need to configure the semaphores of this job with the indirect
872*61046927SAndroid Build Coastguard Worker     * CSD job, as the CPU job must obey to the CSD job synchronization
873*61046927SAndroid Build Coastguard Worker     * demands, such as barriers.
874*61046927SAndroid Build Coastguard Worker     */
875*61046927SAndroid Build Coastguard Worker    set_multisync(&ms, sync_info, NULL, 0, (void *)&indirect, device, csd_job,
876*61046927SAndroid Build Coastguard Worker 	         V3DV_QUEUE_CPU, V3DV_QUEUE_CSD, V3D_CPU, signal_syncs);
877*61046927SAndroid Build Coastguard Worker    if (!ms.base.id)
878*61046927SAndroid Build Coastguard Worker       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
879*61046927SAndroid Build Coastguard Worker 
880*61046927SAndroid Build Coastguard Worker    submit.flags |= DRM_V3D_SUBMIT_EXTENSION;
881*61046927SAndroid Build Coastguard Worker    submit.extensions = (uintptr_t)(void *)&ms;
882*61046927SAndroid Build Coastguard Worker 
883*61046927SAndroid Build Coastguard Worker    int ret = v3dv_ioctl(device->pdevice->render_fd,
884*61046927SAndroid Build Coastguard Worker 			DRM_IOCTL_V3D_SUBMIT_CPU, &submit);
885*61046927SAndroid Build Coastguard Worker 
886*61046927SAndroid Build Coastguard Worker    free(bo_handles);
887*61046927SAndroid Build Coastguard Worker    multisync_free(device, &ms);
888*61046927SAndroid Build Coastguard Worker 
889*61046927SAndroid Build Coastguard Worker    queue->last_job_syncs.first[V3DV_QUEUE_CPU] = false;
890*61046927SAndroid Build Coastguard Worker    queue->last_job_syncs.first[V3DV_QUEUE_CSD] = false;
891*61046927SAndroid Build Coastguard Worker 
892*61046927SAndroid Build Coastguard Worker    if (ret)
893*61046927SAndroid Build Coastguard Worker       return vk_queue_set_lost(&queue->vk, "V3D_SUBMIT_CPU failed: %m");
894*61046927SAndroid Build Coastguard Worker 
895*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
896*61046927SAndroid Build Coastguard Worker }
897*61046927SAndroid Build Coastguard Worker 
898*61046927SAndroid Build Coastguard Worker static VkResult
handle_cl_job(struct v3dv_queue * queue,struct v3dv_job * job,uint32_t counter_pass_idx,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)899*61046927SAndroid Build Coastguard Worker handle_cl_job(struct v3dv_queue *queue,
900*61046927SAndroid Build Coastguard Worker               struct v3dv_job *job,
901*61046927SAndroid Build Coastguard Worker               uint32_t counter_pass_idx,
902*61046927SAndroid Build Coastguard Worker               struct v3dv_submit_sync_info *sync_info,
903*61046927SAndroid Build Coastguard Worker               bool signal_syncs)
904*61046927SAndroid Build Coastguard Worker {
905*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
906*61046927SAndroid Build Coastguard Worker 
907*61046927SAndroid Build Coastguard Worker    struct drm_v3d_submit_cl submit = { 0 };
908*61046927SAndroid Build Coastguard Worker 
909*61046927SAndroid Build Coastguard Worker    /* Sanity check: we should only flag a bcl sync on a job that needs to be
910*61046927SAndroid Build Coastguard Worker     * serialized.
911*61046927SAndroid Build Coastguard Worker     */
912*61046927SAndroid Build Coastguard Worker    assert(job->serialize || !job->needs_bcl_sync);
913*61046927SAndroid Build Coastguard Worker 
914*61046927SAndroid Build Coastguard Worker    /* We expect to have just one RCL per job which should fit in just one BO.
915*61046927SAndroid Build Coastguard Worker     * Our BCL, could chain multiple BOS together though.
916*61046927SAndroid Build Coastguard Worker     */
917*61046927SAndroid Build Coastguard Worker    assert(list_length(&job->rcl.bo_list) == 1);
918*61046927SAndroid Build Coastguard Worker    assert(list_length(&job->bcl.bo_list) >= 1);
919*61046927SAndroid Build Coastguard Worker    struct v3dv_bo *bcl_fist_bo =
920*61046927SAndroid Build Coastguard Worker       list_first_entry(&job->bcl.bo_list, struct v3dv_bo, list_link);
921*61046927SAndroid Build Coastguard Worker    submit.bcl_start = bcl_fist_bo->offset;
922*61046927SAndroid Build Coastguard Worker    submit.bcl_end = job->suspending ? job->suspended_bcl_end :
923*61046927SAndroid Build Coastguard Worker                                       job->bcl.bo->offset + v3dv_cl_offset(&job->bcl);
924*61046927SAndroid Build Coastguard Worker    submit.rcl_start = job->rcl.bo->offset;
925*61046927SAndroid Build Coastguard Worker    submit.rcl_end = job->rcl.bo->offset + v3dv_cl_offset(&job->rcl);
926*61046927SAndroid Build Coastguard Worker 
927*61046927SAndroid Build Coastguard Worker    submit.qma = job->tile_alloc->offset;
928*61046927SAndroid Build Coastguard Worker    submit.qms = job->tile_alloc->size;
929*61046927SAndroid Build Coastguard Worker    submit.qts = job->tile_state->offset;
930*61046927SAndroid Build Coastguard Worker 
931*61046927SAndroid Build Coastguard Worker    submit.flags = 0;
932*61046927SAndroid Build Coastguard Worker    if (job->tmu_dirty_rcl)
933*61046927SAndroid Build Coastguard Worker       submit.flags |= DRM_V3D_SUBMIT_CL_FLUSH_CACHE;
934*61046927SAndroid Build Coastguard Worker 
935*61046927SAndroid Build Coastguard Worker    /* If the job uses VK_KHR_buffer_device_address we need to ensure all
936*61046927SAndroid Build Coastguard Worker     * buffers flagged with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
937*61046927SAndroid Build Coastguard Worker     * are included.
938*61046927SAndroid Build Coastguard Worker     */
939*61046927SAndroid Build Coastguard Worker    if (job->uses_buffer_device_address) {
940*61046927SAndroid Build Coastguard Worker       util_dynarray_foreach(&queue->device->device_address_bo_list,
941*61046927SAndroid Build Coastguard Worker                             struct v3dv_bo *, bo) {
942*61046927SAndroid Build Coastguard Worker          v3dv_job_add_bo(job, *bo);
943*61046927SAndroid Build Coastguard Worker       }
944*61046927SAndroid Build Coastguard Worker    }
945*61046927SAndroid Build Coastguard Worker 
946*61046927SAndroid Build Coastguard Worker    submit.bo_handle_count = job->bo_count;
947*61046927SAndroid Build Coastguard Worker    uint32_t *bo_handles =
948*61046927SAndroid Build Coastguard Worker       (uint32_t *) malloc(sizeof(uint32_t) * submit.bo_handle_count);
949*61046927SAndroid Build Coastguard Worker    uint32_t bo_idx = 0;
950*61046927SAndroid Build Coastguard Worker    set_foreach(job->bos, entry) {
951*61046927SAndroid Build Coastguard Worker       struct v3dv_bo *bo = (struct v3dv_bo *)entry->key;
952*61046927SAndroid Build Coastguard Worker       bo_handles[bo_idx++] = bo->handle;
953*61046927SAndroid Build Coastguard Worker    }
954*61046927SAndroid Build Coastguard Worker    assert(bo_idx == submit.bo_handle_count);
955*61046927SAndroid Build Coastguard Worker    submit.bo_handles = (uintptr_t)(void *)bo_handles;
956*61046927SAndroid Build Coastguard Worker 
957*61046927SAndroid Build Coastguard Worker    submit.perfmon_id = job->perf ?
958*61046927SAndroid Build Coastguard Worker       job->perf->kperfmon_ids[counter_pass_idx] : 0;
959*61046927SAndroid Build Coastguard Worker    const bool needs_perf_sync = queue->last_perfmon_id != submit.perfmon_id;
960*61046927SAndroid Build Coastguard Worker    queue->last_perfmon_id = submit.perfmon_id;
961*61046927SAndroid Build Coastguard Worker 
962*61046927SAndroid Build Coastguard Worker    /* We need a binning sync if we are the first CL job waiting on a semaphore
963*61046927SAndroid Build Coastguard Worker     * with a wait stage that involves the geometry pipeline, or if the job
964*61046927SAndroid Build Coastguard Worker     * comes after a pipeline barrier that involves geometry stages
965*61046927SAndroid Build Coastguard Worker     * (needs_bcl_sync) or when performance queries are in use.
966*61046927SAndroid Build Coastguard Worker     *
967*61046927SAndroid Build Coastguard Worker     * We need a render sync if the job doesn't need a binning sync but has
968*61046927SAndroid Build Coastguard Worker     * still been flagged for serialization. It should be noted that RCL jobs
969*61046927SAndroid Build Coastguard Worker     * don't start until the previous RCL job has finished so we don't really
970*61046927SAndroid Build Coastguard Worker     * need to add a fence for those, however, we might need to wait on a CSD or
971*61046927SAndroid Build Coastguard Worker     * TFU job, which are not automatically serialized with CL jobs.
972*61046927SAndroid Build Coastguard Worker     */
973*61046927SAndroid Build Coastguard Worker    bool needs_bcl_sync = job->needs_bcl_sync || needs_perf_sync;
974*61046927SAndroid Build Coastguard Worker    if (queue->last_job_syncs.first[V3DV_QUEUE_CL]) {
975*61046927SAndroid Build Coastguard Worker       for (int i = 0; !needs_bcl_sync && i < sync_info->wait_count; i++) {
976*61046927SAndroid Build Coastguard Worker          needs_bcl_sync = sync_info->waits[i].stage_mask &
977*61046927SAndroid Build Coastguard Worker              (VK_PIPELINE_STAGE_2_TOP_OF_PIPE_BIT |
978*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT |
979*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT |
980*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_DRAW_INDIRECT_BIT |
981*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_INDEX_INPUT_BIT |
982*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_VERTEX_INPUT_BIT |
983*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_VERTEX_ATTRIBUTE_INPUT_BIT |
984*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_VERTEX_SHADER_BIT |
985*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_TESSELLATION_CONTROL_SHADER_BIT |
986*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_TESSELLATION_EVALUATION_SHADER_BIT |
987*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_GEOMETRY_SHADER_BIT |
988*61046927SAndroid Build Coastguard Worker               VK_PIPELINE_STAGE_2_PRE_RASTERIZATION_SHADERS_BIT);
989*61046927SAndroid Build Coastguard Worker       }
990*61046927SAndroid Build Coastguard Worker    }
991*61046927SAndroid Build Coastguard Worker 
992*61046927SAndroid Build Coastguard Worker    bool needs_rcl_sync = job->serialize && !needs_bcl_sync;
993*61046927SAndroid Build Coastguard Worker 
994*61046927SAndroid Build Coastguard Worker    /* Replace single semaphore settings whenever our kernel-driver supports
995*61046927SAndroid Build Coastguard Worker     * multiple semaphores extension.
996*61046927SAndroid Build Coastguard Worker     */
997*61046927SAndroid Build Coastguard Worker    struct drm_v3d_multi_sync ms = { 0 };
998*61046927SAndroid Build Coastguard Worker    enum v3d_queue wait_stage = needs_rcl_sync ? V3D_RENDER : V3D_BIN;
999*61046927SAndroid Build Coastguard Worker    set_multisync(&ms, sync_info, NULL, 0, NULL, device, job,
1000*61046927SAndroid Build Coastguard Worker                  V3DV_QUEUE_CL, V3DV_QUEUE_CL, wait_stage, signal_syncs);
1001*61046927SAndroid Build Coastguard Worker    if (!ms.base.id)
1002*61046927SAndroid Build Coastguard Worker       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1003*61046927SAndroid Build Coastguard Worker 
1004*61046927SAndroid Build Coastguard Worker    submit.flags |= DRM_V3D_SUBMIT_EXTENSION;
1005*61046927SAndroid Build Coastguard Worker    submit.extensions = (uintptr_t)(void *)&ms;
1006*61046927SAndroid Build Coastguard Worker 
1007*61046927SAndroid Build Coastguard Worker    /* We are using multisync so disable legacy single-sync interface */
1008*61046927SAndroid Build Coastguard Worker    submit.in_sync_rcl = 0;
1009*61046927SAndroid Build Coastguard Worker    submit.in_sync_bcl = 0;
1010*61046927SAndroid Build Coastguard Worker    submit.out_sync = 0;
1011*61046927SAndroid Build Coastguard Worker 
1012*61046927SAndroid Build Coastguard Worker    v3dv_clif_dump(device, job, &submit);
1013*61046927SAndroid Build Coastguard Worker    int ret = v3dv_ioctl(device->pdevice->render_fd,
1014*61046927SAndroid Build Coastguard Worker                         DRM_IOCTL_V3D_SUBMIT_CL, &submit);
1015*61046927SAndroid Build Coastguard Worker 
1016*61046927SAndroid Build Coastguard Worker    static bool warned = false;
1017*61046927SAndroid Build Coastguard Worker    if (ret && !warned) {
1018*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Draw call returned %s. Expect corruption.\n",
1019*61046927SAndroid Build Coastguard Worker               strerror(errno));
1020*61046927SAndroid Build Coastguard Worker       warned = true;
1021*61046927SAndroid Build Coastguard Worker    }
1022*61046927SAndroid Build Coastguard Worker 
1023*61046927SAndroid Build Coastguard Worker    free(bo_handles);
1024*61046927SAndroid Build Coastguard Worker    multisync_free(device, &ms);
1025*61046927SAndroid Build Coastguard Worker 
1026*61046927SAndroid Build Coastguard Worker    queue->last_job_syncs.first[V3DV_QUEUE_CL] = false;
1027*61046927SAndroid Build Coastguard Worker 
1028*61046927SAndroid Build Coastguard Worker    if (ret)
1029*61046927SAndroid Build Coastguard Worker       return vk_queue_set_lost(&queue->vk, "V3D_SUBMIT_CL failed: %m");
1030*61046927SAndroid Build Coastguard Worker 
1031*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1032*61046927SAndroid Build Coastguard Worker }
1033*61046927SAndroid Build Coastguard Worker 
1034*61046927SAndroid Build Coastguard Worker static VkResult
handle_tfu_job(struct v3dv_queue * queue,struct v3dv_job * job,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)1035*61046927SAndroid Build Coastguard Worker handle_tfu_job(struct v3dv_queue *queue,
1036*61046927SAndroid Build Coastguard Worker                struct v3dv_job *job,
1037*61046927SAndroid Build Coastguard Worker                struct v3dv_submit_sync_info *sync_info,
1038*61046927SAndroid Build Coastguard Worker                bool signal_syncs)
1039*61046927SAndroid Build Coastguard Worker {
1040*61046927SAndroid Build Coastguard Worker    assert(!V3D_DBG(DISABLE_TFU));
1041*61046927SAndroid Build Coastguard Worker 
1042*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
1043*61046927SAndroid Build Coastguard Worker 
1044*61046927SAndroid Build Coastguard Worker    /* Replace single semaphore settings whenever our kernel-driver supports
1045*61046927SAndroid Build Coastguard Worker     * multiple semaphore extension.
1046*61046927SAndroid Build Coastguard Worker     */
1047*61046927SAndroid Build Coastguard Worker    struct drm_v3d_multi_sync ms = { 0 };
1048*61046927SAndroid Build Coastguard Worker    set_multisync(&ms, sync_info, NULL, 0, NULL, device, job,
1049*61046927SAndroid Build Coastguard Worker                  V3DV_QUEUE_TFU, V3DV_QUEUE_TFU, V3D_TFU, signal_syncs);
1050*61046927SAndroid Build Coastguard Worker    if (!ms.base.id)
1051*61046927SAndroid Build Coastguard Worker       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1052*61046927SAndroid Build Coastguard Worker 
1053*61046927SAndroid Build Coastguard Worker    job->tfu.flags |= DRM_V3D_SUBMIT_EXTENSION;
1054*61046927SAndroid Build Coastguard Worker    job->tfu.extensions = (uintptr_t)(void *)&ms;
1055*61046927SAndroid Build Coastguard Worker 
1056*61046927SAndroid Build Coastguard Worker    /* We are using multisync so disable legacy single-sync interface */
1057*61046927SAndroid Build Coastguard Worker    job->tfu.in_sync = 0;
1058*61046927SAndroid Build Coastguard Worker    job->tfu.out_sync = 0;
1059*61046927SAndroid Build Coastguard Worker 
1060*61046927SAndroid Build Coastguard Worker    int ret = v3dv_ioctl(device->pdevice->render_fd,
1061*61046927SAndroid Build Coastguard Worker                         DRM_IOCTL_V3D_SUBMIT_TFU, &job->tfu);
1062*61046927SAndroid Build Coastguard Worker 
1063*61046927SAndroid Build Coastguard Worker    multisync_free(device, &ms);
1064*61046927SAndroid Build Coastguard Worker    queue->last_job_syncs.first[V3DV_QUEUE_TFU] = false;
1065*61046927SAndroid Build Coastguard Worker 
1066*61046927SAndroid Build Coastguard Worker    if (ret != 0)
1067*61046927SAndroid Build Coastguard Worker       return vk_queue_set_lost(&queue->vk, "V3D_SUBMIT_TFU failed: %m");
1068*61046927SAndroid Build Coastguard Worker 
1069*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1070*61046927SAndroid Build Coastguard Worker }
1071*61046927SAndroid Build Coastguard Worker 
1072*61046927SAndroid Build Coastguard Worker static VkResult
handle_csd_job(struct v3dv_queue * queue,struct v3dv_job * job,uint32_t counter_pass_idx,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)1073*61046927SAndroid Build Coastguard Worker handle_csd_job(struct v3dv_queue *queue,
1074*61046927SAndroid Build Coastguard Worker                struct v3dv_job *job,
1075*61046927SAndroid Build Coastguard Worker                uint32_t counter_pass_idx,
1076*61046927SAndroid Build Coastguard Worker                struct v3dv_submit_sync_info *sync_info,
1077*61046927SAndroid Build Coastguard Worker                bool signal_syncs)
1078*61046927SAndroid Build Coastguard Worker {
1079*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
1080*61046927SAndroid Build Coastguard Worker 
1081*61046927SAndroid Build Coastguard Worker    struct drm_v3d_submit_csd *submit = &job->csd.submit;
1082*61046927SAndroid Build Coastguard Worker 
1083*61046927SAndroid Build Coastguard Worker    /* If the job uses VK_KHR_buffer_device_address we need to ensure all
1084*61046927SAndroid Build Coastguard Worker     * buffers flagged with VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT
1085*61046927SAndroid Build Coastguard Worker     * are included.
1086*61046927SAndroid Build Coastguard Worker     */
1087*61046927SAndroid Build Coastguard Worker    if (job->uses_buffer_device_address) {
1088*61046927SAndroid Build Coastguard Worker       util_dynarray_foreach(&queue->device->device_address_bo_list,
1089*61046927SAndroid Build Coastguard Worker                             struct v3dv_bo *, bo) {
1090*61046927SAndroid Build Coastguard Worker          v3dv_job_add_bo(job, *bo);
1091*61046927SAndroid Build Coastguard Worker       }
1092*61046927SAndroid Build Coastguard Worker    }
1093*61046927SAndroid Build Coastguard Worker 
1094*61046927SAndroid Build Coastguard Worker    submit->bo_handle_count = job->bo_count;
1095*61046927SAndroid Build Coastguard Worker    uint32_t *bo_handles =
1096*61046927SAndroid Build Coastguard Worker       (uint32_t *) malloc(sizeof(uint32_t) * MAX2(4, submit->bo_handle_count * 2));
1097*61046927SAndroid Build Coastguard Worker    uint32_t bo_idx = 0;
1098*61046927SAndroid Build Coastguard Worker    set_foreach(job->bos, entry) {
1099*61046927SAndroid Build Coastguard Worker       struct v3dv_bo *bo = (struct v3dv_bo *)entry->key;
1100*61046927SAndroid Build Coastguard Worker       bo_handles[bo_idx++] = bo->handle;
1101*61046927SAndroid Build Coastguard Worker    }
1102*61046927SAndroid Build Coastguard Worker    assert(bo_idx == submit->bo_handle_count);
1103*61046927SAndroid Build Coastguard Worker    submit->bo_handles = (uintptr_t)(void *)bo_handles;
1104*61046927SAndroid Build Coastguard Worker 
1105*61046927SAndroid Build Coastguard Worker    /* Replace single semaphore settings whenever our kernel-driver supports
1106*61046927SAndroid Build Coastguard Worker     * multiple semaphore extension.
1107*61046927SAndroid Build Coastguard Worker     */
1108*61046927SAndroid Build Coastguard Worker    struct drm_v3d_multi_sync ms = { 0 };
1109*61046927SAndroid Build Coastguard Worker    set_multisync(&ms, sync_info, NULL, 0, NULL, device, job,
1110*61046927SAndroid Build Coastguard Worker                  V3DV_QUEUE_CSD, V3DV_QUEUE_CSD, V3D_CSD, signal_syncs);
1111*61046927SAndroid Build Coastguard Worker    if (!ms.base.id)
1112*61046927SAndroid Build Coastguard Worker       return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1113*61046927SAndroid Build Coastguard Worker 
1114*61046927SAndroid Build Coastguard Worker    submit->flags |= DRM_V3D_SUBMIT_EXTENSION;
1115*61046927SAndroid Build Coastguard Worker    submit->extensions = (uintptr_t)(void *)&ms;
1116*61046927SAndroid Build Coastguard Worker 
1117*61046927SAndroid Build Coastguard Worker    /* We are using multisync so disable legacy single-sync interface */
1118*61046927SAndroid Build Coastguard Worker    submit->in_sync = 0;
1119*61046927SAndroid Build Coastguard Worker    submit->out_sync = 0;
1120*61046927SAndroid Build Coastguard Worker 
1121*61046927SAndroid Build Coastguard Worker    submit->perfmon_id = job->perf ?
1122*61046927SAndroid Build Coastguard Worker       job->perf->kperfmon_ids[counter_pass_idx] : 0;
1123*61046927SAndroid Build Coastguard Worker    queue->last_perfmon_id = submit->perfmon_id;
1124*61046927SAndroid Build Coastguard Worker 
1125*61046927SAndroid Build Coastguard Worker    int ret = v3dv_ioctl(device->pdevice->render_fd,
1126*61046927SAndroid Build Coastguard Worker                         DRM_IOCTL_V3D_SUBMIT_CSD, submit);
1127*61046927SAndroid Build Coastguard Worker 
1128*61046927SAndroid Build Coastguard Worker    static bool warned = false;
1129*61046927SAndroid Build Coastguard Worker    if (ret && !warned) {
1130*61046927SAndroid Build Coastguard Worker       fprintf(stderr, "Compute dispatch returned %s. Expect corruption.\n",
1131*61046927SAndroid Build Coastguard Worker               strerror(errno));
1132*61046927SAndroid Build Coastguard Worker       warned = true;
1133*61046927SAndroid Build Coastguard Worker    }
1134*61046927SAndroid Build Coastguard Worker 
1135*61046927SAndroid Build Coastguard Worker    free(bo_handles);
1136*61046927SAndroid Build Coastguard Worker 
1137*61046927SAndroid Build Coastguard Worker    multisync_free(device, &ms);
1138*61046927SAndroid Build Coastguard Worker    queue->last_job_syncs.first[V3DV_QUEUE_CSD] = false;
1139*61046927SAndroid Build Coastguard Worker 
1140*61046927SAndroid Build Coastguard Worker    if (ret)
1141*61046927SAndroid Build Coastguard Worker       return vk_queue_set_lost(&queue->vk, "V3D_SUBMIT_CSD failed: %m");
1142*61046927SAndroid Build Coastguard Worker 
1143*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1144*61046927SAndroid Build Coastguard Worker }
1145*61046927SAndroid Build Coastguard Worker 
1146*61046927SAndroid Build Coastguard Worker static VkResult
queue_handle_job(struct v3dv_queue * queue,struct v3dv_job * job,uint32_t counter_pass_idx,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)1147*61046927SAndroid Build Coastguard Worker queue_handle_job(struct v3dv_queue *queue,
1148*61046927SAndroid Build Coastguard Worker                  struct v3dv_job *job,
1149*61046927SAndroid Build Coastguard Worker                  uint32_t counter_pass_idx,
1150*61046927SAndroid Build Coastguard Worker                  struct v3dv_submit_sync_info *sync_info,
1151*61046927SAndroid Build Coastguard Worker                  bool signal_syncs)
1152*61046927SAndroid Build Coastguard Worker {
1153*61046927SAndroid Build Coastguard Worker    switch (job->type) {
1154*61046927SAndroid Build Coastguard Worker    case V3DV_JOB_TYPE_GPU_CL:
1155*61046927SAndroid Build Coastguard Worker       return handle_cl_job(queue, job, counter_pass_idx, sync_info, signal_syncs);
1156*61046927SAndroid Build Coastguard Worker    case V3DV_JOB_TYPE_GPU_TFU:
1157*61046927SAndroid Build Coastguard Worker       return handle_tfu_job(queue, job, sync_info, signal_syncs);
1158*61046927SAndroid Build Coastguard Worker    case V3DV_JOB_TYPE_GPU_CSD:
1159*61046927SAndroid Build Coastguard Worker       return handle_csd_job(queue, job, counter_pass_idx, sync_info, signal_syncs);
1160*61046927SAndroid Build Coastguard Worker    case V3DV_JOB_TYPE_CPU_RESET_QUERIES:
1161*61046927SAndroid Build Coastguard Worker       return handle_reset_query_cpu_job(queue, job, sync_info, signal_syncs);
1162*61046927SAndroid Build Coastguard Worker    case V3DV_JOB_TYPE_CPU_END_QUERY:
1163*61046927SAndroid Build Coastguard Worker       return handle_end_query_cpu_job(job, counter_pass_idx);
1164*61046927SAndroid Build Coastguard Worker    case V3DV_JOB_TYPE_CPU_COPY_QUERY_RESULTS:
1165*61046927SAndroid Build Coastguard Worker       return handle_copy_query_results_cpu_job(queue, job, sync_info, signal_syncs);
1166*61046927SAndroid Build Coastguard Worker    case V3DV_JOB_TYPE_CPU_CSD_INDIRECT:
1167*61046927SAndroid Build Coastguard Worker       return handle_csd_indirect_cpu_job(queue, job, sync_info, signal_syncs);
1168*61046927SAndroid Build Coastguard Worker    case V3DV_JOB_TYPE_CPU_TIMESTAMP_QUERY:
1169*61046927SAndroid Build Coastguard Worker       return handle_timestamp_query_cpu_job(queue, job, sync_info, signal_syncs);
1170*61046927SAndroid Build Coastguard Worker    default:
1171*61046927SAndroid Build Coastguard Worker       unreachable("Unhandled job type");
1172*61046927SAndroid Build Coastguard Worker    }
1173*61046927SAndroid Build Coastguard Worker }
1174*61046927SAndroid Build Coastguard Worker 
1175*61046927SAndroid Build Coastguard Worker static VkResult
queue_create_noop_job(struct v3dv_queue * queue)1176*61046927SAndroid Build Coastguard Worker queue_create_noop_job(struct v3dv_queue *queue)
1177*61046927SAndroid Build Coastguard Worker {
1178*61046927SAndroid Build Coastguard Worker    struct v3dv_device *device = queue->device;
1179*61046927SAndroid Build Coastguard Worker    queue->noop_job = vk_zalloc(&device->vk.alloc, sizeof(struct v3dv_job), 8,
1180*61046927SAndroid Build Coastguard Worker                                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1181*61046927SAndroid Build Coastguard Worker    if (!queue->noop_job)
1182*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1183*61046927SAndroid Build Coastguard Worker    v3dv_job_init(queue->noop_job, V3DV_JOB_TYPE_GPU_CL, device, NULL, -1);
1184*61046927SAndroid Build Coastguard Worker 
1185*61046927SAndroid Build Coastguard Worker    v3dv_X(device, job_emit_noop)(queue->noop_job);
1186*61046927SAndroid Build Coastguard Worker 
1187*61046927SAndroid Build Coastguard Worker    /* We use no-op jobs to signal semaphores/fences. These jobs needs to be
1188*61046927SAndroid Build Coastguard Worker     * serialized across all hw queues to comply with Vulkan's signal operation
1189*61046927SAndroid Build Coastguard Worker     * order requirements, which basically require that signal operations occur
1190*61046927SAndroid Build Coastguard Worker     * in submission order.
1191*61046927SAndroid Build Coastguard Worker     */
1192*61046927SAndroid Build Coastguard Worker    queue->noop_job->serialize = V3DV_BARRIER_ALL;
1193*61046927SAndroid Build Coastguard Worker 
1194*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1195*61046927SAndroid Build Coastguard Worker }
1196*61046927SAndroid Build Coastguard Worker 
1197*61046927SAndroid Build Coastguard Worker static VkResult
queue_submit_noop_job(struct v3dv_queue * queue,uint32_t counter_pass_idx,struct v3dv_submit_sync_info * sync_info,bool signal_syncs)1198*61046927SAndroid Build Coastguard Worker queue_submit_noop_job(struct v3dv_queue *queue,
1199*61046927SAndroid Build Coastguard Worker                       uint32_t counter_pass_idx,
1200*61046927SAndroid Build Coastguard Worker                       struct v3dv_submit_sync_info *sync_info,
1201*61046927SAndroid Build Coastguard Worker                       bool signal_syncs)
1202*61046927SAndroid Build Coastguard Worker {
1203*61046927SAndroid Build Coastguard Worker    if (!queue->noop_job) {
1204*61046927SAndroid Build Coastguard Worker       VkResult result = queue_create_noop_job(queue);
1205*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
1206*61046927SAndroid Build Coastguard Worker          return result;
1207*61046927SAndroid Build Coastguard Worker    }
1208*61046927SAndroid Build Coastguard Worker 
1209*61046927SAndroid Build Coastguard Worker    assert(queue->noop_job);
1210*61046927SAndroid Build Coastguard Worker    return queue_handle_job(queue, queue->noop_job, counter_pass_idx,
1211*61046927SAndroid Build Coastguard Worker                            sync_info, signal_syncs);
1212*61046927SAndroid Build Coastguard Worker }
1213*61046927SAndroid Build Coastguard Worker 
1214*61046927SAndroid Build Coastguard Worker VkResult
v3dv_queue_driver_submit(struct vk_queue * vk_queue,struct vk_queue_submit * submit)1215*61046927SAndroid Build Coastguard Worker v3dv_queue_driver_submit(struct vk_queue *vk_queue,
1216*61046927SAndroid Build Coastguard Worker                          struct vk_queue_submit *submit)
1217*61046927SAndroid Build Coastguard Worker {
1218*61046927SAndroid Build Coastguard Worker    struct v3dv_queue *queue = container_of(vk_queue, struct v3dv_queue, vk);
1219*61046927SAndroid Build Coastguard Worker    VkResult result;
1220*61046927SAndroid Build Coastguard Worker 
1221*61046927SAndroid Build Coastguard Worker    struct v3dv_submit_sync_info sync_info = {
1222*61046927SAndroid Build Coastguard Worker       .wait_count = submit->wait_count,
1223*61046927SAndroid Build Coastguard Worker       .waits = submit->waits,
1224*61046927SAndroid Build Coastguard Worker       .signal_count = submit->signal_count,
1225*61046927SAndroid Build Coastguard Worker       .signals = submit->signals,
1226*61046927SAndroid Build Coastguard Worker    };
1227*61046927SAndroid Build Coastguard Worker 
1228*61046927SAndroid Build Coastguard Worker    for (int i = 0; i < V3DV_QUEUE_COUNT; i++)
1229*61046927SAndroid Build Coastguard Worker       queue->last_job_syncs.first[i] = true;
1230*61046927SAndroid Build Coastguard Worker 
1231*61046927SAndroid Build Coastguard Worker    struct v3dv_job *first_suspend_job = NULL;
1232*61046927SAndroid Build Coastguard Worker    struct v3dv_job *current_suspend_job = NULL;
1233*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < submit->command_buffer_count; i++) {
1234*61046927SAndroid Build Coastguard Worker       struct v3dv_cmd_buffer *cmd_buffer =
1235*61046927SAndroid Build Coastguard Worker          container_of(submit->command_buffers[i], struct v3dv_cmd_buffer, vk);
1236*61046927SAndroid Build Coastguard Worker       list_for_each_entry_safe(struct v3dv_job, job,
1237*61046927SAndroid Build Coastguard Worker                                &cmd_buffer->jobs, list_link) {
1238*61046927SAndroid Build Coastguard Worker          if (job->suspending) {
1239*61046927SAndroid Build Coastguard Worker             job = v3dv_X(job->device,
1240*61046927SAndroid Build Coastguard Worker                          cmd_buffer_prepare_suspend_job_for_submit)(job);
1241*61046927SAndroid Build Coastguard Worker             if (!job)
1242*61046927SAndroid Build Coastguard Worker                return VK_ERROR_OUT_OF_DEVICE_MEMORY;
1243*61046927SAndroid Build Coastguard Worker          }
1244*61046927SAndroid Build Coastguard Worker 
1245*61046927SAndroid Build Coastguard Worker          if (job->suspending && !job->resuming) {
1246*61046927SAndroid Build Coastguard Worker             assert(!first_suspend_job);
1247*61046927SAndroid Build Coastguard Worker             assert(!current_suspend_job);
1248*61046927SAndroid Build Coastguard Worker             first_suspend_job = job;
1249*61046927SAndroid Build Coastguard Worker          }
1250*61046927SAndroid Build Coastguard Worker 
1251*61046927SAndroid Build Coastguard Worker          if (job->resuming) {
1252*61046927SAndroid Build Coastguard Worker             assert(first_suspend_job);
1253*61046927SAndroid Build Coastguard Worker             assert(current_suspend_job);
1254*61046927SAndroid Build Coastguard Worker             v3dv_X(job->device, job_patch_resume_address)(first_suspend_job,
1255*61046927SAndroid Build Coastguard Worker                                                           current_suspend_job,
1256*61046927SAndroid Build Coastguard Worker                                                           job);
1257*61046927SAndroid Build Coastguard Worker             current_suspend_job = NULL;
1258*61046927SAndroid Build Coastguard Worker          }
1259*61046927SAndroid Build Coastguard Worker 
1260*61046927SAndroid Build Coastguard Worker          if (job->suspending) {
1261*61046927SAndroid Build Coastguard Worker             current_suspend_job = job;
1262*61046927SAndroid Build Coastguard Worker          } else {
1263*61046927SAndroid Build Coastguard Worker             assert(!current_suspend_job);
1264*61046927SAndroid Build Coastguard Worker             struct v3dv_job *submit_job = first_suspend_job ?
1265*61046927SAndroid Build Coastguard Worker                                           first_suspend_job : job;
1266*61046927SAndroid Build Coastguard Worker             result =
1267*61046927SAndroid Build Coastguard Worker                queue_handle_job(queue, submit_job, submit->perf_pass_index,
1268*61046927SAndroid Build Coastguard Worker                                 &sync_info, false);
1269*61046927SAndroid Build Coastguard Worker 
1270*61046927SAndroid Build Coastguard Worker             if (result != VK_SUCCESS)
1271*61046927SAndroid Build Coastguard Worker                return result;
1272*61046927SAndroid Build Coastguard Worker 
1273*61046927SAndroid Build Coastguard Worker             first_suspend_job = NULL;
1274*61046927SAndroid Build Coastguard Worker          }
1275*61046927SAndroid Build Coastguard Worker       }
1276*61046927SAndroid Build Coastguard Worker 
1277*61046927SAndroid Build Coastguard Worker       /* If the command buffer ends with a barrier we need to consume it now.
1278*61046927SAndroid Build Coastguard Worker        *
1279*61046927SAndroid Build Coastguard Worker        * FIXME: this will drain all hw queues. Instead, we could use the pending
1280*61046927SAndroid Build Coastguard Worker        * barrier state to limit the queues we serialize against.
1281*61046927SAndroid Build Coastguard Worker        */
1282*61046927SAndroid Build Coastguard Worker       if (cmd_buffer->state.barrier.dst_mask) {
1283*61046927SAndroid Build Coastguard Worker          result = queue_submit_noop_job(queue, submit->perf_pass_index,
1284*61046927SAndroid Build Coastguard Worker                                         &sync_info, false);
1285*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
1286*61046927SAndroid Build Coastguard Worker             return result;
1287*61046927SAndroid Build Coastguard Worker       }
1288*61046927SAndroid Build Coastguard Worker    }
1289*61046927SAndroid Build Coastguard Worker 
1290*61046927SAndroid Build Coastguard Worker    assert(!first_suspend_job);
1291*61046927SAndroid Build Coastguard Worker    assert(!current_suspend_job);
1292*61046927SAndroid Build Coastguard Worker 
1293*61046927SAndroid Build Coastguard Worker    /* Handle signaling now */
1294*61046927SAndroid Build Coastguard Worker    if (submit->signal_count > 0) {
1295*61046927SAndroid Build Coastguard Worker       /* Finish by submitting a no-op job that synchronizes across all queues.
1296*61046927SAndroid Build Coastguard Worker        * This will ensure that the signal semaphores don't get triggered until
1297*61046927SAndroid Build Coastguard Worker        * all work on any queue completes. See Vulkan's signal operation order
1298*61046927SAndroid Build Coastguard Worker        * requirements.
1299*61046927SAndroid Build Coastguard Worker        */
1300*61046927SAndroid Build Coastguard Worker       return queue_submit_noop_job(queue, submit->perf_pass_index,
1301*61046927SAndroid Build Coastguard Worker                                    &sync_info, true);
1302*61046927SAndroid Build Coastguard Worker    }
1303*61046927SAndroid Build Coastguard Worker 
1304*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
1305*61046927SAndroid Build Coastguard Worker }
1306*61046927SAndroid Build Coastguard Worker 
1307*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
v3dv_QueueBindSparse(VkQueue _queue,uint32_t bindInfoCount,const VkBindSparseInfo * pBindInfo,VkFence fence)1308*61046927SAndroid Build Coastguard Worker v3dv_QueueBindSparse(VkQueue _queue,
1309*61046927SAndroid Build Coastguard Worker                      uint32_t bindInfoCount,
1310*61046927SAndroid Build Coastguard Worker                      const VkBindSparseInfo *pBindInfo,
1311*61046927SAndroid Build Coastguard Worker                      VkFence fence)
1312*61046927SAndroid Build Coastguard Worker {
1313*61046927SAndroid Build Coastguard Worker    V3DV_FROM_HANDLE(v3dv_queue, queue, _queue);
1314*61046927SAndroid Build Coastguard Worker    return vk_error(queue, VK_ERROR_FEATURE_NOT_PRESENT);
1315*61046927SAndroid Build Coastguard Worker }
1316