• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
46 static VkResult
47 vk_queue_start_submit_thread(struct vk_queue *queue);
48 
49 VkResult
vk_queue_init(struct vk_queue * queue,struct vk_device * device,const VkDeviceQueueCreateInfo * pCreateInfo,uint32_t index_in_family)50 vk_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 
103 fail_thread:
104    cnd_destroy(&queue->submit.pop);
105 fail_pop:
106    cnd_destroy(&queue->submit.push);
107 fail_push:
108    mtx_destroy(&queue->submit.mutex);
109 fail_mutex:
110    return result;
111 }
112 
113 VkResult
_vk_queue_set_lost(struct vk_queue * queue,const char * file,int line,const char * msg,...)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 
140 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)141 vk_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 
209 static void
vk_queue_submit_cleanup(struct vk_queue * queue,struct vk_queue_submit * submit)210 vk_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 
240 static void
vk_queue_submit_free(struct vk_queue * queue,struct vk_queue_submit * submit)241 vk_queue_submit_free(struct vk_queue *queue,
242                      struct vk_queue_submit *submit)
243 {
244    vk_free(&queue->base.device->alloc, submit);
245 }
246 
247 static void
vk_queue_submit_destroy(struct vk_queue * queue,struct vk_queue_submit * submit)248 vk_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 
255 static void
vk_queue_push_submit(struct vk_queue * queue,struct vk_queue_submit * submit)256 vk_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 
265 static VkResult
vk_queue_drain(struct vk_queue * queue)266 vk_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 
288 static VkResult
vk_queue_submit_final(struct vk_queue * queue,struct vk_queue_submit * submit)289 vk_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 
395 VkResult
vk_queue_flush(struct vk_queue * queue,uint32_t * submit_count_out)396 vk_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 
444 done:
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 
456 static int
vk_queue_submit_thread_func(void * _data)457 vk_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 
518 static VkResult
vk_queue_start_submit_thread(struct vk_queue * queue)519 vk_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 
536 static void
vk_queue_stop_submit_thread(struct vk_queue * queue)537 vk_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 
553 VkResult
vk_queue_enable_submit_thread(struct vk_queue * queue)554 vk_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 
570 struct 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 
594 static VkResult
vk_queue_submit(struct vk_queue * queue,const struct vulkan_submit_info * info)595 vk_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 
996 fail:
997    vk_queue_submit_destroy(queue, submit);
998    return result;
999 }
1000 
1001 VkResult
vk_queue_wait_before_present(struct vk_queue * queue,const VkPresentInfoKHR * pPresentInfo)1002 vk_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 
1062 static VkResult
vk_queue_signal_sync(struct vk_queue * queue,struct vk_sync * sync,uint32_t signal_value)1063 vk_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 
1099 void
vk_queue_finish(struct vk_queue * queue)1100 vk_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 
1125 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_QueueSubmit2KHR(VkQueue _queue,uint32_t submitCount,const VkSubmitInfo2 * pSubmits,VkFence _fence)1126 vk_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 
1164 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_QueueBindSparse(VkQueue _queue,uint32_t bindInfoCount,const VkBindSparseInfo * pBindInfo,VkFence _fence)1165 vk_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 
1270 static const struct vk_sync_type *
get_cpu_wait_type(struct vk_physical_device * pdevice)1271 get_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 
1283 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_QueueWaitIdle(VkQueue _queue)1284 vk_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