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