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