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