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