xref: /aosp_15_r20/external/mesa3d/src/vulkan/runtime/vk_queue.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2021 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "vk_queue.h"
25 
26 #include "util/perf/cpu_trace.h"
27 #include "util/u_debug.h"
28 #include <inttypes.h>
29 
30 #include "vk_alloc.h"
31 #include "vk_command_buffer.h"
32 #include "vk_command_pool.h"
33 #include "vk_common_entrypoints.h"
34 #include "vk_device.h"
35 #include "vk_fence.h"
36 #include "vk_log.h"
37 #include "vk_physical_device.h"
38 #include "vk_semaphore.h"
39 #include "vk_sync.h"
40 #include "vk_sync_binary.h"
41 #include "vk_sync_dummy.h"
42 #include "vk_sync_timeline.h"
43 #include "vk_util.h"
44 
45 #include "vulkan/wsi/wsi_common.h"
46 
47 static VkResult
48 vk_queue_start_submit_thread(struct vk_queue *queue);
49 
50 VkResult
vk_queue_init(struct vk_queue * queue,struct vk_device * device,const VkDeviceQueueCreateInfo * pCreateInfo,uint32_t index_in_family)51 vk_queue_init(struct vk_queue *queue, struct vk_device *device,
52               const VkDeviceQueueCreateInfo *pCreateInfo,
53               uint32_t index_in_family)
54 {
55    VkResult result = VK_SUCCESS;
56    int ret;
57 
58    memset(queue, 0, sizeof(*queue));
59    vk_object_base_init(device, &queue->base, VK_OBJECT_TYPE_QUEUE);
60 
61    list_addtail(&queue->link, &device->queues);
62 
63    queue->flags = pCreateInfo->flags;
64    queue->queue_family_index = pCreateInfo->queueFamilyIndex;
65 
66    assert(index_in_family < pCreateInfo->queueCount);
67    queue->index_in_family = index_in_family;
68 
69    queue->submit.mode = device->submit_mode;
70    if (queue->submit.mode == VK_QUEUE_SUBMIT_MODE_THREADED_ON_DEMAND)
71       queue->submit.mode = VK_QUEUE_SUBMIT_MODE_IMMEDIATE;
72 
73    list_inithead(&queue->submit.submits);
74 
75    ret = mtx_init(&queue->submit.mutex, mtx_plain);
76    if (ret == thrd_error) {
77       result = vk_errorf(queue, VK_ERROR_UNKNOWN, "mtx_init failed");
78       goto fail_mutex;
79    }
80 
81    ret = cnd_init(&queue->submit.push);
82    if (ret == thrd_error) {
83       result = vk_errorf(queue, VK_ERROR_UNKNOWN, "cnd_init failed");
84       goto fail_push;
85    }
86 
87    ret = cnd_init(&queue->submit.pop);
88    if (ret == thrd_error) {
89       result = vk_errorf(queue, VK_ERROR_UNKNOWN, "cnd_init failed");
90       goto fail_pop;
91    }
92 
93    if (queue->submit.mode == VK_QUEUE_SUBMIT_MODE_THREADED) {
94       result = vk_queue_start_submit_thread(queue);
95       if (result != VK_SUCCESS)
96          goto fail_thread;
97    }
98 
99    util_dynarray_init(&queue->labels, NULL);
100    queue->region_begin = true;
101 
102    return VK_SUCCESS;
103 
104 fail_thread:
105    cnd_destroy(&queue->submit.pop);
106 fail_pop:
107    cnd_destroy(&queue->submit.push);
108 fail_push:
109    mtx_destroy(&queue->submit.mutex);
110 fail_mutex:
111    return result;
112 }
113 
114 VkResult
_vk_queue_set_lost(struct vk_queue * queue,const char * file,int line,const char * msg,...)115 _vk_queue_set_lost(struct vk_queue *queue,
116                    const char *file, int line,
117                    const char *msg, ...)
118 {
119    if (queue->_lost.lost)
120       return VK_ERROR_DEVICE_LOST;
121 
122    queue->_lost.lost = true;
123    queue->_lost.error_file = file;
124    queue->_lost.error_line = line;
125 
126    va_list ap;
127    va_start(ap, msg);
128    vsnprintf(queue->_lost.error_msg, sizeof(queue->_lost.error_msg), msg, ap);
129    va_end(ap);
130 
131    p_atomic_inc(&queue->base.device->_lost.lost);
132 
133    if (debug_get_bool_option("MESA_VK_ABORT_ON_DEVICE_LOSS", false)) {
134       _vk_device_report_lost(queue->base.device);
135       abort();
136    }
137 
138    return VK_ERROR_DEVICE_LOST;
139 }
140 
141 static struct vk_queue_submit *
vk_queue_submit_alloc(struct vk_queue * queue,uint32_t wait_count,uint32_t command_buffer_count,uint32_t buffer_bind_count,uint32_t image_opaque_bind_count,uint32_t image_bind_count,uint32_t bind_entry_count,uint32_t image_bind_entry_count,uint32_t signal_count,VkSparseMemoryBind ** bind_entries,VkSparseImageMemoryBind ** image_bind_entries)142 vk_queue_submit_alloc(struct vk_queue *queue,
143                       uint32_t wait_count,
144                       uint32_t command_buffer_count,
145                       uint32_t buffer_bind_count,
146                       uint32_t image_opaque_bind_count,
147                       uint32_t image_bind_count,
148                       uint32_t bind_entry_count,
149                       uint32_t image_bind_entry_count,
150                       uint32_t signal_count,
151                       VkSparseMemoryBind **bind_entries,
152                       VkSparseImageMemoryBind **image_bind_entries)
153 {
154    VK_MULTIALLOC(ma);
155    VK_MULTIALLOC_DECL(&ma, struct vk_queue_submit, submit, 1);
156    VK_MULTIALLOC_DECL(&ma, struct vk_sync_wait, waits, wait_count);
157    VK_MULTIALLOC_DECL(&ma, struct vk_command_buffer *, command_buffers,
158                       command_buffer_count);
159    VK_MULTIALLOC_DECL(&ma, VkSparseBufferMemoryBindInfo, buffer_binds,
160                       buffer_bind_count);
161    VK_MULTIALLOC_DECL(&ma, VkSparseImageOpaqueMemoryBindInfo,
162                       image_opaque_binds, image_opaque_bind_count);
163    VK_MULTIALLOC_DECL(&ma, VkSparseImageMemoryBindInfo, image_binds,
164                       image_bind_count);
165    VK_MULTIALLOC_DECL(&ma, VkSparseMemoryBind,
166                       bind_entries_local, bind_entry_count);
167    VK_MULTIALLOC_DECL(&ma, VkSparseImageMemoryBind, image_bind_entries_local,
168                       image_bind_entry_count);
169    VK_MULTIALLOC_DECL(&ma, struct vk_sync_signal, signals, signal_count);
170    VK_MULTIALLOC_DECL(&ma, struct vk_sync *, wait_temps, wait_count);
171 
172    struct vk_sync_timeline_point **wait_points = NULL, **signal_points = NULL;
173    if (queue->base.device->timeline_mode == VK_DEVICE_TIMELINE_MODE_EMULATED) {
174       vk_multialloc_add(&ma, &wait_points,
175                         struct vk_sync_timeline_point *, wait_count);
176       vk_multialloc_add(&ma, &signal_points,
177                         struct vk_sync_timeline_point *, signal_count);
178    }
179 
180    if (!vk_multialloc_zalloc(&ma, &queue->base.device->alloc,
181                              VK_SYSTEM_ALLOCATION_SCOPE_DEVICE))
182       return NULL;
183 
184    submit->wait_count            = wait_count;
185    submit->command_buffer_count  = command_buffer_count;
186    submit->signal_count          = signal_count;
187    submit->buffer_bind_count     = buffer_bind_count;
188    submit->image_opaque_bind_count = image_opaque_bind_count;
189    submit->image_bind_count      = image_bind_count;
190 
191    submit->waits           = waits;
192    submit->command_buffers = command_buffers;
193    submit->signals         = signals;
194    submit->buffer_binds    = buffer_binds;
195    submit->image_opaque_binds = image_opaque_binds;
196    submit->image_binds     = image_binds;
197    submit->_wait_temps     = wait_temps;
198    submit->_wait_points    = wait_points;
199    submit->_signal_points  = signal_points;
200 
201    if (bind_entries)
202       *bind_entries = bind_entries_local;
203 
204    if (image_bind_entries)
205       *image_bind_entries = image_bind_entries_local;
206 
207    return submit;
208 }
209 
210 static void
vk_queue_submit_cleanup(struct vk_queue * queue,struct vk_queue_submit * submit)211 vk_queue_submit_cleanup(struct vk_queue *queue,
212                         struct vk_queue_submit *submit)
213 {
214    for (uint32_t i = 0; i < submit->wait_count; i++) {
215       if (submit->_wait_temps[i] != NULL)
216          vk_sync_destroy(queue->base.device, submit->_wait_temps[i]);
217    }
218 
219    if (submit->_mem_signal_temp != NULL)
220       vk_sync_destroy(queue->base.device, submit->_mem_signal_temp);
221 
222    if (submit->_wait_points != NULL) {
223       for (uint32_t i = 0; i < submit->wait_count; i++) {
224          if (unlikely(submit->_wait_points[i] != NULL)) {
225             vk_sync_timeline_point_release(queue->base.device,
226                                            submit->_wait_points[i]);
227          }
228       }
229    }
230 
231    if (submit->_signal_points != NULL) {
232       for (uint32_t i = 0; i < submit->signal_count; i++) {
233          if (unlikely(submit->_signal_points[i] != NULL)) {
234             vk_sync_timeline_point_free(queue->base.device,
235                                         submit->_signal_points[i]);
236          }
237       }
238    }
239 }
240 
241 static void
vk_queue_submit_free(struct vk_queue * queue,struct vk_queue_submit * submit)242 vk_queue_submit_free(struct vk_queue *queue,
243                      struct vk_queue_submit *submit)
244 {
245    vk_free(&queue->base.device->alloc, submit);
246 }
247 
248 static void
vk_queue_submit_destroy(struct vk_queue * queue,struct vk_queue_submit * submit)249 vk_queue_submit_destroy(struct vk_queue *queue,
250                         struct vk_queue_submit *submit)
251 {
252    vk_queue_submit_cleanup(queue, submit);
253    vk_queue_submit_free(queue, submit);
254 }
255 
256 static void
vk_queue_push_submit(struct vk_queue * queue,struct vk_queue_submit * submit)257 vk_queue_push_submit(struct vk_queue *queue,
258                      struct vk_queue_submit *submit)
259 {
260    mtx_lock(&queue->submit.mutex);
261    list_addtail(&submit->link, &queue->submit.submits);
262    cnd_signal(&queue->submit.push);
263    mtx_unlock(&queue->submit.mutex);
264 }
265 
266 static VkResult
vk_queue_drain(struct vk_queue * queue)267 vk_queue_drain(struct vk_queue *queue)
268 {
269    VkResult result = VK_SUCCESS;
270 
271    mtx_lock(&queue->submit.mutex);
272    while (!list_is_empty(&queue->submit.submits)) {
273       if (vk_device_is_lost(queue->base.device)) {
274          result = VK_ERROR_DEVICE_LOST;
275          break;
276       }
277 
278       int ret = cnd_wait(&queue->submit.pop, &queue->submit.mutex);
279       if (ret == thrd_error) {
280          result = vk_queue_set_lost(queue, "cnd_wait failed");
281          break;
282       }
283    }
284    mtx_unlock(&queue->submit.mutex);
285 
286    return result;
287 }
288 
289 static VkResult
vk_queue_submit_final(struct vk_queue * queue,struct vk_queue_submit * submit)290 vk_queue_submit_final(struct vk_queue *queue,
291                       struct vk_queue_submit *submit)
292 {
293    VkResult result;
294 
295    /* Now that we know all our time points exist, fetch the time point syncs
296     * from any vk_sync_timelines.  While we're here, also compact down the
297     * list of waits to get rid of any trivial timeline waits.
298     */
299    uint32_t wait_count = 0;
300    for (uint32_t i = 0; i < submit->wait_count; i++) {
301       /* A timeline wait on 0 is always a no-op */
302       if ((submit->waits[i].sync->flags & VK_SYNC_IS_TIMELINE) &&
303           submit->waits[i].wait_value == 0)
304          continue;
305 
306       /* Waits on dummy vk_syncs are no-ops */
307       if (vk_sync_type_is_dummy(submit->waits[i].sync->type)) {
308          /* We are about to lose track of this wait, if it has a temporary
309           * we need to destroy it now, as vk_queue_submit_cleanup will not
310           * know about it */
311          if (submit->_wait_temps[i] != NULL) {
312             vk_sync_destroy(queue->base.device, submit->_wait_temps[i]);
313             submit->waits[i].sync = NULL;
314          }
315          continue;
316       }
317 
318       /* For emulated timelines, we have a binary vk_sync associated with
319        * each time point and pass the binary vk_sync to the driver.
320        */
321       struct vk_sync_timeline *timeline =
322          vk_sync_as_timeline(submit->waits[i].sync);
323       if (timeline) {
324          assert(queue->base.device->timeline_mode ==
325                 VK_DEVICE_TIMELINE_MODE_EMULATED);
326          result = vk_sync_timeline_get_point(queue->base.device, timeline,
327                                              submit->waits[i].wait_value,
328                                              &submit->_wait_points[i]);
329          if (unlikely(result != VK_SUCCESS)) {
330             result = vk_queue_set_lost(queue,
331                                        "Time point >= %"PRIu64" not found",
332                                        submit->waits[i].wait_value);
333          }
334 
335          /* This can happen if the point is long past */
336          if (submit->_wait_points[i] == NULL)
337             continue;
338 
339          submit->waits[i].sync = &submit->_wait_points[i]->sync;
340          submit->waits[i].wait_value = 0;
341       }
342 
343       struct vk_sync_binary *binary =
344          vk_sync_as_binary(submit->waits[i].sync);
345       if (binary) {
346          submit->waits[i].sync = &binary->timeline;
347          submit->waits[i].wait_value = binary->next_point;
348       }
349 
350       assert((submit->waits[i].sync->flags & VK_SYNC_IS_TIMELINE) ||
351              submit->waits[i].wait_value == 0);
352 
353       assert(wait_count <= i);
354       if (wait_count < i) {
355          submit->waits[wait_count] = submit->waits[i];
356          submit->_wait_temps[wait_count] = submit->_wait_temps[i];
357          if (submit->_wait_points)
358             submit->_wait_points[wait_count] = submit->_wait_points[i];
359       }
360       wait_count++;
361    }
362 
363    assert(wait_count <= submit->wait_count);
364    submit->wait_count = wait_count;
365 
366    for (uint32_t i = 0; i < submit->signal_count; i++) {
367       assert((submit->signals[i].sync->flags & VK_SYNC_IS_TIMELINE) ||
368              submit->signals[i].signal_value == 0);
369 
370       struct vk_sync_binary *binary =
371          vk_sync_as_binary(submit->signals[i].sync);
372       if (binary) {
373          submit->signals[i].sync = &binary->timeline;
374          submit->signals[i].signal_value = ++binary->next_point;
375       }
376    }
377 
378    result = queue->driver_submit(queue, submit);
379    if (unlikely(result != VK_SUCCESS))
380       return result;
381 
382    if (submit->_signal_points) {
383       for (uint32_t i = 0; i < submit->signal_count; i++) {
384          if (submit->_signal_points[i] == NULL)
385             continue;
386 
387          vk_sync_timeline_point_install(queue->base.device,
388                                         submit->_signal_points[i]);
389          submit->_signal_points[i] = NULL;
390       }
391    }
392 
393    return VK_SUCCESS;
394 }
395 
396 VkResult
vk_queue_flush(struct vk_queue * queue,uint32_t * submit_count_out)397 vk_queue_flush(struct vk_queue *queue, uint32_t *submit_count_out)
398 {
399    VkResult result = VK_SUCCESS;
400 
401    assert(queue->submit.mode == VK_QUEUE_SUBMIT_MODE_DEFERRED);
402 
403    mtx_lock(&queue->submit.mutex);
404 
405    uint32_t submit_count = 0;
406    while (!list_is_empty(&queue->submit.submits)) {
407       struct vk_queue_submit *submit =
408          list_first_entry(&queue->submit.submits,
409                           struct vk_queue_submit, link);
410 
411       for (uint32_t i = 0; i < submit->wait_count; i++) {
412          /* In emulated timeline mode, only emulated timelines are allowed */
413          if (!vk_sync_type_is_vk_sync_timeline(submit->waits[i].sync->type)) {
414             assert(!(submit->waits[i].sync->flags & VK_SYNC_IS_TIMELINE));
415             continue;
416          }
417 
418          result = vk_sync_wait(queue->base.device,
419                                submit->waits[i].sync,
420                                submit->waits[i].wait_value,
421                                VK_SYNC_WAIT_PENDING, 0);
422          if (result == VK_TIMEOUT) {
423             /* This one's not ready yet */
424             result = VK_SUCCESS;
425             goto done;
426          } else if (result != VK_SUCCESS) {
427             result = vk_queue_set_lost(queue, "Wait for time points failed");
428             goto done;
429          }
430       }
431 
432       result = vk_queue_submit_final(queue, submit);
433       if (unlikely(result != VK_SUCCESS)) {
434          result = vk_queue_set_lost(queue, "queue::driver_submit failed");
435          goto done;
436       }
437 
438       submit_count++;
439 
440       list_del(&submit->link);
441 
442       vk_queue_submit_destroy(queue, submit);
443    }
444 
445 done:
446    if (submit_count)
447       cnd_broadcast(&queue->submit.pop);
448 
449    mtx_unlock(&queue->submit.mutex);
450 
451    if (submit_count_out)
452       *submit_count_out = submit_count;
453 
454    return result;
455 }
456 
457 static int
vk_queue_submit_thread_func(void * _data)458 vk_queue_submit_thread_func(void *_data)
459 {
460    struct vk_queue *queue = _data;
461    VkResult result;
462 
463    mtx_lock(&queue->submit.mutex);
464 
465    while (queue->submit.thread_run) {
466       if (list_is_empty(&queue->submit.submits)) {
467          int ret = cnd_wait(&queue->submit.push, &queue->submit.mutex);
468          if (ret == thrd_error) {
469             mtx_unlock(&queue->submit.mutex);
470             vk_queue_set_lost(queue, "cnd_wait failed");
471             return 1;
472          }
473          continue;
474       }
475 
476       struct vk_queue_submit *submit =
477          list_first_entry(&queue->submit.submits,
478                           struct vk_queue_submit, link);
479 
480       /* Drop the lock while we wait */
481       mtx_unlock(&queue->submit.mutex);
482 
483       result = vk_sync_wait_many(queue->base.device,
484                                  submit->wait_count, submit->waits,
485                                  VK_SYNC_WAIT_PENDING, UINT64_MAX);
486       if (unlikely(result != VK_SUCCESS)) {
487          vk_queue_set_lost(queue, "Wait for time points failed");
488          return 1;
489       }
490 
491       result = vk_queue_submit_final(queue, submit);
492       if (unlikely(result != VK_SUCCESS)) {
493          vk_queue_set_lost(queue, "queue::driver_submit failed");
494          return 1;
495       }
496 
497       /* Do all our cleanup of individual fences etc. outside the lock.
498        * We can't actually remove it from the list yet.  We have to do
499        * that under the lock.
500        */
501       vk_queue_submit_cleanup(queue, submit);
502 
503       mtx_lock(&queue->submit.mutex);
504 
505       /* Only remove the submit from from the list and free it after
506        * queue->submit() has completed.  This ensures that, when
507        * vk_queue_drain() completes, there are no more pending jobs.
508        */
509       list_del(&submit->link);
510       vk_queue_submit_free(queue, submit);
511 
512       cnd_broadcast(&queue->submit.pop);
513    }
514 
515    mtx_unlock(&queue->submit.mutex);
516    return 0;
517 }
518 
519 static VkResult
vk_queue_start_submit_thread(struct vk_queue * queue)520 vk_queue_start_submit_thread(struct vk_queue *queue)
521 {
522    int ret;
523 
524    mtx_lock(&queue->submit.mutex);
525    queue->submit.thread_run = true;
526    mtx_unlock(&queue->submit.mutex);
527 
528    ret = thrd_create(&queue->submit.thread,
529                      vk_queue_submit_thread_func,
530                      queue);
531    if (ret == thrd_error)
532       return vk_errorf(queue, VK_ERROR_UNKNOWN, "thrd_create failed");
533 
534    return VK_SUCCESS;
535 }
536 
537 static void
vk_queue_stop_submit_thread(struct vk_queue * queue)538 vk_queue_stop_submit_thread(struct vk_queue *queue)
539 {
540    vk_queue_drain(queue);
541 
542    /* Kick the thread to disable it */
543    mtx_lock(&queue->submit.mutex);
544    queue->submit.thread_run = false;
545    cnd_signal(&queue->submit.push);
546    mtx_unlock(&queue->submit.mutex);
547 
548    thrd_join(queue->submit.thread, NULL);
549 
550    assert(list_is_empty(&queue->submit.submits));
551    queue->submit.mode = VK_QUEUE_SUBMIT_MODE_IMMEDIATE;
552 }
553 
554 VkResult
vk_queue_enable_submit_thread(struct vk_queue * queue)555 vk_queue_enable_submit_thread(struct vk_queue *queue)
556 {
557    assert(vk_device_supports_threaded_submit(queue->base.device));
558 
559    if (queue->submit.mode == VK_QUEUE_SUBMIT_MODE_THREADED)
560       return VK_SUCCESS;
561 
562    VkResult result = vk_queue_start_submit_thread(queue);
563    if (result != VK_SUCCESS)
564       return result;
565 
566    queue->submit.mode = VK_QUEUE_SUBMIT_MODE_THREADED;
567 
568    return VK_SUCCESS;
569 }
570 
571 struct vulkan_submit_info {
572    const void *pNext;
573 
574    uint32_t command_buffer_count;
575    const VkCommandBufferSubmitInfo *command_buffers;
576 
577    uint32_t wait_count;
578    const VkSemaphoreSubmitInfo *waits;
579 
580    uint32_t signal_count;
581    const VkSemaphoreSubmitInfo *signals;
582 
583    uint32_t buffer_bind_count;
584    const VkSparseBufferMemoryBindInfo *buffer_binds;
585 
586    uint32_t image_opaque_bind_count;
587    const VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
588 
589    uint32_t image_bind_count;
590    const VkSparseImageMemoryBindInfo *image_binds;
591 
592    struct vk_fence *fence;
593 };
594 
595 static VkResult
vk_queue_submit(struct vk_queue * queue,const struct vulkan_submit_info * info)596 vk_queue_submit(struct vk_queue *queue,
597                 const struct vulkan_submit_info *info)
598 {
599    struct vk_device *device = queue->base.device;
600    VkResult result;
601    uint32_t sparse_memory_bind_entry_count = 0;
602    uint32_t sparse_memory_image_bind_entry_count = 0;
603    VkSparseMemoryBind *sparse_memory_bind_entries = NULL;
604    VkSparseImageMemoryBind *sparse_memory_image_bind_entries = NULL;
605 
606    for (uint32_t i = 0; i < info->buffer_bind_count; ++i)
607       sparse_memory_bind_entry_count += info->buffer_binds[i].bindCount;
608 
609    for (uint32_t i = 0; i < info->image_opaque_bind_count; ++i)
610       sparse_memory_bind_entry_count += info->image_opaque_binds[i].bindCount;
611 
612    for (uint32_t i = 0; i < info->image_bind_count; ++i)
613       sparse_memory_image_bind_entry_count += info->image_binds[i].bindCount;
614 
615    const struct wsi_memory_signal_submit_info *mem_signal =
616       vk_find_struct_const(info->pNext, WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA);
617    bool signal_mem_sync = mem_signal != NULL &&
618                           mem_signal->memory != VK_NULL_HANDLE &&
619                           queue->base.device->create_sync_for_memory != NULL;
620 
621    struct vk_queue_submit *submit =
622       vk_queue_submit_alloc(queue, info->wait_count,
623                             info->command_buffer_count,
624                             info->buffer_bind_count,
625                             info->image_opaque_bind_count,
626                             info->image_bind_count,
627                             sparse_memory_bind_entry_count,
628                             sparse_memory_image_bind_entry_count,
629                             info->signal_count +
630                             signal_mem_sync + (info->fence != NULL),
631                             &sparse_memory_bind_entries,
632                             &sparse_memory_image_bind_entries);
633    if (unlikely(submit == NULL))
634       return vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
635 
636    /* From the Vulkan 1.2.194 spec:
637     *
638     *    "If the VkSubmitInfo::pNext chain does not include this structure,
639     *    the batch defaults to use counter pass index 0."
640     */
641    const VkPerformanceQuerySubmitInfoKHR *perf_info =
642       vk_find_struct_const(info->pNext, PERFORMANCE_QUERY_SUBMIT_INFO_KHR);
643    submit->perf_pass_index = perf_info ? perf_info->counterPassIndex : 0;
644 
645    bool has_binary_permanent_semaphore_wait = false;
646    for (uint32_t i = 0; i < info->wait_count; i++) {
647       VK_FROM_HANDLE(vk_semaphore, semaphore,
648                      info->waits[i].semaphore);
649 
650       /* From the Vulkan 1.2.194 spec:
651        *
652        *    "Applications can import a semaphore payload into an existing
653        *    semaphore using an external semaphore handle. The effects of the
654        *    import operation will be either temporary or permanent, as
655        *    specified by the application. If the import is temporary, the
656        *    implementation must restore the semaphore to its prior permanent
657        *    state after submitting the next semaphore wait operation."
658        *
659        * and
660        *
661        *    VUID-VkImportSemaphoreFdInfoKHR-flags-03323
662        *
663        *    "If flags contains VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, the
664        *    VkSemaphoreTypeCreateInfo::semaphoreType field of the semaphore
665        *    from which handle or name was exported must not be
666        *    VK_SEMAPHORE_TYPE_TIMELINE"
667        */
668       struct vk_sync *sync;
669       if (semaphore->temporary) {
670          assert(semaphore->type == VK_SEMAPHORE_TYPE_BINARY);
671          sync = submit->_wait_temps[i] = semaphore->temporary;
672          semaphore->temporary = NULL;
673       } else {
674          if (semaphore->type == VK_SEMAPHORE_TYPE_BINARY) {
675             if (vk_device_supports_threaded_submit(device))
676                assert(semaphore->permanent.type->move);
677             has_binary_permanent_semaphore_wait = true;
678          }
679 
680          sync = &semaphore->permanent;
681       }
682 
683       uint64_t wait_value = semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE ?
684                             info->waits[i].value : 0;
685 
686       submit->waits[i] = (struct vk_sync_wait) {
687          .sync = sync,
688          .stage_mask = info->waits[i].stageMask,
689          .wait_value = wait_value,
690       };
691    }
692 
693    for (uint32_t i = 0; i < info->command_buffer_count; i++) {
694       VK_FROM_HANDLE(vk_command_buffer, cmd_buffer,
695                      info->command_buffers[i].commandBuffer);
696       assert(info->command_buffers[i].deviceMask == 0 ||
697              info->command_buffers[i].deviceMask == 1);
698       assert(cmd_buffer->pool->queue_family_index == queue->queue_family_index);
699 
700       /* Some drivers don't call vk_command_buffer_begin/end() yet and, for
701        * those, we'll see initial layout.  However, this is enough to catch
702        * command buffers which get submitted without calling EndCommandBuffer.
703        */
704       assert(cmd_buffer->state == MESA_VK_COMMAND_BUFFER_STATE_INITIAL ||
705              cmd_buffer->state == MESA_VK_COMMAND_BUFFER_STATE_EXECUTABLE ||
706              cmd_buffer->state == MESA_VK_COMMAND_BUFFER_STATE_PENDING);
707       cmd_buffer->state = MESA_VK_COMMAND_BUFFER_STATE_PENDING;
708 
709       submit->command_buffers[i] = cmd_buffer;
710    }
711 
712    sparse_memory_bind_entry_count = 0;
713    sparse_memory_image_bind_entry_count = 0;
714 
715    if (info->buffer_binds)
716       typed_memcpy(submit->buffer_binds, info->buffer_binds, info->buffer_bind_count);
717 
718    for (uint32_t i = 0; i < info->buffer_bind_count; ++i) {
719       VkSparseMemoryBind *binds = sparse_memory_bind_entries +
720                                   sparse_memory_bind_entry_count;
721       submit->buffer_binds[i].pBinds = binds;
722       typed_memcpy(binds, info->buffer_binds[i].pBinds,
723                    info->buffer_binds[i].bindCount);
724 
725       sparse_memory_bind_entry_count += info->buffer_binds[i].bindCount;
726    }
727 
728    if (info->image_opaque_binds)
729       typed_memcpy(submit->image_opaque_binds, info->image_opaque_binds,
730                    info->image_opaque_bind_count);
731 
732    for (uint32_t i = 0; i < info->image_opaque_bind_count; ++i) {
733       VkSparseMemoryBind *binds = sparse_memory_bind_entries +
734                                   sparse_memory_bind_entry_count;
735       submit->image_opaque_binds[i].pBinds = binds;
736       typed_memcpy(binds, info->image_opaque_binds[i].pBinds,
737                    info->image_opaque_binds[i].bindCount);
738 
739       sparse_memory_bind_entry_count += info->image_opaque_binds[i].bindCount;
740    }
741 
742    if (info->image_binds)
743       typed_memcpy(submit->image_binds, info->image_binds, info->image_bind_count);
744 
745    for (uint32_t i = 0; i < info->image_bind_count; ++i) {
746       VkSparseImageMemoryBind *binds = sparse_memory_image_bind_entries +
747                                        sparse_memory_image_bind_entry_count;
748       submit->image_binds[i].pBinds = binds;
749       typed_memcpy(binds, info->image_binds[i].pBinds,
750                    info->image_binds[i].bindCount);
751 
752       sparse_memory_image_bind_entry_count += info->image_binds[i].bindCount;
753    }
754 
755    for (uint32_t i = 0; i < info->signal_count; i++) {
756       VK_FROM_HANDLE(vk_semaphore, semaphore,
757                      info->signals[i].semaphore);
758 
759       struct vk_sync *sync = vk_semaphore_get_active_sync(semaphore);
760       uint64_t signal_value = info->signals[i].value;
761       if (semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE) {
762          if (signal_value == 0) {
763             result = vk_queue_set_lost(queue,
764                "Tried to signal a timeline with value 0");
765             goto fail;
766          }
767       } else {
768          signal_value = 0;
769       }
770 
771       /* For emulated timelines, we need to associate a binary vk_sync with
772        * each time point and pass the binary vk_sync to the driver.  We could
773        * do this in vk_queue_submit_final but it might require doing memory
774        * allocation and we don't want to to add extra failure paths there.
775        * Instead, allocate and replace the driver-visible vk_sync now and
776        * we'll insert it into the timeline in vk_queue_submit_final.  The
777        * insert step is guaranteed to not fail.
778        */
779       struct vk_sync_timeline *timeline = vk_sync_as_timeline(sync);
780       if (timeline) {
781          assert(queue->base.device->timeline_mode ==
782                 VK_DEVICE_TIMELINE_MODE_EMULATED);
783          result = vk_sync_timeline_alloc_point(queue->base.device, timeline,
784                                                signal_value,
785                                                &submit->_signal_points[i]);
786          if (unlikely(result != VK_SUCCESS))
787             goto fail;
788 
789          sync = &submit->_signal_points[i]->sync;
790          signal_value = 0;
791       }
792 
793       submit->signals[i] = (struct vk_sync_signal) {
794          .sync = sync,
795          .stage_mask = info->signals[i].stageMask,
796          .signal_value = signal_value,
797       };
798    }
799 
800    uint32_t signal_count = info->signal_count;
801    if (signal_mem_sync) {
802       struct vk_sync *mem_sync;
803       result = queue->base.device->create_sync_for_memory(queue->base.device,
804                                                           mem_signal->memory,
805                                                           true, &mem_sync);
806       if (unlikely(result != VK_SUCCESS))
807          goto fail;
808 
809       submit->_mem_signal_temp = mem_sync;
810 
811       assert(submit->signals[signal_count].sync == NULL);
812       submit->signals[signal_count++] = (struct vk_sync_signal) {
813          .sync = mem_sync,
814          .stage_mask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
815       };
816    }
817 
818    if (info->fence != NULL) {
819       assert(submit->signals[signal_count].sync == NULL);
820       submit->signals[signal_count++] = (struct vk_sync_signal) {
821          .sync = vk_fence_get_active_sync(info->fence),
822          .stage_mask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
823       };
824    }
825 
826    assert(signal_count == submit->signal_count);
827 
828    /* If this device supports threaded submit, we can't rely on the client
829     * ordering requirements to ensure submits happen in the right order.  Even
830     * if this queue doesn't have a submit thread, another queue (possibly in a
831     * different process) may and that means we our dependencies may not have
832     * been submitted to the kernel yet.  Do a quick zero-timeout WAIT_PENDING
833     * on all the wait semaphores to see if we need to start up our own thread.
834     */
835    if (device->submit_mode == VK_QUEUE_SUBMIT_MODE_THREADED_ON_DEMAND &&
836        queue->submit.mode != VK_QUEUE_SUBMIT_MODE_THREADED) {
837       assert(queue->submit.mode == VK_QUEUE_SUBMIT_MODE_IMMEDIATE);
838 
839       result = vk_sync_wait_many(queue->base.device,
840                                  submit->wait_count, submit->waits,
841                                  VK_SYNC_WAIT_PENDING, 0);
842       if (result == VK_TIMEOUT)
843          result = vk_queue_enable_submit_thread(queue);
844       if (unlikely(result != VK_SUCCESS))
845          goto fail;
846    }
847 
848    switch (queue->submit.mode) {
849    case VK_QUEUE_SUBMIT_MODE_IMMEDIATE:
850       result = vk_queue_submit_final(queue, submit);
851       if (unlikely(result != VK_SUCCESS))
852          goto fail;
853 
854       /* If threaded submit is possible on this device, we need to ensure that
855        * binary semaphore payloads get reset so that any other threads can
856        * properly wait on them for dependency checking.  Because we don't
857        * currently have a submit thread, we can directly reset that binary
858        * semaphore payloads.
859        *
860        * If we the vk_sync is in our signal et, we can consider it to have
861        * been both reset and signaled by queue_submit_final().  A reset in
862        * this case would be wrong because it would throw away our signal
863        * operation.  If we don't signal the vk_sync, then we need to reset it.
864        */
865       if (vk_device_supports_threaded_submit(device) &&
866           has_binary_permanent_semaphore_wait) {
867          for (uint32_t i = 0; i < submit->wait_count; i++) {
868             if ((submit->waits[i].sync->flags & VK_SYNC_IS_TIMELINE) ||
869                 submit->_wait_temps[i] != NULL)
870                continue;
871 
872             bool was_signaled = false;
873             for (uint32_t j = 0; j < submit->signal_count; j++) {
874                if (submit->signals[j].sync == submit->waits[i].sync) {
875                   was_signaled = true;
876                   break;
877                }
878             }
879 
880             if (!was_signaled) {
881                result = vk_sync_reset(queue->base.device,
882                                       submit->waits[i].sync);
883                if (unlikely(result != VK_SUCCESS))
884                   goto fail;
885             }
886          }
887       }
888 
889       vk_queue_submit_destroy(queue, submit);
890       return result;
891 
892    case VK_QUEUE_SUBMIT_MODE_DEFERRED:
893       vk_queue_push_submit(queue, submit);
894       return vk_device_flush(queue->base.device);
895 
896    case VK_QUEUE_SUBMIT_MODE_THREADED:
897       if (has_binary_permanent_semaphore_wait) {
898          for (uint32_t i = 0; i < info->wait_count; i++) {
899             VK_FROM_HANDLE(vk_semaphore, semaphore,
900                            info->waits[i].semaphore);
901 
902             if (semaphore->type != VK_SEMAPHORE_TYPE_BINARY)
903                continue;
904 
905             /* From the Vulkan 1.2.194 spec:
906              *
907              *    "When a batch is submitted to a queue via a queue
908              *    submission, and it includes semaphores to be waited on,
909              *    it defines a memory dependency between prior semaphore
910              *    signal operations and the batch, and defines semaphore
911              *    wait operations.
912              *
913              *    Such semaphore wait operations set the semaphores
914              *    created with a VkSemaphoreType of
915              *    VK_SEMAPHORE_TYPE_BINARY to the unsignaled state."
916              *
917              * For threaded submit, we depend on tracking the unsignaled
918              * state of binary semaphores to determine when we can safely
919              * submit.  The VK_SYNC_WAIT_PENDING check above as well as the
920              * one in the sumbit thread depend on all binary semaphores
921              * being reset when they're not in active use from the point
922              * of view of the client's CPU timeline.  This means we need to
923              * reset them inside vkQueueSubmit and cannot wait until the
924              * actual submit which happens later in the thread.
925              *
926              * We've already stolen temporary semaphore payloads above as
927              * part of basic semaphore processing.  We steal permanent
928              * semaphore payloads here by way of vk_sync_move.  For shared
929              * semaphores, this can be a bit expensive (sync file import
930              * and export) but, for non-shared semaphores, it can be made
931              * fairly cheap.  Also, we only do this semaphore swapping in
932              * the case where you have real timelines AND the client is
933              * using timeline semaphores with wait-before-signal (that's
934              * the only way to get a submit thread) AND mixing those with
935              * waits on binary semaphores AND said binary semaphore is
936              * using its permanent payload.  In other words, this code
937              * should basically only ever get executed in CTS tests.
938              */
939             if (submit->_wait_temps[i] != NULL)
940                continue;
941 
942             assert(submit->waits[i].sync == &semaphore->permanent);
943 
944             /* From the Vulkan 1.2.194 spec:
945              *
946              *    VUID-vkQueueSubmit-pWaitSemaphores-03238
947              *
948              *    "All elements of the pWaitSemaphores member of all
949              *    elements of pSubmits created with a VkSemaphoreType of
950              *    VK_SEMAPHORE_TYPE_BINARY must reference a semaphore
951              *    signal operation that has been submitted for execution
952              *    and any semaphore signal operations on which it depends
953              *    (if any) must have also been submitted for execution."
954              *
955              * Therefore, we can safely do a blocking wait here and it
956              * won't actually block for long.  This ensures that the
957              * vk_sync_move below will succeed.
958              */
959             result = vk_sync_wait(queue->base.device,
960                                   submit->waits[i].sync, 0,
961                                   VK_SYNC_WAIT_PENDING, UINT64_MAX);
962             if (unlikely(result != VK_SUCCESS))
963                goto fail;
964 
965             result = vk_sync_create(queue->base.device,
966                                     semaphore->permanent.type,
967                                     0 /* flags */,
968                                     0 /* initial value */,
969                                     &submit->_wait_temps[i]);
970             if (unlikely(result != VK_SUCCESS))
971                goto fail;
972 
973             result = vk_sync_move(queue->base.device,
974                                   submit->_wait_temps[i],
975                                   &semaphore->permanent);
976             if (unlikely(result != VK_SUCCESS))
977                goto fail;
978 
979             submit->waits[i].sync = submit->_wait_temps[i];
980          }
981       }
982 
983       vk_queue_push_submit(queue, submit);
984 
985       if (signal_mem_sync) {
986          /* If we're signaling a memory object, we have to ensure that
987           * vkQueueSubmit does not return until the kernel submission has
988           * happened.  Otherwise, we may get a race between this process
989           * and whatever is going to wait on the object where the other
990           * process may wait before we've submitted our work.  Drain the
991           * queue now to avoid this.  It's the responsibility of the caller
992           * to ensure that any vkQueueSubmit which signals a memory object
993           * has fully resolved dependencies.
994           */
995          result = vk_queue_drain(queue);
996          if (unlikely(result != VK_SUCCESS))
997             return result;
998       }
999 
1000       return VK_SUCCESS;
1001 
1002    case VK_QUEUE_SUBMIT_MODE_THREADED_ON_DEMAND:
1003       unreachable("Invalid vk_queue::submit.mode");
1004    }
1005    unreachable("Invalid submit mode");
1006 
1007 fail:
1008    vk_queue_submit_destroy(queue, submit);
1009    return result;
1010 }
1011 
1012 VkResult
vk_queue_wait_before_present(struct vk_queue * queue,const VkPresentInfoKHR * pPresentInfo)1013 vk_queue_wait_before_present(struct vk_queue *queue,
1014                              const VkPresentInfoKHR *pPresentInfo)
1015 {
1016    if (vk_device_is_lost(queue->base.device))
1017       return VK_ERROR_DEVICE_LOST;
1018 
1019    /* From the Vulkan 1.2.194 spec:
1020     *
1021     *    VUID-vkQueuePresentKHR-pWaitSemaphores-03268
1022     *
1023     *    "All elements of the pWaitSemaphores member of pPresentInfo must
1024     *    reference a semaphore signal operation that has been submitted for
1025     *    execution and any semaphore signal operations on which it depends (if
1026     *    any) must have also been submitted for execution."
1027     *
1028     * As with vkQueueSubmit above, we need to ensure that any binary
1029     * semaphores we use in this present actually exist.  If we don't have
1030     * timeline semaphores, this is a non-issue.  If they're emulated, then
1031     * this is ensured for us by the vk_device_flush() at the end of every
1032     * vkQueueSubmit() and every vkSignalSemaphore().  For real timeline
1033     * semaphores, however, we need to do a wait.  Thanks to the above bit of
1034     * spec text, that wait should never block for long.
1035     */
1036    if (!vk_device_supports_threaded_submit(queue->base.device))
1037       return VK_SUCCESS;
1038 
1039    const uint32_t wait_count = pPresentInfo->waitSemaphoreCount;
1040 
1041    if (wait_count == 0)
1042       return VK_SUCCESS;
1043 
1044    STACK_ARRAY(struct vk_sync_wait, waits, wait_count);
1045 
1046    for (uint32_t i = 0; i < wait_count; i++) {
1047       VK_FROM_HANDLE(vk_semaphore, semaphore,
1048                      pPresentInfo->pWaitSemaphores[i]);
1049 
1050       /* From the Vulkan 1.2.194 spec:
1051        *
1052        *    VUID-vkQueuePresentKHR-pWaitSemaphores-03267
1053        *
1054        *    "All elements of the pWaitSemaphores member of pPresentInfo must
1055        *    be created with a VkSemaphoreType of VK_SEMAPHORE_TYPE_BINARY."
1056        */
1057       assert(semaphore->type == VK_SEMAPHORE_TYPE_BINARY);
1058 
1059       waits[i] = (struct vk_sync_wait) {
1060          .sync = vk_semaphore_get_active_sync(semaphore),
1061          .stage_mask = ~(VkPipelineStageFlags2)0,
1062       };
1063    }
1064 
1065    VkResult result = vk_sync_wait_many(queue->base.device, wait_count, waits,
1066                                        VK_SYNC_WAIT_PENDING, UINT64_MAX);
1067 
1068    STACK_ARRAY_FINISH(waits);
1069 
1070    /* Check again, just in case */
1071    if (vk_device_is_lost(queue->base.device))
1072       return VK_ERROR_DEVICE_LOST;
1073 
1074    return result;
1075 }
1076 
1077 static VkResult
vk_queue_signal_sync(struct vk_queue * queue,struct vk_sync * sync,uint32_t signal_value)1078 vk_queue_signal_sync(struct vk_queue *queue,
1079                      struct vk_sync *sync,
1080                      uint32_t signal_value)
1081 {
1082    struct vk_queue_submit *submit = vk_queue_submit_alloc(queue, 0, 0, 0, 0, 0,
1083                                                           0, 0, 1, NULL, NULL);
1084    if (unlikely(submit == NULL))
1085       return vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
1086 
1087    submit->signals[0] = (struct vk_sync_signal) {
1088       .sync = sync,
1089       .stage_mask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT,
1090       .signal_value = signal_value,
1091    };
1092 
1093    VkResult result;
1094    switch (queue->submit.mode) {
1095    case VK_QUEUE_SUBMIT_MODE_IMMEDIATE:
1096       result = vk_queue_submit_final(queue, submit);
1097       vk_queue_submit_destroy(queue, submit);
1098       return result;
1099 
1100    case VK_QUEUE_SUBMIT_MODE_DEFERRED:
1101       vk_queue_push_submit(queue, submit);
1102       return vk_device_flush(queue->base.device);
1103 
1104    case VK_QUEUE_SUBMIT_MODE_THREADED:
1105       vk_queue_push_submit(queue, submit);
1106       return VK_SUCCESS;
1107 
1108    case VK_QUEUE_SUBMIT_MODE_THREADED_ON_DEMAND:
1109       unreachable("Invalid vk_queue::submit.mode");
1110    }
1111    unreachable("Invalid timeline mode");
1112 }
1113 
1114 void
vk_queue_finish(struct vk_queue * queue)1115 vk_queue_finish(struct vk_queue *queue)
1116 {
1117    if (queue->submit.mode == VK_QUEUE_SUBMIT_MODE_THREADED)
1118       vk_queue_stop_submit_thread(queue);
1119 
1120    while (!list_is_empty(&queue->submit.submits)) {
1121       assert(vk_device_is_lost_no_report(queue->base.device));
1122 
1123       struct vk_queue_submit *submit =
1124          list_first_entry(&queue->submit.submits,
1125                           struct vk_queue_submit, link);
1126 
1127       list_del(&submit->link);
1128       vk_queue_submit_destroy(queue, submit);
1129    }
1130 
1131 #if DETECT_OS_ANDROID
1132    if (queue->anb_semaphore != VK_NULL_HANDLE) {
1133       struct vk_device *device = queue->base.device;
1134       device->dispatch_table.DestroySemaphore(vk_device_to_handle(device),
1135                                               queue->anb_semaphore, NULL);
1136    }
1137 #endif
1138 
1139    cnd_destroy(&queue->submit.pop);
1140    cnd_destroy(&queue->submit.push);
1141    mtx_destroy(&queue->submit.mutex);
1142 
1143    util_dynarray_fini(&queue->labels);
1144    list_del(&queue->link);
1145    vk_object_base_finish(&queue->base);
1146 }
1147 
1148 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_QueueSubmit2(VkQueue _queue,uint32_t submitCount,const VkSubmitInfo2 * pSubmits,VkFence _fence)1149 vk_common_QueueSubmit2(VkQueue _queue,
1150                           uint32_t submitCount,
1151                           const VkSubmitInfo2 *pSubmits,
1152                           VkFence _fence)
1153 {
1154    VK_FROM_HANDLE(vk_queue, queue, _queue);
1155    VK_FROM_HANDLE(vk_fence, fence, _fence);
1156 
1157    if (vk_device_is_lost(queue->base.device))
1158       return VK_ERROR_DEVICE_LOST;
1159 
1160    if (submitCount == 0) {
1161       if (fence == NULL) {
1162          return VK_SUCCESS;
1163       } else {
1164          return vk_queue_signal_sync(queue, vk_fence_get_active_sync(fence), 0);
1165       }
1166    }
1167 
1168    for (uint32_t i = 0; i < submitCount; i++) {
1169       struct vulkan_submit_info info = {
1170          .pNext = pSubmits[i].pNext,
1171          .command_buffer_count = pSubmits[i].commandBufferInfoCount,
1172          .command_buffers = pSubmits[i].pCommandBufferInfos,
1173          .wait_count = pSubmits[i].waitSemaphoreInfoCount,
1174          .waits = pSubmits[i].pWaitSemaphoreInfos,
1175          .signal_count = pSubmits[i].signalSemaphoreInfoCount,
1176          .signals = pSubmits[i].pSignalSemaphoreInfos,
1177          .fence = i == submitCount - 1 ? fence : NULL
1178       };
1179       VkResult result = vk_queue_submit(queue, &info);
1180       if (unlikely(result != VK_SUCCESS))
1181          return result;
1182    }
1183 
1184    return VK_SUCCESS;
1185 }
1186 
1187 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_QueueBindSparse(VkQueue _queue,uint32_t bindInfoCount,const VkBindSparseInfo * pBindInfo,VkFence _fence)1188 vk_common_QueueBindSparse(VkQueue _queue,
1189                           uint32_t bindInfoCount,
1190                           const VkBindSparseInfo *pBindInfo,
1191                           VkFence _fence)
1192 {
1193    VK_FROM_HANDLE(vk_queue, queue, _queue);
1194    VK_FROM_HANDLE(vk_fence, fence, _fence);
1195 
1196    if (vk_device_is_lost(queue->base.device))
1197       return VK_ERROR_DEVICE_LOST;
1198 
1199    if (bindInfoCount == 0) {
1200       if (fence == NULL) {
1201          return VK_SUCCESS;
1202       } else {
1203          return vk_queue_signal_sync(queue, vk_fence_get_active_sync(fence), 0);
1204       }
1205    }
1206 
1207    for (uint32_t i = 0; i < bindInfoCount; i++) {
1208       const VkTimelineSemaphoreSubmitInfo *timeline_info =
1209          vk_find_struct_const(pBindInfo[i].pNext, TIMELINE_SEMAPHORE_SUBMIT_INFO);
1210       const uint64_t *wait_values = NULL;
1211       const uint64_t *signal_values = NULL;
1212 
1213       if (timeline_info && timeline_info->waitSemaphoreValueCount) {
1214          /* From the Vulkan 1.3.204 spec:
1215           *
1216           *    VUID-VkBindSparseInfo-pNext-03248
1217           *
1218           *    "If the pNext chain of this structure includes a VkTimelineSemaphoreSubmitInfo structure
1219           *    and any element of pSignalSemaphores was created with a VkSemaphoreType of
1220           *    VK_SEMAPHORE_TYPE_TIMELINE, then its signalSemaphoreValueCount member must equal
1221           *    signalSemaphoreCount"
1222           */
1223          assert(timeline_info->waitSemaphoreValueCount == pBindInfo[i].waitSemaphoreCount);
1224          wait_values = timeline_info->pWaitSemaphoreValues;
1225       }
1226 
1227       if (timeline_info && timeline_info->signalSemaphoreValueCount) {
1228          /* From the Vulkan 1.3.204 spec:
1229           *
1230           * VUID-VkBindSparseInfo-pNext-03247
1231           *
1232           *    "If the pNext chain of this structure includes a VkTimelineSemaphoreSubmitInfo structure
1233           *    and any element of pWaitSemaphores was created with a VkSemaphoreType of
1234           *    VK_SEMAPHORE_TYPE_TIMELINE, then its waitSemaphoreValueCount member must equal
1235           *    waitSemaphoreCount"
1236           */
1237          assert(timeline_info->signalSemaphoreValueCount == pBindInfo[i].signalSemaphoreCount);
1238          signal_values = timeline_info->pSignalSemaphoreValues;
1239       }
1240 
1241       STACK_ARRAY(VkSemaphoreSubmitInfo, wait_semaphore_infos,
1242                   pBindInfo[i].waitSemaphoreCount);
1243       STACK_ARRAY(VkSemaphoreSubmitInfo, signal_semaphore_infos,
1244                   pBindInfo[i].signalSemaphoreCount);
1245 
1246       if (!wait_semaphore_infos || !signal_semaphore_infos) {
1247          STACK_ARRAY_FINISH(wait_semaphore_infos);
1248          STACK_ARRAY_FINISH(signal_semaphore_infos);
1249          return vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
1250       }
1251 
1252       for (uint32_t j = 0; j < pBindInfo[i].waitSemaphoreCount; j++) {
1253          wait_semaphore_infos[j] = (VkSemaphoreSubmitInfo) {
1254             .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
1255             .semaphore = pBindInfo[i].pWaitSemaphores[j],
1256             .value = wait_values ? wait_values[j] : 0,
1257          };
1258       }
1259 
1260       for (uint32_t j = 0; j < pBindInfo[i].signalSemaphoreCount; j++) {
1261          signal_semaphore_infos[j] = (VkSemaphoreSubmitInfo) {
1262             .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
1263             .semaphore = pBindInfo[i].pSignalSemaphores[j],
1264             .value = signal_values ? signal_values[j] : 0,
1265          };
1266       }
1267       struct vulkan_submit_info info = {
1268          .pNext = pBindInfo[i].pNext,
1269          .wait_count = pBindInfo[i].waitSemaphoreCount,
1270          .waits = wait_semaphore_infos,
1271          .signal_count = pBindInfo[i].signalSemaphoreCount,
1272          .signals = signal_semaphore_infos,
1273          .buffer_bind_count = pBindInfo[i].bufferBindCount,
1274          .buffer_binds = pBindInfo[i].pBufferBinds,
1275          .image_opaque_bind_count = pBindInfo[i].imageOpaqueBindCount,
1276          .image_opaque_binds = pBindInfo[i].pImageOpaqueBinds,
1277          .image_bind_count = pBindInfo[i].imageBindCount,
1278          .image_binds = pBindInfo[i].pImageBinds,
1279          .fence = i == bindInfoCount - 1 ? fence : NULL
1280       };
1281       VkResult result = vk_queue_submit(queue, &info);
1282 
1283       STACK_ARRAY_FINISH(wait_semaphore_infos);
1284       STACK_ARRAY_FINISH(signal_semaphore_infos);
1285 
1286       if (unlikely(result != VK_SUCCESS))
1287          return result;
1288    }
1289 
1290    return VK_SUCCESS;
1291 }
1292 
1293 static const struct vk_sync_type *
get_cpu_wait_type(struct vk_physical_device * pdevice)1294 get_cpu_wait_type(struct vk_physical_device *pdevice)
1295 {
1296    for (const struct vk_sync_type *const *t =
1297         pdevice->supported_sync_types; *t; t++) {
1298       if (((*t)->features & VK_SYNC_FEATURE_BINARY) &&
1299           ((*t)->features & VK_SYNC_FEATURE_CPU_WAIT))
1300          return *t;
1301    }
1302 
1303    unreachable("You must have a non-timeline CPU wait sync type");
1304 }
1305 
1306 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_QueueWaitIdle(VkQueue _queue)1307 vk_common_QueueWaitIdle(VkQueue _queue)
1308 {
1309    MESA_TRACE_FUNC();
1310 
1311    VK_FROM_HANDLE(vk_queue, queue, _queue);
1312    VkResult result;
1313 
1314    if (vk_device_is_lost(queue->base.device))
1315       return VK_ERROR_DEVICE_LOST;
1316 
1317    const struct vk_sync_type *sync_type =
1318       get_cpu_wait_type(queue->base.device->physical);
1319 
1320    struct vk_sync *sync;
1321    result = vk_sync_create(queue->base.device, sync_type, 0, 0, &sync);
1322    if (unlikely(result != VK_SUCCESS))
1323       return result;
1324 
1325    result = vk_queue_signal_sync(queue, sync, 0);
1326    if (unlikely(result != VK_SUCCESS))
1327       return result;
1328 
1329    result = vk_sync_wait(queue->base.device, sync, 0,
1330                          VK_SYNC_WAIT_COMPLETE, UINT64_MAX);
1331 
1332    vk_sync_destroy(queue->base.device, sync);
1333 
1334    VkResult device_status = vk_device_check_status(queue->base.device);
1335    if (device_status != VK_SUCCESS)
1336       return device_status;
1337 
1338    return result;
1339 }
1340