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