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(©.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 *)©, 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(©.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 *)©, 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(×tamp.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 *)×tamp, 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