1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2019 Google LLC 3bf215546Sopenharmony_ci * SPDX-License-Identifier: MIT 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * based in part on anv and radv which are: 6bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 7bf215546Sopenharmony_ci * Copyright © 2016 Red Hat. 8bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen 9bf215546Sopenharmony_ci */ 10bf215546Sopenharmony_ci 11bf215546Sopenharmony_ci#include "vn_queue.h" 12bf215546Sopenharmony_ci 13bf215546Sopenharmony_ci#include "util/libsync.h" 14bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_event.h" 15bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_fence.h" 16bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_queue.h" 17bf215546Sopenharmony_ci#include "venus-protocol/vn_protocol_driver_semaphore.h" 18bf215546Sopenharmony_ci 19bf215546Sopenharmony_ci#include "vn_device.h" 20bf215546Sopenharmony_ci#include "vn_device_memory.h" 21bf215546Sopenharmony_ci#include "vn_renderer.h" 22bf215546Sopenharmony_ci#include "vn_wsi.h" 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci/* queue commands */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_civoid 27bf215546Sopenharmony_civn_GetDeviceQueue2(VkDevice device, 28bf215546Sopenharmony_ci const VkDeviceQueueInfo2 *pQueueInfo, 29bf215546Sopenharmony_ci VkQueue *pQueue) 30bf215546Sopenharmony_ci{ 31bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci for (uint32_t i = 0; i < dev->queue_count; i++) { 34bf215546Sopenharmony_ci struct vn_queue *queue = &dev->queues[i]; 35bf215546Sopenharmony_ci if (queue->family == pQueueInfo->queueFamilyIndex && 36bf215546Sopenharmony_ci queue->index == pQueueInfo->queueIndex && 37bf215546Sopenharmony_ci queue->flags == pQueueInfo->flags) { 38bf215546Sopenharmony_ci *pQueue = vn_queue_to_handle(queue); 39bf215546Sopenharmony_ci return; 40bf215546Sopenharmony_ci } 41bf215546Sopenharmony_ci } 42bf215546Sopenharmony_ci unreachable("bad queue family/index"); 43bf215546Sopenharmony_ci} 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_cistatic void 46bf215546Sopenharmony_civn_semaphore_reset_wsi(struct vn_device *dev, struct vn_semaphore *sem); 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistruct vn_queue_submission { 49bf215546Sopenharmony_ci VkStructureType batch_type; 50bf215546Sopenharmony_ci VkQueue queue; 51bf215546Sopenharmony_ci uint32_t batch_count; 52bf215546Sopenharmony_ci union { 53bf215546Sopenharmony_ci const void *batches; 54bf215546Sopenharmony_ci const VkSubmitInfo *submit_batches; 55bf215546Sopenharmony_ci const VkBindSparseInfo *bind_sparse_batches; 56bf215546Sopenharmony_ci }; 57bf215546Sopenharmony_ci VkFence fence; 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci uint32_t wait_semaphore_count; 60bf215546Sopenharmony_ci uint32_t wait_wsi_count; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci struct { 63bf215546Sopenharmony_ci void *storage; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci union { 66bf215546Sopenharmony_ci void *batches; 67bf215546Sopenharmony_ci VkSubmitInfo *submit_batches; 68bf215546Sopenharmony_ci VkBindSparseInfo *bind_sparse_batches; 69bf215546Sopenharmony_ci }; 70bf215546Sopenharmony_ci VkSemaphore *semaphores; 71bf215546Sopenharmony_ci } temp; 72bf215546Sopenharmony_ci}; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_cistatic void 75bf215546Sopenharmony_civn_queue_submission_count_batch_semaphores(struct vn_queue_submission *submit, 76bf215546Sopenharmony_ci uint32_t batch_index) 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci union { 79bf215546Sopenharmony_ci const VkSubmitInfo *submit_batch; 80bf215546Sopenharmony_ci const VkBindSparseInfo *bind_sparse_batch; 81bf215546Sopenharmony_ci } u; 82bf215546Sopenharmony_ci const VkSemaphore *wait_sems; 83bf215546Sopenharmony_ci uint32_t wait_count; 84bf215546Sopenharmony_ci switch (submit->batch_type) { 85bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_SUBMIT_INFO: 86bf215546Sopenharmony_ci u.submit_batch = &submit->submit_batches[batch_index]; 87bf215546Sopenharmony_ci wait_sems = u.submit_batch->pWaitSemaphores; 88bf215546Sopenharmony_ci wait_count = u.submit_batch->waitSemaphoreCount; 89bf215546Sopenharmony_ci break; 90bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_BIND_SPARSE_INFO: 91bf215546Sopenharmony_ci u.bind_sparse_batch = &submit->bind_sparse_batches[batch_index]; 92bf215546Sopenharmony_ci wait_sems = u.bind_sparse_batch->pWaitSemaphores; 93bf215546Sopenharmony_ci wait_count = u.bind_sparse_batch->waitSemaphoreCount; 94bf215546Sopenharmony_ci break; 95bf215546Sopenharmony_ci default: 96bf215546Sopenharmony_ci unreachable("unexpected batch type"); 97bf215546Sopenharmony_ci break; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci submit->wait_semaphore_count += wait_count; 101bf215546Sopenharmony_ci for (uint32_t i = 0; i < wait_count; i++) { 102bf215546Sopenharmony_ci struct vn_semaphore *sem = vn_semaphore_from_handle(wait_sems[i]); 103bf215546Sopenharmony_ci const struct vn_sync_payload *payload = sem->payload; 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci if (payload->type == VN_SYNC_TYPE_WSI_SIGNALED) 106bf215546Sopenharmony_ci submit->wait_wsi_count++; 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci} 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_cistatic void 111bf215546Sopenharmony_civn_queue_submission_count_semaphores(struct vn_queue_submission *submit) 112bf215546Sopenharmony_ci{ 113bf215546Sopenharmony_ci submit->wait_semaphore_count = 0; 114bf215546Sopenharmony_ci submit->wait_wsi_count = 0; 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci for (uint32_t i = 0; i < submit->batch_count; i++) 117bf215546Sopenharmony_ci vn_queue_submission_count_batch_semaphores(submit, i); 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_cistatic VkResult 121bf215546Sopenharmony_civn_queue_submission_alloc_storage(struct vn_queue_submission *submit) 122bf215546Sopenharmony_ci{ 123bf215546Sopenharmony_ci struct vn_queue *queue = vn_queue_from_handle(submit->queue); 124bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = &queue->device->base.base.alloc; 125bf215546Sopenharmony_ci size_t alloc_size = 0; 126bf215546Sopenharmony_ci size_t semaphores_offset = 0; 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci /* we want to filter out VN_SYNC_TYPE_WSI_SIGNALED wait semaphores */ 129bf215546Sopenharmony_ci if (submit->wait_wsi_count) { 130bf215546Sopenharmony_ci switch (submit->batch_type) { 131bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_SUBMIT_INFO: 132bf215546Sopenharmony_ci alloc_size += sizeof(VkSubmitInfo) * submit->batch_count; 133bf215546Sopenharmony_ci break; 134bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_BIND_SPARSE_INFO: 135bf215546Sopenharmony_ci alloc_size += sizeof(VkBindSparseInfo) * submit->batch_count; 136bf215546Sopenharmony_ci break; 137bf215546Sopenharmony_ci default: 138bf215546Sopenharmony_ci unreachable("unexpected batch type"); 139bf215546Sopenharmony_ci break; 140bf215546Sopenharmony_ci } 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci semaphores_offset = alloc_size; 143bf215546Sopenharmony_ci alloc_size += sizeof(*submit->temp.semaphores) * 144bf215546Sopenharmony_ci (submit->wait_semaphore_count - submit->wait_wsi_count); 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci if (!alloc_size) { 148bf215546Sopenharmony_ci submit->temp.storage = NULL; 149bf215546Sopenharmony_ci return VK_SUCCESS; 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci submit->temp.storage = vk_alloc(alloc, alloc_size, VN_DEFAULT_ALIGN, 153bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 154bf215546Sopenharmony_ci if (!submit->temp.storage) 155bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci submit->temp.batches = submit->temp.storage; 158bf215546Sopenharmony_ci submit->temp.semaphores = submit->temp.storage + semaphores_offset; 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci return VK_SUCCESS; 161bf215546Sopenharmony_ci} 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_cistatic uint32_t 164bf215546Sopenharmony_civn_queue_submission_filter_batch_wsi_semaphores( 165bf215546Sopenharmony_ci struct vn_queue_submission *submit, 166bf215546Sopenharmony_ci uint32_t batch_index, 167bf215546Sopenharmony_ci uint32_t sem_base) 168bf215546Sopenharmony_ci{ 169bf215546Sopenharmony_ci struct vn_queue *queue = vn_queue_from_handle(submit->queue); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci union { 172bf215546Sopenharmony_ci VkSubmitInfo *submit_batch; 173bf215546Sopenharmony_ci VkBindSparseInfo *bind_sparse_batch; 174bf215546Sopenharmony_ci } u; 175bf215546Sopenharmony_ci const VkSemaphore *src_sems; 176bf215546Sopenharmony_ci uint32_t src_count; 177bf215546Sopenharmony_ci switch (submit->batch_type) { 178bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_SUBMIT_INFO: 179bf215546Sopenharmony_ci u.submit_batch = &submit->temp.submit_batches[batch_index]; 180bf215546Sopenharmony_ci src_sems = u.submit_batch->pWaitSemaphores; 181bf215546Sopenharmony_ci src_count = u.submit_batch->waitSemaphoreCount; 182bf215546Sopenharmony_ci break; 183bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_BIND_SPARSE_INFO: 184bf215546Sopenharmony_ci u.bind_sparse_batch = &submit->temp.bind_sparse_batches[batch_index]; 185bf215546Sopenharmony_ci src_sems = u.bind_sparse_batch->pWaitSemaphores; 186bf215546Sopenharmony_ci src_count = u.bind_sparse_batch->waitSemaphoreCount; 187bf215546Sopenharmony_ci break; 188bf215546Sopenharmony_ci default: 189bf215546Sopenharmony_ci unreachable("unexpected batch type"); 190bf215546Sopenharmony_ci break; 191bf215546Sopenharmony_ci } 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci VkSemaphore *dst_sems = &submit->temp.semaphores[sem_base]; 194bf215546Sopenharmony_ci uint32_t dst_count = 0; 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci /* filter out VN_SYNC_TYPE_WSI_SIGNALED wait semaphores */ 197bf215546Sopenharmony_ci for (uint32_t i = 0; i < src_count; i++) { 198bf215546Sopenharmony_ci struct vn_semaphore *sem = vn_semaphore_from_handle(src_sems[i]); 199bf215546Sopenharmony_ci const struct vn_sync_payload *payload = sem->payload; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci if (payload->type == VN_SYNC_TYPE_WSI_SIGNALED) 202bf215546Sopenharmony_ci vn_semaphore_reset_wsi(queue->device, sem); 203bf215546Sopenharmony_ci else 204bf215546Sopenharmony_ci dst_sems[dst_count++] = src_sems[i]; 205bf215546Sopenharmony_ci } 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci switch (submit->batch_type) { 208bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_SUBMIT_INFO: 209bf215546Sopenharmony_ci u.submit_batch->pWaitSemaphores = dst_sems; 210bf215546Sopenharmony_ci u.submit_batch->waitSemaphoreCount = dst_count; 211bf215546Sopenharmony_ci break; 212bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_BIND_SPARSE_INFO: 213bf215546Sopenharmony_ci u.bind_sparse_batch->pWaitSemaphores = dst_sems; 214bf215546Sopenharmony_ci u.bind_sparse_batch->waitSemaphoreCount = dst_count; 215bf215546Sopenharmony_ci break; 216bf215546Sopenharmony_ci default: 217bf215546Sopenharmony_ci break; 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci return dst_count; 221bf215546Sopenharmony_ci} 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_cistatic void 224bf215546Sopenharmony_civn_queue_submission_setup_batches(struct vn_queue_submission *submit) 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci if (!submit->temp.storage) 227bf215546Sopenharmony_ci return; 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci /* make a copy because we need to filter out WSI semaphores */ 230bf215546Sopenharmony_ci if (submit->wait_wsi_count) { 231bf215546Sopenharmony_ci switch (submit->batch_type) { 232bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_SUBMIT_INFO: 233bf215546Sopenharmony_ci memcpy(submit->temp.submit_batches, submit->submit_batches, 234bf215546Sopenharmony_ci sizeof(submit->submit_batches[0]) * submit->batch_count); 235bf215546Sopenharmony_ci submit->submit_batches = submit->temp.submit_batches; 236bf215546Sopenharmony_ci break; 237bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_BIND_SPARSE_INFO: 238bf215546Sopenharmony_ci memcpy(submit->temp.bind_sparse_batches, submit->bind_sparse_batches, 239bf215546Sopenharmony_ci sizeof(submit->bind_sparse_batches[0]) * submit->batch_count); 240bf215546Sopenharmony_ci submit->bind_sparse_batches = submit->temp.bind_sparse_batches; 241bf215546Sopenharmony_ci break; 242bf215546Sopenharmony_ci default: 243bf215546Sopenharmony_ci unreachable("unexpected batch type"); 244bf215546Sopenharmony_ci break; 245bf215546Sopenharmony_ci } 246bf215546Sopenharmony_ci } 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci uint32_t wait_sem_base = 0; 249bf215546Sopenharmony_ci for (uint32_t i = 0; i < submit->batch_count; i++) { 250bf215546Sopenharmony_ci if (submit->wait_wsi_count) { 251bf215546Sopenharmony_ci wait_sem_base += vn_queue_submission_filter_batch_wsi_semaphores( 252bf215546Sopenharmony_ci submit, i, wait_sem_base); 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci } 255bf215546Sopenharmony_ci} 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_cistatic VkResult 258bf215546Sopenharmony_civn_queue_submission_prepare_submit(struct vn_queue_submission *submit, 259bf215546Sopenharmony_ci VkQueue queue, 260bf215546Sopenharmony_ci uint32_t batch_count, 261bf215546Sopenharmony_ci const VkSubmitInfo *submit_batches, 262bf215546Sopenharmony_ci VkFence fence) 263bf215546Sopenharmony_ci{ 264bf215546Sopenharmony_ci submit->batch_type = VK_STRUCTURE_TYPE_SUBMIT_INFO; 265bf215546Sopenharmony_ci submit->queue = queue; 266bf215546Sopenharmony_ci submit->batch_count = batch_count; 267bf215546Sopenharmony_ci submit->submit_batches = submit_batches; 268bf215546Sopenharmony_ci submit->fence = fence; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci vn_queue_submission_count_semaphores(submit); 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci VkResult result = vn_queue_submission_alloc_storage(submit); 273bf215546Sopenharmony_ci if (result != VK_SUCCESS) 274bf215546Sopenharmony_ci return result; 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci vn_queue_submission_setup_batches(submit); 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci return VK_SUCCESS; 279bf215546Sopenharmony_ci} 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_cistatic VkResult 282bf215546Sopenharmony_civn_queue_submission_prepare_bind_sparse( 283bf215546Sopenharmony_ci struct vn_queue_submission *submit, 284bf215546Sopenharmony_ci VkQueue queue, 285bf215546Sopenharmony_ci uint32_t batch_count, 286bf215546Sopenharmony_ci const VkBindSparseInfo *bind_sparse_batches, 287bf215546Sopenharmony_ci VkFence fence) 288bf215546Sopenharmony_ci{ 289bf215546Sopenharmony_ci submit->batch_type = VK_STRUCTURE_TYPE_BIND_SPARSE_INFO; 290bf215546Sopenharmony_ci submit->queue = queue; 291bf215546Sopenharmony_ci submit->batch_count = batch_count; 292bf215546Sopenharmony_ci submit->bind_sparse_batches = bind_sparse_batches; 293bf215546Sopenharmony_ci submit->fence = fence; 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ci vn_queue_submission_count_semaphores(submit); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci VkResult result = vn_queue_submission_alloc_storage(submit); 298bf215546Sopenharmony_ci if (result != VK_SUCCESS) 299bf215546Sopenharmony_ci return result; 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci vn_queue_submission_setup_batches(submit); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci return VK_SUCCESS; 304bf215546Sopenharmony_ci} 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_cistatic void 307bf215546Sopenharmony_civn_queue_submission_cleanup(struct vn_queue_submission *submit) 308bf215546Sopenharmony_ci{ 309bf215546Sopenharmony_ci struct vn_queue *queue = vn_queue_from_handle(submit->queue); 310bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = &queue->device->base.base.alloc; 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci vk_free(alloc, submit->temp.storage); 313bf215546Sopenharmony_ci} 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_cistatic inline uint32_t 316bf215546Sopenharmony_civn_queue_family_array_index(struct vn_queue *queue) 317bf215546Sopenharmony_ci{ 318bf215546Sopenharmony_ci for (uint32_t i = 0; i < queue->device->queue_family_count; i++) { 319bf215546Sopenharmony_ci if (queue->device->queue_families[i] == queue->family) 320bf215546Sopenharmony_ci return i; 321bf215546Sopenharmony_ci } 322bf215546Sopenharmony_ci unreachable("invalid queue"); 323bf215546Sopenharmony_ci} 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_cistatic VkResult 326bf215546Sopenharmony_civn_queue_submit(struct vn_instance *instance, 327bf215546Sopenharmony_ci VkQueue queue_handle, 328bf215546Sopenharmony_ci uint32_t batch_count, 329bf215546Sopenharmony_ci const VkSubmitInfo *batches, 330bf215546Sopenharmony_ci VkFence fence_handle, 331bf215546Sopenharmony_ci bool sync_submit) 332bf215546Sopenharmony_ci{ 333bf215546Sopenharmony_ci /* skip no-op submit */ 334bf215546Sopenharmony_ci if (!batch_count && fence_handle == VK_NULL_HANDLE) 335bf215546Sopenharmony_ci return VK_SUCCESS; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci if (sync_submit) { 338bf215546Sopenharmony_ci return vn_call_vkQueueSubmit(instance, queue_handle, batch_count, 339bf215546Sopenharmony_ci batches, fence_handle); 340bf215546Sopenharmony_ci } 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci vn_async_vkQueueSubmit(instance, queue_handle, batch_count, batches, 343bf215546Sopenharmony_ci fence_handle); 344bf215546Sopenharmony_ci return VK_SUCCESS; 345bf215546Sopenharmony_ci} 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ciVkResult 348bf215546Sopenharmony_civn_QueueSubmit(VkQueue _queue, 349bf215546Sopenharmony_ci uint32_t submitCount, 350bf215546Sopenharmony_ci const VkSubmitInfo *pSubmits, 351bf215546Sopenharmony_ci VkFence _fence) 352bf215546Sopenharmony_ci{ 353bf215546Sopenharmony_ci VN_TRACE_FUNC(); 354bf215546Sopenharmony_ci struct vn_queue *queue = vn_queue_from_handle(_queue); 355bf215546Sopenharmony_ci struct vn_device *dev = queue->device; 356bf215546Sopenharmony_ci struct vn_fence *fence = vn_fence_from_handle(_fence); 357bf215546Sopenharmony_ci const bool external_fence = fence && fence->is_external; 358bf215546Sopenharmony_ci const bool feedback_fence = fence && fence->feedback.slot; 359bf215546Sopenharmony_ci struct vn_queue_submission submit; 360bf215546Sopenharmony_ci const struct vn_device_memory *wsi_mem = NULL; 361bf215546Sopenharmony_ci bool sync_submit; 362bf215546Sopenharmony_ci VkResult result; 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci result = vn_queue_submission_prepare_submit(&submit, _queue, submitCount, 365bf215546Sopenharmony_ci pSubmits, _fence); 366bf215546Sopenharmony_ci if (result != VK_SUCCESS) 367bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci if (submit.batch_count == 1) { 370bf215546Sopenharmony_ci const struct wsi_memory_signal_submit_info *info = vk_find_struct_const( 371bf215546Sopenharmony_ci submit.submit_batches[0].pNext, WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA); 372bf215546Sopenharmony_ci if (info) { 373bf215546Sopenharmony_ci wsi_mem = vn_device_memory_from_handle(info->memory); 374bf215546Sopenharmony_ci assert(!wsi_mem->base_memory && wsi_mem->base_bo); 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci } 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci /* force synchronous submission if any of the below applies: 379bf215546Sopenharmony_ci * - struct wsi_memory_signal_submit_info 380bf215546Sopenharmony_ci * - fence is an external fence 381bf215546Sopenharmony_ci * - NO_ASYNC_QUEUE_SUBMIT perf option enabled 382bf215546Sopenharmony_ci */ 383bf215546Sopenharmony_ci sync_submit = wsi_mem || external_fence || VN_PERF(NO_ASYNC_QUEUE_SUBMIT); 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci /* if the original submission involves a feedback fence: 386bf215546Sopenharmony_ci * - defer the feedback fence to another submit to avoid deep copy 387bf215546Sopenharmony_ci * - defer the potential sync_submit to the feedback fence submission 388bf215546Sopenharmony_ci */ 389bf215546Sopenharmony_ci result = vn_queue_submit(dev->instance, submit.queue, submit.batch_count, 390bf215546Sopenharmony_ci submit.submit_batches, 391bf215546Sopenharmony_ci feedback_fence ? VK_NULL_HANDLE : submit.fence, 392bf215546Sopenharmony_ci !feedback_fence && sync_submit); 393bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 394bf215546Sopenharmony_ci vn_queue_submission_cleanup(&submit); 395bf215546Sopenharmony_ci return vn_error(dev->instance, result); 396bf215546Sopenharmony_ci } 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci /* TODO intercept original submit batches to append the fence feedback cmd 399bf215546Sopenharmony_ci * with a per-queue cached submission builder to avoid transient allocs. 400bf215546Sopenharmony_ci * 401bf215546Sopenharmony_ci * vn_queue_submission bits must be fixed for VkTimelineSemaphoreSubmitInfo 402bf215546Sopenharmony_ci * before adding timeline semaphore feedback. 403bf215546Sopenharmony_ci */ 404bf215546Sopenharmony_ci if (feedback_fence) { 405bf215546Sopenharmony_ci const uint32_t feedback_cmd_index = vn_queue_family_array_index(queue); 406bf215546Sopenharmony_ci const VkSubmitInfo info = { 407bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, 408bf215546Sopenharmony_ci .pNext = NULL, 409bf215546Sopenharmony_ci .waitSemaphoreCount = 0, 410bf215546Sopenharmony_ci .pWaitSemaphores = NULL, 411bf215546Sopenharmony_ci .pWaitDstStageMask = NULL, 412bf215546Sopenharmony_ci .commandBufferCount = 1, 413bf215546Sopenharmony_ci .pCommandBuffers = &fence->feedback.commands[feedback_cmd_index], 414bf215546Sopenharmony_ci }; 415bf215546Sopenharmony_ci result = vn_queue_submit(dev->instance, submit.queue, 1, &info, 416bf215546Sopenharmony_ci submit.fence, sync_submit); 417bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 418bf215546Sopenharmony_ci vn_queue_submission_cleanup(&submit); 419bf215546Sopenharmony_ci return vn_error(dev->instance, result); 420bf215546Sopenharmony_ci } 421bf215546Sopenharmony_ci } 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci if (wsi_mem) { 424bf215546Sopenharmony_ci /* XXX this is always false and kills the performance */ 425bf215546Sopenharmony_ci if (dev->instance->renderer->info.has_implicit_fencing) { 426bf215546Sopenharmony_ci vn_renderer_submit(dev->renderer, &(const struct vn_renderer_submit){ 427bf215546Sopenharmony_ci .bos = &wsi_mem->base_bo, 428bf215546Sopenharmony_ci .bo_count = 1, 429bf215546Sopenharmony_ci }); 430bf215546Sopenharmony_ci } else { 431bf215546Sopenharmony_ci if (VN_DEBUG(WSI)) { 432bf215546Sopenharmony_ci static uint32_t ratelimit; 433bf215546Sopenharmony_ci if (ratelimit < 10) { 434bf215546Sopenharmony_ci vn_log(dev->instance, 435bf215546Sopenharmony_ci "forcing vkQueueWaitIdle before presenting"); 436bf215546Sopenharmony_ci ratelimit++; 437bf215546Sopenharmony_ci } 438bf215546Sopenharmony_ci } 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci vn_QueueWaitIdle(submit.queue); 441bf215546Sopenharmony_ci } 442bf215546Sopenharmony_ci } 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_ci vn_queue_submission_cleanup(&submit); 445bf215546Sopenharmony_ci 446bf215546Sopenharmony_ci return VK_SUCCESS; 447bf215546Sopenharmony_ci} 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_ciVkResult 450bf215546Sopenharmony_civn_QueueBindSparse(VkQueue _queue, 451bf215546Sopenharmony_ci uint32_t bindInfoCount, 452bf215546Sopenharmony_ci const VkBindSparseInfo *pBindInfo, 453bf215546Sopenharmony_ci VkFence fence) 454bf215546Sopenharmony_ci{ 455bf215546Sopenharmony_ci VN_TRACE_FUNC(); 456bf215546Sopenharmony_ci struct vn_queue *queue = vn_queue_from_handle(_queue); 457bf215546Sopenharmony_ci struct vn_device *dev = queue->device; 458bf215546Sopenharmony_ci 459bf215546Sopenharmony_ci /* TODO allow sparse resource along with sync feedback */ 460bf215546Sopenharmony_ci assert(VN_PERF(NO_FENCE_FEEDBACK)); 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci struct vn_queue_submission submit; 463bf215546Sopenharmony_ci VkResult result = vn_queue_submission_prepare_bind_sparse( 464bf215546Sopenharmony_ci &submit, _queue, bindInfoCount, pBindInfo, fence); 465bf215546Sopenharmony_ci if (result != VK_SUCCESS) 466bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci result = vn_call_vkQueueBindSparse( 469bf215546Sopenharmony_ci dev->instance, submit.queue, submit.batch_count, 470bf215546Sopenharmony_ci submit.bind_sparse_batches, submit.fence); 471bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 472bf215546Sopenharmony_ci vn_queue_submission_cleanup(&submit); 473bf215546Sopenharmony_ci return vn_error(dev->instance, result); 474bf215546Sopenharmony_ci } 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ci vn_queue_submission_cleanup(&submit); 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci return VK_SUCCESS; 479bf215546Sopenharmony_ci} 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ciVkResult 482bf215546Sopenharmony_civn_QueueWaitIdle(VkQueue _queue) 483bf215546Sopenharmony_ci{ 484bf215546Sopenharmony_ci VN_TRACE_FUNC(); 485bf215546Sopenharmony_ci struct vn_queue *queue = vn_queue_from_handle(_queue); 486bf215546Sopenharmony_ci VkDevice device = vn_device_to_handle(queue->device); 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci VkResult result = vn_QueueSubmit(_queue, 0, NULL, queue->wait_fence); 489bf215546Sopenharmony_ci if (result != VK_SUCCESS) 490bf215546Sopenharmony_ci return result; 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci result = vn_WaitForFences(device, 1, &queue->wait_fence, true, UINT64_MAX); 493bf215546Sopenharmony_ci vn_ResetFences(device, 1, &queue->wait_fence); 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci return vn_result(queue->device->instance, result); 496bf215546Sopenharmony_ci} 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci/* fence commands */ 499bf215546Sopenharmony_ci 500bf215546Sopenharmony_cistatic void 501bf215546Sopenharmony_civn_sync_payload_release(struct vn_device *dev, 502bf215546Sopenharmony_ci struct vn_sync_payload *payload) 503bf215546Sopenharmony_ci{ 504bf215546Sopenharmony_ci payload->type = VN_SYNC_TYPE_INVALID; 505bf215546Sopenharmony_ci} 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_cistatic VkResult 508bf215546Sopenharmony_civn_fence_init_payloads(struct vn_device *dev, 509bf215546Sopenharmony_ci struct vn_fence *fence, 510bf215546Sopenharmony_ci bool signaled, 511bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 512bf215546Sopenharmony_ci{ 513bf215546Sopenharmony_ci fence->permanent.type = VN_SYNC_TYPE_DEVICE_ONLY; 514bf215546Sopenharmony_ci fence->temporary.type = VN_SYNC_TYPE_INVALID; 515bf215546Sopenharmony_ci fence->payload = &fence->permanent; 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci return VK_SUCCESS; 518bf215546Sopenharmony_ci} 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_civoid 521bf215546Sopenharmony_civn_fence_signal_wsi(struct vn_device *dev, struct vn_fence *fence) 522bf215546Sopenharmony_ci{ 523bf215546Sopenharmony_ci struct vn_sync_payload *temp = &fence->temporary; 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci vn_sync_payload_release(dev, temp); 526bf215546Sopenharmony_ci temp->type = VN_SYNC_TYPE_WSI_SIGNALED; 527bf215546Sopenharmony_ci fence->payload = temp; 528bf215546Sopenharmony_ci} 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_cistatic VkResult 531bf215546Sopenharmony_civn_fence_feedback_init(struct vn_device *dev, 532bf215546Sopenharmony_ci struct vn_fence *fence, 533bf215546Sopenharmony_ci bool signaled, 534bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 535bf215546Sopenharmony_ci{ 536bf215546Sopenharmony_ci VkDevice dev_handle = vn_device_to_handle(dev); 537bf215546Sopenharmony_ci struct vn_feedback_slot *slot; 538bf215546Sopenharmony_ci VkCommandBuffer *cmd_handles; 539bf215546Sopenharmony_ci VkResult result; 540bf215546Sopenharmony_ci 541bf215546Sopenharmony_ci if (fence->is_external) 542bf215546Sopenharmony_ci return VK_SUCCESS; 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_ci /* Fence feedback implementation relies on vkWaitForFences to cover the gap 545bf215546Sopenharmony_ci * between feedback slot signaling and the actual fence signal operation. 546bf215546Sopenharmony_ci */ 547bf215546Sopenharmony_ci if (unlikely(!dev->instance->renderer->info.allow_vk_wait_syncs)) 548bf215546Sopenharmony_ci return VK_SUCCESS; 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci if (VN_PERF(NO_FENCE_FEEDBACK)) 551bf215546Sopenharmony_ci return VK_SUCCESS; 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci slot = vn_feedback_pool_alloc(&dev->feedback_pool, VN_FEEDBACK_TYPE_FENCE); 554bf215546Sopenharmony_ci if (!slot) 555bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_ci vn_feedback_set_status(slot, signaled ? VK_SUCCESS : VK_NOT_READY); 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci cmd_handles = 560bf215546Sopenharmony_ci vk_zalloc(alloc, sizeof(*cmd_handles) * dev->queue_family_count, 561bf215546Sopenharmony_ci VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 562bf215546Sopenharmony_ci if (!cmd_handles) { 563bf215546Sopenharmony_ci vn_feedback_pool_free(&dev->feedback_pool, slot); 564bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 565bf215546Sopenharmony_ci } 566bf215546Sopenharmony_ci 567bf215546Sopenharmony_ci for (uint32_t i = 0; i < dev->queue_family_count; i++) { 568bf215546Sopenharmony_ci result = vn_feedback_fence_cmd_alloc(dev_handle, &dev->cmd_pools[i], 569bf215546Sopenharmony_ci slot, &cmd_handles[i]); 570bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 571bf215546Sopenharmony_ci for (uint32_t j = 0; j < i; j++) { 572bf215546Sopenharmony_ci vn_feedback_fence_cmd_free(dev_handle, &dev->cmd_pools[j], 573bf215546Sopenharmony_ci cmd_handles[j]); 574bf215546Sopenharmony_ci } 575bf215546Sopenharmony_ci break; 576bf215546Sopenharmony_ci } 577bf215546Sopenharmony_ci } 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 580bf215546Sopenharmony_ci vk_free(alloc, cmd_handles); 581bf215546Sopenharmony_ci vn_feedback_pool_free(&dev->feedback_pool, slot); 582bf215546Sopenharmony_ci return result; 583bf215546Sopenharmony_ci } 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci fence->feedback.slot = slot; 586bf215546Sopenharmony_ci fence->feedback.commands = cmd_handles; 587bf215546Sopenharmony_ci 588bf215546Sopenharmony_ci return VK_SUCCESS; 589bf215546Sopenharmony_ci} 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_cistatic void 592bf215546Sopenharmony_civn_fence_feedback_fini(struct vn_device *dev, 593bf215546Sopenharmony_ci struct vn_fence *fence, 594bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 595bf215546Sopenharmony_ci{ 596bf215546Sopenharmony_ci VkDevice dev_handle = vn_device_to_handle(dev); 597bf215546Sopenharmony_ci 598bf215546Sopenharmony_ci if (!fence->feedback.slot) 599bf215546Sopenharmony_ci return; 600bf215546Sopenharmony_ci 601bf215546Sopenharmony_ci for (uint32_t i = 0; i < dev->queue_family_count; i++) { 602bf215546Sopenharmony_ci vn_feedback_fence_cmd_free(dev_handle, &dev->cmd_pools[i], 603bf215546Sopenharmony_ci fence->feedback.commands[i]); 604bf215546Sopenharmony_ci } 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_ci vn_feedback_pool_free(&dev->feedback_pool, fence->feedback.slot); 607bf215546Sopenharmony_ci 608bf215546Sopenharmony_ci vk_free(alloc, fence->feedback.commands); 609bf215546Sopenharmony_ci} 610bf215546Sopenharmony_ci 611bf215546Sopenharmony_ciVkResult 612bf215546Sopenharmony_civn_CreateFence(VkDevice device, 613bf215546Sopenharmony_ci const VkFenceCreateInfo *pCreateInfo, 614bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 615bf215546Sopenharmony_ci VkFence *pFence) 616bf215546Sopenharmony_ci{ 617bf215546Sopenharmony_ci VN_TRACE_FUNC(); 618bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 619bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 620bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 621bf215546Sopenharmony_ci const bool signaled = pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT; 622bf215546Sopenharmony_ci VkResult result; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci struct vn_fence *fence = vk_zalloc(alloc, sizeof(*fence), VN_DEFAULT_ALIGN, 625bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 626bf215546Sopenharmony_ci if (!fence) 627bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci vn_object_base_init(&fence->base, VK_OBJECT_TYPE_FENCE, &dev->base); 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci const struct VkExportFenceCreateInfo *export_info = 632bf215546Sopenharmony_ci vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO); 633bf215546Sopenharmony_ci VkFenceCreateInfo local_create_info; 634bf215546Sopenharmony_ci if (export_info) { 635bf215546Sopenharmony_ci local_create_info = *pCreateInfo; 636bf215546Sopenharmony_ci local_create_info.pNext = NULL; 637bf215546Sopenharmony_ci pCreateInfo = &local_create_info; 638bf215546Sopenharmony_ci 639bf215546Sopenharmony_ci fence->is_external = !!export_info->handleTypes; 640bf215546Sopenharmony_ci } 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_ci result = vn_fence_init_payloads(dev, fence, signaled, alloc); 643bf215546Sopenharmony_ci if (result != VK_SUCCESS) 644bf215546Sopenharmony_ci goto out_object_base_fini; 645bf215546Sopenharmony_ci 646bf215546Sopenharmony_ci result = vn_fence_feedback_init(dev, fence, signaled, alloc); 647bf215546Sopenharmony_ci if (result != VK_SUCCESS) 648bf215546Sopenharmony_ci goto out_payloads_fini; 649bf215546Sopenharmony_ci 650bf215546Sopenharmony_ci *pFence = vn_fence_to_handle(fence); 651bf215546Sopenharmony_ci vn_async_vkCreateFence(dev->instance, device, pCreateInfo, NULL, pFence); 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci return VK_SUCCESS; 654bf215546Sopenharmony_ci 655bf215546Sopenharmony_ciout_payloads_fini: 656bf215546Sopenharmony_ci vn_sync_payload_release(dev, &fence->permanent); 657bf215546Sopenharmony_ci vn_sync_payload_release(dev, &fence->temporary); 658bf215546Sopenharmony_ci 659bf215546Sopenharmony_ciout_object_base_fini: 660bf215546Sopenharmony_ci vn_object_base_fini(&fence->base); 661bf215546Sopenharmony_ci vk_free(alloc, fence); 662bf215546Sopenharmony_ci return vn_error(dev->instance, result); 663bf215546Sopenharmony_ci} 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_civoid 666bf215546Sopenharmony_civn_DestroyFence(VkDevice device, 667bf215546Sopenharmony_ci VkFence _fence, 668bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 669bf215546Sopenharmony_ci{ 670bf215546Sopenharmony_ci VN_TRACE_FUNC(); 671bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 672bf215546Sopenharmony_ci struct vn_fence *fence = vn_fence_from_handle(_fence); 673bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 674bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_ci if (!fence) 677bf215546Sopenharmony_ci return; 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_ci vn_async_vkDestroyFence(dev->instance, device, _fence, NULL); 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_ci vn_fence_feedback_fini(dev, fence, alloc); 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_ci vn_sync_payload_release(dev, &fence->permanent); 684bf215546Sopenharmony_ci vn_sync_payload_release(dev, &fence->temporary); 685bf215546Sopenharmony_ci 686bf215546Sopenharmony_ci vn_object_base_fini(&fence->base); 687bf215546Sopenharmony_ci vk_free(alloc, fence); 688bf215546Sopenharmony_ci} 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ciVkResult 691bf215546Sopenharmony_civn_ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) 692bf215546Sopenharmony_ci{ 693bf215546Sopenharmony_ci VN_TRACE_FUNC(); 694bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci /* TODO if the fence is shared-by-ref, this needs to be synchronous */ 697bf215546Sopenharmony_ci if (false) 698bf215546Sopenharmony_ci vn_call_vkResetFences(dev->instance, device, fenceCount, pFences); 699bf215546Sopenharmony_ci else 700bf215546Sopenharmony_ci vn_async_vkResetFences(dev->instance, device, fenceCount, pFences); 701bf215546Sopenharmony_ci 702bf215546Sopenharmony_ci for (uint32_t i = 0; i < fenceCount; i++) { 703bf215546Sopenharmony_ci struct vn_fence *fence = vn_fence_from_handle(pFences[i]); 704bf215546Sopenharmony_ci struct vn_sync_payload *perm = &fence->permanent; 705bf215546Sopenharmony_ci 706bf215546Sopenharmony_ci vn_sync_payload_release(dev, &fence->temporary); 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_ci assert(perm->type == VN_SYNC_TYPE_DEVICE_ONLY); 709bf215546Sopenharmony_ci fence->payload = perm; 710bf215546Sopenharmony_ci 711bf215546Sopenharmony_ci if (fence->feedback.slot) 712bf215546Sopenharmony_ci vn_feedback_reset_status(fence->feedback.slot); 713bf215546Sopenharmony_ci } 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci return VK_SUCCESS; 716bf215546Sopenharmony_ci} 717bf215546Sopenharmony_ci 718bf215546Sopenharmony_ciVkResult 719bf215546Sopenharmony_civn_GetFenceStatus(VkDevice device, VkFence _fence) 720bf215546Sopenharmony_ci{ 721bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 722bf215546Sopenharmony_ci struct vn_fence *fence = vn_fence_from_handle(_fence); 723bf215546Sopenharmony_ci struct vn_sync_payload *payload = fence->payload; 724bf215546Sopenharmony_ci 725bf215546Sopenharmony_ci VkResult result; 726bf215546Sopenharmony_ci switch (payload->type) { 727bf215546Sopenharmony_ci case VN_SYNC_TYPE_DEVICE_ONLY: 728bf215546Sopenharmony_ci if (fence->feedback.slot) { 729bf215546Sopenharmony_ci result = vn_feedback_get_status(fence->feedback.slot); 730bf215546Sopenharmony_ci if (result == VK_SUCCESS) { 731bf215546Sopenharmony_ci /* When fence feedback slot gets signaled, the real fence 732bf215546Sopenharmony_ci * signal operation follows after but the signaling isr can be 733bf215546Sopenharmony_ci * deferred or preempted. To avoid theoretical racing, we let 734bf215546Sopenharmony_ci * the renderer wait for the fence. This also helps resolve 735bf215546Sopenharmony_ci * synchronization validation errors, because the layer no 736bf215546Sopenharmony_ci * longer sees any fence status checks and falsely believes the 737bf215546Sopenharmony_ci * caller does not sync. 738bf215546Sopenharmony_ci */ 739bf215546Sopenharmony_ci vn_async_vkWaitForFences(dev->instance, device, 1, &_fence, 740bf215546Sopenharmony_ci VK_TRUE, UINT64_MAX); 741bf215546Sopenharmony_ci } 742bf215546Sopenharmony_ci } else { 743bf215546Sopenharmony_ci result = vn_call_vkGetFenceStatus(dev->instance, device, _fence); 744bf215546Sopenharmony_ci } 745bf215546Sopenharmony_ci break; 746bf215546Sopenharmony_ci case VN_SYNC_TYPE_WSI_SIGNALED: 747bf215546Sopenharmony_ci result = VK_SUCCESS; 748bf215546Sopenharmony_ci break; 749bf215546Sopenharmony_ci default: 750bf215546Sopenharmony_ci unreachable("unexpected fence payload type"); 751bf215546Sopenharmony_ci break; 752bf215546Sopenharmony_ci } 753bf215546Sopenharmony_ci 754bf215546Sopenharmony_ci return vn_result(dev->instance, result); 755bf215546Sopenharmony_ci} 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_cistatic VkResult 758bf215546Sopenharmony_civn_find_first_signaled_fence(VkDevice device, 759bf215546Sopenharmony_ci const VkFence *fences, 760bf215546Sopenharmony_ci uint32_t count) 761bf215546Sopenharmony_ci{ 762bf215546Sopenharmony_ci for (uint32_t i = 0; i < count; i++) { 763bf215546Sopenharmony_ci VkResult result = vn_GetFenceStatus(device, fences[i]); 764bf215546Sopenharmony_ci if (result == VK_SUCCESS || result < 0) 765bf215546Sopenharmony_ci return result; 766bf215546Sopenharmony_ci } 767bf215546Sopenharmony_ci return VK_NOT_READY; 768bf215546Sopenharmony_ci} 769bf215546Sopenharmony_ci 770bf215546Sopenharmony_cistatic VkResult 771bf215546Sopenharmony_civn_remove_signaled_fences(VkDevice device, VkFence *fences, uint32_t *count) 772bf215546Sopenharmony_ci{ 773bf215546Sopenharmony_ci uint32_t cur = 0; 774bf215546Sopenharmony_ci for (uint32_t i = 0; i < *count; i++) { 775bf215546Sopenharmony_ci VkResult result = vn_GetFenceStatus(device, fences[i]); 776bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 777bf215546Sopenharmony_ci if (result < 0) 778bf215546Sopenharmony_ci return result; 779bf215546Sopenharmony_ci fences[cur++] = fences[i]; 780bf215546Sopenharmony_ci } 781bf215546Sopenharmony_ci } 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_ci *count = cur; 784bf215546Sopenharmony_ci return cur ? VK_NOT_READY : VK_SUCCESS; 785bf215546Sopenharmony_ci} 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_cistatic VkResult 788bf215546Sopenharmony_civn_update_sync_result(VkResult result, int64_t abs_timeout, uint32_t *iter) 789bf215546Sopenharmony_ci{ 790bf215546Sopenharmony_ci switch (result) { 791bf215546Sopenharmony_ci case VK_NOT_READY: 792bf215546Sopenharmony_ci if (abs_timeout != OS_TIMEOUT_INFINITE && 793bf215546Sopenharmony_ci os_time_get_nano() >= abs_timeout) 794bf215546Sopenharmony_ci result = VK_TIMEOUT; 795bf215546Sopenharmony_ci else 796bf215546Sopenharmony_ci vn_relax(iter, "client"); 797bf215546Sopenharmony_ci break; 798bf215546Sopenharmony_ci default: 799bf215546Sopenharmony_ci assert(result == VK_SUCCESS || result < 0); 800bf215546Sopenharmony_ci break; 801bf215546Sopenharmony_ci } 802bf215546Sopenharmony_ci 803bf215546Sopenharmony_ci return result; 804bf215546Sopenharmony_ci} 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ciVkResult 807bf215546Sopenharmony_civn_WaitForFences(VkDevice device, 808bf215546Sopenharmony_ci uint32_t fenceCount, 809bf215546Sopenharmony_ci const VkFence *pFences, 810bf215546Sopenharmony_ci VkBool32 waitAll, 811bf215546Sopenharmony_ci uint64_t timeout) 812bf215546Sopenharmony_ci{ 813bf215546Sopenharmony_ci VN_TRACE_FUNC(); 814bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 815bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 816bf215546Sopenharmony_ci 817bf215546Sopenharmony_ci const int64_t abs_timeout = os_time_get_absolute_timeout(timeout); 818bf215546Sopenharmony_ci VkResult result = VK_NOT_READY; 819bf215546Sopenharmony_ci uint32_t iter = 0; 820bf215546Sopenharmony_ci if (fenceCount > 1 && waitAll) { 821bf215546Sopenharmony_ci VkFence local_fences[8]; 822bf215546Sopenharmony_ci VkFence *fences = local_fences; 823bf215546Sopenharmony_ci if (fenceCount > ARRAY_SIZE(local_fences)) { 824bf215546Sopenharmony_ci fences = 825bf215546Sopenharmony_ci vk_alloc(alloc, sizeof(*fences) * fenceCount, VN_DEFAULT_ALIGN, 826bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 827bf215546Sopenharmony_ci if (!fences) 828bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 829bf215546Sopenharmony_ci } 830bf215546Sopenharmony_ci memcpy(fences, pFences, sizeof(*fences) * fenceCount); 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_ci while (result == VK_NOT_READY) { 833bf215546Sopenharmony_ci result = vn_remove_signaled_fences(device, fences, &fenceCount); 834bf215546Sopenharmony_ci result = vn_update_sync_result(result, abs_timeout, &iter); 835bf215546Sopenharmony_ci } 836bf215546Sopenharmony_ci 837bf215546Sopenharmony_ci if (fences != local_fences) 838bf215546Sopenharmony_ci vk_free(alloc, fences); 839bf215546Sopenharmony_ci } else { 840bf215546Sopenharmony_ci while (result == VK_NOT_READY) { 841bf215546Sopenharmony_ci result = vn_find_first_signaled_fence(device, pFences, fenceCount); 842bf215546Sopenharmony_ci result = vn_update_sync_result(result, abs_timeout, &iter); 843bf215546Sopenharmony_ci } 844bf215546Sopenharmony_ci } 845bf215546Sopenharmony_ci 846bf215546Sopenharmony_ci return vn_result(dev->instance, result); 847bf215546Sopenharmony_ci} 848bf215546Sopenharmony_ci 849bf215546Sopenharmony_cistatic VkResult 850bf215546Sopenharmony_civn_create_sync_file(struct vn_device *dev, int *out_fd) 851bf215546Sopenharmony_ci{ 852bf215546Sopenharmony_ci struct vn_renderer_sync *sync; 853bf215546Sopenharmony_ci VkResult result = vn_renderer_sync_create(dev->renderer, 0, 854bf215546Sopenharmony_ci VN_RENDERER_SYNC_BINARY, &sync); 855bf215546Sopenharmony_ci if (result != VK_SUCCESS) 856bf215546Sopenharmony_ci return vn_error(dev->instance, result); 857bf215546Sopenharmony_ci 858bf215546Sopenharmony_ci const struct vn_renderer_submit submit = { 859bf215546Sopenharmony_ci .batches = 860bf215546Sopenharmony_ci &(const struct vn_renderer_submit_batch){ 861bf215546Sopenharmony_ci .syncs = &sync, 862bf215546Sopenharmony_ci .sync_values = &(const uint64_t){ 1 }, 863bf215546Sopenharmony_ci .sync_count = 1, 864bf215546Sopenharmony_ci }, 865bf215546Sopenharmony_ci .batch_count = 1, 866bf215546Sopenharmony_ci }; 867bf215546Sopenharmony_ci result = vn_renderer_submit(dev->renderer, &submit); 868bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 869bf215546Sopenharmony_ci vn_renderer_sync_destroy(dev->renderer, sync); 870bf215546Sopenharmony_ci return vn_error(dev->instance, result); 871bf215546Sopenharmony_ci } 872bf215546Sopenharmony_ci 873bf215546Sopenharmony_ci *out_fd = vn_renderer_sync_export_syncobj(dev->renderer, sync, true); 874bf215546Sopenharmony_ci vn_renderer_sync_destroy(dev->renderer, sync); 875bf215546Sopenharmony_ci 876bf215546Sopenharmony_ci return *out_fd >= 0 ? VK_SUCCESS : VK_ERROR_TOO_MANY_OBJECTS; 877bf215546Sopenharmony_ci} 878bf215546Sopenharmony_ci 879bf215546Sopenharmony_ciVkResult 880bf215546Sopenharmony_civn_ImportFenceFdKHR(VkDevice device, 881bf215546Sopenharmony_ci const VkImportFenceFdInfoKHR *pImportFenceFdInfo) 882bf215546Sopenharmony_ci{ 883bf215546Sopenharmony_ci VN_TRACE_FUNC(); 884bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 885bf215546Sopenharmony_ci struct vn_fence *fence = vn_fence_from_handle(pImportFenceFdInfo->fence); 886bf215546Sopenharmony_ci ASSERTED const bool sync_file = pImportFenceFdInfo->handleType == 887bf215546Sopenharmony_ci VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; 888bf215546Sopenharmony_ci const int fd = pImportFenceFdInfo->fd; 889bf215546Sopenharmony_ci 890bf215546Sopenharmony_ci /* TODO update fence->is_external after we support opaque fd import */ 891bf215546Sopenharmony_ci assert(dev->instance->experimental.globalFencing); 892bf215546Sopenharmony_ci assert(sync_file); 893bf215546Sopenharmony_ci if (fd >= 0) { 894bf215546Sopenharmony_ci if (sync_wait(fd, -1)) 895bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); 896bf215546Sopenharmony_ci 897bf215546Sopenharmony_ci close(fd); 898bf215546Sopenharmony_ci } 899bf215546Sopenharmony_ci 900bf215546Sopenharmony_ci /* abuse VN_SYNC_TYPE_WSI_SIGNALED */ 901bf215546Sopenharmony_ci vn_fence_signal_wsi(dev, fence); 902bf215546Sopenharmony_ci 903bf215546Sopenharmony_ci return VK_SUCCESS; 904bf215546Sopenharmony_ci} 905bf215546Sopenharmony_ci 906bf215546Sopenharmony_ciVkResult 907bf215546Sopenharmony_civn_GetFenceFdKHR(VkDevice device, 908bf215546Sopenharmony_ci const VkFenceGetFdInfoKHR *pGetFdInfo, 909bf215546Sopenharmony_ci int *pFd) 910bf215546Sopenharmony_ci{ 911bf215546Sopenharmony_ci VN_TRACE_FUNC(); 912bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 913bf215546Sopenharmony_ci struct vn_fence *fence = vn_fence_from_handle(pGetFdInfo->fence); 914bf215546Sopenharmony_ci const bool sync_file = 915bf215546Sopenharmony_ci pGetFdInfo->handleType == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; 916bf215546Sopenharmony_ci struct vn_sync_payload *payload = fence->payload; 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci assert(dev->instance->experimental.globalFencing); 919bf215546Sopenharmony_ci assert(sync_file); 920bf215546Sopenharmony_ci int fd = -1; 921bf215546Sopenharmony_ci if (payload->type == VN_SYNC_TYPE_DEVICE_ONLY) { 922bf215546Sopenharmony_ci VkResult result = vn_create_sync_file(dev, &fd); 923bf215546Sopenharmony_ci if (result != VK_SUCCESS) 924bf215546Sopenharmony_ci return vn_error(dev->instance, result); 925bf215546Sopenharmony_ci } 926bf215546Sopenharmony_ci 927bf215546Sopenharmony_ci if (sync_file) { 928bf215546Sopenharmony_ci vn_sync_payload_release(dev, &fence->temporary); 929bf215546Sopenharmony_ci fence->payload = &fence->permanent; 930bf215546Sopenharmony_ci 931bf215546Sopenharmony_ci /* XXX implies reset operation on the host fence */ 932bf215546Sopenharmony_ci } 933bf215546Sopenharmony_ci 934bf215546Sopenharmony_ci *pFd = fd; 935bf215546Sopenharmony_ci return VK_SUCCESS; 936bf215546Sopenharmony_ci} 937bf215546Sopenharmony_ci 938bf215546Sopenharmony_ci/* semaphore commands */ 939bf215546Sopenharmony_ci 940bf215546Sopenharmony_cistatic VkResult 941bf215546Sopenharmony_civn_semaphore_init_payloads(struct vn_device *dev, 942bf215546Sopenharmony_ci struct vn_semaphore *sem, 943bf215546Sopenharmony_ci uint64_t initial_val, 944bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 945bf215546Sopenharmony_ci{ 946bf215546Sopenharmony_ci sem->permanent.type = VN_SYNC_TYPE_DEVICE_ONLY; 947bf215546Sopenharmony_ci sem->temporary.type = VN_SYNC_TYPE_INVALID; 948bf215546Sopenharmony_ci sem->payload = &sem->permanent; 949bf215546Sopenharmony_ci 950bf215546Sopenharmony_ci return VK_SUCCESS; 951bf215546Sopenharmony_ci} 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_cistatic void 954bf215546Sopenharmony_civn_semaphore_reset_wsi(struct vn_device *dev, struct vn_semaphore *sem) 955bf215546Sopenharmony_ci{ 956bf215546Sopenharmony_ci struct vn_sync_payload *perm = &sem->permanent; 957bf215546Sopenharmony_ci 958bf215546Sopenharmony_ci vn_sync_payload_release(dev, &sem->temporary); 959bf215546Sopenharmony_ci 960bf215546Sopenharmony_ci sem->payload = perm; 961bf215546Sopenharmony_ci} 962bf215546Sopenharmony_ci 963bf215546Sopenharmony_civoid 964bf215546Sopenharmony_civn_semaphore_signal_wsi(struct vn_device *dev, struct vn_semaphore *sem) 965bf215546Sopenharmony_ci{ 966bf215546Sopenharmony_ci struct vn_sync_payload *temp = &sem->temporary; 967bf215546Sopenharmony_ci 968bf215546Sopenharmony_ci vn_sync_payload_release(dev, temp); 969bf215546Sopenharmony_ci temp->type = VN_SYNC_TYPE_WSI_SIGNALED; 970bf215546Sopenharmony_ci sem->payload = temp; 971bf215546Sopenharmony_ci} 972bf215546Sopenharmony_ci 973bf215546Sopenharmony_ciVkResult 974bf215546Sopenharmony_civn_CreateSemaphore(VkDevice device, 975bf215546Sopenharmony_ci const VkSemaphoreCreateInfo *pCreateInfo, 976bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 977bf215546Sopenharmony_ci VkSemaphore *pSemaphore) 978bf215546Sopenharmony_ci{ 979bf215546Sopenharmony_ci VN_TRACE_FUNC(); 980bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 981bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 982bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 983bf215546Sopenharmony_ci 984bf215546Sopenharmony_ci struct vn_semaphore *sem = vk_zalloc(alloc, sizeof(*sem), VN_DEFAULT_ALIGN, 985bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 986bf215546Sopenharmony_ci if (!sem) 987bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 988bf215546Sopenharmony_ci 989bf215546Sopenharmony_ci vn_object_base_init(&sem->base, VK_OBJECT_TYPE_SEMAPHORE, &dev->base); 990bf215546Sopenharmony_ci 991bf215546Sopenharmony_ci const VkSemaphoreTypeCreateInfo *type_info = 992bf215546Sopenharmony_ci vk_find_struct_const(pCreateInfo->pNext, SEMAPHORE_TYPE_CREATE_INFO); 993bf215546Sopenharmony_ci uint64_t initial_val = 0; 994bf215546Sopenharmony_ci if (type_info && type_info->semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE) { 995bf215546Sopenharmony_ci sem->type = VK_SEMAPHORE_TYPE_TIMELINE; 996bf215546Sopenharmony_ci initial_val = type_info->initialValue; 997bf215546Sopenharmony_ci } else { 998bf215546Sopenharmony_ci sem->type = VK_SEMAPHORE_TYPE_BINARY; 999bf215546Sopenharmony_ci } 1000bf215546Sopenharmony_ci 1001bf215546Sopenharmony_ci VkResult result = vn_semaphore_init_payloads(dev, sem, initial_val, alloc); 1002bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1003bf215546Sopenharmony_ci vn_object_base_fini(&sem->base); 1004bf215546Sopenharmony_ci vk_free(alloc, sem); 1005bf215546Sopenharmony_ci return vn_error(dev->instance, result); 1006bf215546Sopenharmony_ci } 1007bf215546Sopenharmony_ci 1008bf215546Sopenharmony_ci VkSemaphore sem_handle = vn_semaphore_to_handle(sem); 1009bf215546Sopenharmony_ci vn_async_vkCreateSemaphore(dev->instance, device, pCreateInfo, NULL, 1010bf215546Sopenharmony_ci &sem_handle); 1011bf215546Sopenharmony_ci 1012bf215546Sopenharmony_ci *pSemaphore = sem_handle; 1013bf215546Sopenharmony_ci 1014bf215546Sopenharmony_ci return VK_SUCCESS; 1015bf215546Sopenharmony_ci} 1016bf215546Sopenharmony_ci 1017bf215546Sopenharmony_civoid 1018bf215546Sopenharmony_civn_DestroySemaphore(VkDevice device, 1019bf215546Sopenharmony_ci VkSemaphore semaphore, 1020bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 1021bf215546Sopenharmony_ci{ 1022bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1023bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1024bf215546Sopenharmony_ci struct vn_semaphore *sem = vn_semaphore_from_handle(semaphore); 1025bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 1026bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_ci if (!sem) 1029bf215546Sopenharmony_ci return; 1030bf215546Sopenharmony_ci 1031bf215546Sopenharmony_ci vn_async_vkDestroySemaphore(dev->instance, device, semaphore, NULL); 1032bf215546Sopenharmony_ci 1033bf215546Sopenharmony_ci vn_sync_payload_release(dev, &sem->permanent); 1034bf215546Sopenharmony_ci vn_sync_payload_release(dev, &sem->temporary); 1035bf215546Sopenharmony_ci 1036bf215546Sopenharmony_ci vn_object_base_fini(&sem->base); 1037bf215546Sopenharmony_ci vk_free(alloc, sem); 1038bf215546Sopenharmony_ci} 1039bf215546Sopenharmony_ci 1040bf215546Sopenharmony_ciVkResult 1041bf215546Sopenharmony_civn_GetSemaphoreCounterValue(VkDevice device, 1042bf215546Sopenharmony_ci VkSemaphore semaphore, 1043bf215546Sopenharmony_ci uint64_t *pValue) 1044bf215546Sopenharmony_ci{ 1045bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1046bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1047bf215546Sopenharmony_ci struct vn_semaphore *sem = vn_semaphore_from_handle(semaphore); 1048bf215546Sopenharmony_ci ASSERTED struct vn_sync_payload *payload = sem->payload; 1049bf215546Sopenharmony_ci 1050bf215546Sopenharmony_ci assert(payload->type == VN_SYNC_TYPE_DEVICE_ONLY); 1051bf215546Sopenharmony_ci return vn_call_vkGetSemaphoreCounterValue(dev->instance, device, semaphore, 1052bf215546Sopenharmony_ci pValue); 1053bf215546Sopenharmony_ci} 1054bf215546Sopenharmony_ci 1055bf215546Sopenharmony_ciVkResult 1056bf215546Sopenharmony_civn_SignalSemaphore(VkDevice device, const VkSemaphoreSignalInfo *pSignalInfo) 1057bf215546Sopenharmony_ci{ 1058bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1059bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1060bf215546Sopenharmony_ci 1061bf215546Sopenharmony_ci /* TODO if the semaphore is shared-by-ref, this needs to be synchronous */ 1062bf215546Sopenharmony_ci if (false) 1063bf215546Sopenharmony_ci vn_call_vkSignalSemaphore(dev->instance, device, pSignalInfo); 1064bf215546Sopenharmony_ci else 1065bf215546Sopenharmony_ci vn_async_vkSignalSemaphore(dev->instance, device, pSignalInfo); 1066bf215546Sopenharmony_ci 1067bf215546Sopenharmony_ci return VK_SUCCESS; 1068bf215546Sopenharmony_ci} 1069bf215546Sopenharmony_ci 1070bf215546Sopenharmony_cistatic VkResult 1071bf215546Sopenharmony_civn_find_first_signaled_semaphore(VkDevice device, 1072bf215546Sopenharmony_ci const VkSemaphore *semaphores, 1073bf215546Sopenharmony_ci const uint64_t *values, 1074bf215546Sopenharmony_ci uint32_t count) 1075bf215546Sopenharmony_ci{ 1076bf215546Sopenharmony_ci for (uint32_t i = 0; i < count; i++) { 1077bf215546Sopenharmony_ci uint64_t val = 0; 1078bf215546Sopenharmony_ci VkResult result = 1079bf215546Sopenharmony_ci vn_GetSemaphoreCounterValue(device, semaphores[i], &val); 1080bf215546Sopenharmony_ci if (result != VK_SUCCESS || val >= values[i]) 1081bf215546Sopenharmony_ci return result; 1082bf215546Sopenharmony_ci } 1083bf215546Sopenharmony_ci return VK_NOT_READY; 1084bf215546Sopenharmony_ci} 1085bf215546Sopenharmony_ci 1086bf215546Sopenharmony_cistatic VkResult 1087bf215546Sopenharmony_civn_remove_signaled_semaphores(VkDevice device, 1088bf215546Sopenharmony_ci VkSemaphore *semaphores, 1089bf215546Sopenharmony_ci uint64_t *values, 1090bf215546Sopenharmony_ci uint32_t *count) 1091bf215546Sopenharmony_ci{ 1092bf215546Sopenharmony_ci uint32_t cur = 0; 1093bf215546Sopenharmony_ci for (uint32_t i = 0; i < *count; i++) { 1094bf215546Sopenharmony_ci uint64_t val = 0; 1095bf215546Sopenharmony_ci VkResult result = 1096bf215546Sopenharmony_ci vn_GetSemaphoreCounterValue(device, semaphores[i], &val); 1097bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1098bf215546Sopenharmony_ci return result; 1099bf215546Sopenharmony_ci if (val < values[i]) 1100bf215546Sopenharmony_ci semaphores[cur++] = semaphores[i]; 1101bf215546Sopenharmony_ci } 1102bf215546Sopenharmony_ci 1103bf215546Sopenharmony_ci *count = cur; 1104bf215546Sopenharmony_ci return cur ? VK_NOT_READY : VK_SUCCESS; 1105bf215546Sopenharmony_ci} 1106bf215546Sopenharmony_ci 1107bf215546Sopenharmony_ciVkResult 1108bf215546Sopenharmony_civn_WaitSemaphores(VkDevice device, 1109bf215546Sopenharmony_ci const VkSemaphoreWaitInfo *pWaitInfo, 1110bf215546Sopenharmony_ci uint64_t timeout) 1111bf215546Sopenharmony_ci{ 1112bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1113bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1114bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = &dev->base.base.alloc; 1115bf215546Sopenharmony_ci 1116bf215546Sopenharmony_ci const int64_t abs_timeout = os_time_get_absolute_timeout(timeout); 1117bf215546Sopenharmony_ci VkResult result = VK_NOT_READY; 1118bf215546Sopenharmony_ci uint32_t iter = 0; 1119bf215546Sopenharmony_ci if (pWaitInfo->semaphoreCount > 1 && 1120bf215546Sopenharmony_ci !(pWaitInfo->flags & VK_SEMAPHORE_WAIT_ANY_BIT)) { 1121bf215546Sopenharmony_ci uint32_t semaphore_count = pWaitInfo->semaphoreCount; 1122bf215546Sopenharmony_ci VkSemaphore local_semaphores[8]; 1123bf215546Sopenharmony_ci uint64_t local_values[8]; 1124bf215546Sopenharmony_ci VkSemaphore *semaphores = local_semaphores; 1125bf215546Sopenharmony_ci uint64_t *values = local_values; 1126bf215546Sopenharmony_ci if (semaphore_count > ARRAY_SIZE(local_semaphores)) { 1127bf215546Sopenharmony_ci semaphores = vk_alloc( 1128bf215546Sopenharmony_ci alloc, (sizeof(*semaphores) + sizeof(*values)) * semaphore_count, 1129bf215546Sopenharmony_ci VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); 1130bf215546Sopenharmony_ci if (!semaphores) 1131bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci values = (uint64_t *)&semaphores[semaphore_count]; 1134bf215546Sopenharmony_ci } 1135bf215546Sopenharmony_ci memcpy(semaphores, pWaitInfo->pSemaphores, 1136bf215546Sopenharmony_ci sizeof(*semaphores) * semaphore_count); 1137bf215546Sopenharmony_ci memcpy(values, pWaitInfo->pValues, sizeof(*values) * semaphore_count); 1138bf215546Sopenharmony_ci 1139bf215546Sopenharmony_ci while (result == VK_NOT_READY) { 1140bf215546Sopenharmony_ci result = vn_remove_signaled_semaphores(device, semaphores, values, 1141bf215546Sopenharmony_ci &semaphore_count); 1142bf215546Sopenharmony_ci result = vn_update_sync_result(result, abs_timeout, &iter); 1143bf215546Sopenharmony_ci } 1144bf215546Sopenharmony_ci 1145bf215546Sopenharmony_ci if (semaphores != local_semaphores) 1146bf215546Sopenharmony_ci vk_free(alloc, semaphores); 1147bf215546Sopenharmony_ci } else { 1148bf215546Sopenharmony_ci while (result == VK_NOT_READY) { 1149bf215546Sopenharmony_ci result = vn_find_first_signaled_semaphore( 1150bf215546Sopenharmony_ci device, pWaitInfo->pSemaphores, pWaitInfo->pValues, 1151bf215546Sopenharmony_ci pWaitInfo->semaphoreCount); 1152bf215546Sopenharmony_ci result = vn_update_sync_result(result, abs_timeout, &iter); 1153bf215546Sopenharmony_ci } 1154bf215546Sopenharmony_ci } 1155bf215546Sopenharmony_ci 1156bf215546Sopenharmony_ci return vn_result(dev->instance, result); 1157bf215546Sopenharmony_ci} 1158bf215546Sopenharmony_ci 1159bf215546Sopenharmony_ciVkResult 1160bf215546Sopenharmony_civn_ImportSemaphoreFdKHR( 1161bf215546Sopenharmony_ci VkDevice device, const VkImportSemaphoreFdInfoKHR *pImportSemaphoreFdInfo) 1162bf215546Sopenharmony_ci{ 1163bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1164bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1165bf215546Sopenharmony_ci struct vn_semaphore *sem = 1166bf215546Sopenharmony_ci vn_semaphore_from_handle(pImportSemaphoreFdInfo->semaphore); 1167bf215546Sopenharmony_ci ASSERTED const bool sync_file = 1168bf215546Sopenharmony_ci pImportSemaphoreFdInfo->handleType == 1169bf215546Sopenharmony_ci VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; 1170bf215546Sopenharmony_ci const int fd = pImportSemaphoreFdInfo->fd; 1171bf215546Sopenharmony_ci 1172bf215546Sopenharmony_ci assert(dev->instance->experimental.globalFencing); 1173bf215546Sopenharmony_ci assert(sync_file); 1174bf215546Sopenharmony_ci if (fd >= 0) { 1175bf215546Sopenharmony_ci if (sync_wait(fd, -1)) 1176bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); 1177bf215546Sopenharmony_ci 1178bf215546Sopenharmony_ci close(fd); 1179bf215546Sopenharmony_ci } 1180bf215546Sopenharmony_ci 1181bf215546Sopenharmony_ci /* abuse VN_SYNC_TYPE_WSI_SIGNALED */ 1182bf215546Sopenharmony_ci vn_semaphore_signal_wsi(dev, sem); 1183bf215546Sopenharmony_ci 1184bf215546Sopenharmony_ci return VK_SUCCESS; 1185bf215546Sopenharmony_ci} 1186bf215546Sopenharmony_ci 1187bf215546Sopenharmony_ciVkResult 1188bf215546Sopenharmony_civn_GetSemaphoreFdKHR(VkDevice device, 1189bf215546Sopenharmony_ci const VkSemaphoreGetFdInfoKHR *pGetFdInfo, 1190bf215546Sopenharmony_ci int *pFd) 1191bf215546Sopenharmony_ci{ 1192bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1193bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1194bf215546Sopenharmony_ci struct vn_semaphore *sem = vn_semaphore_from_handle(pGetFdInfo->semaphore); 1195bf215546Sopenharmony_ci const bool sync_file = 1196bf215546Sopenharmony_ci pGetFdInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; 1197bf215546Sopenharmony_ci struct vn_sync_payload *payload = sem->payload; 1198bf215546Sopenharmony_ci 1199bf215546Sopenharmony_ci assert(dev->instance->experimental.globalFencing); 1200bf215546Sopenharmony_ci assert(sync_file); 1201bf215546Sopenharmony_ci int fd = -1; 1202bf215546Sopenharmony_ci if (payload->type == VN_SYNC_TYPE_DEVICE_ONLY) { 1203bf215546Sopenharmony_ci VkResult result = vn_create_sync_file(dev, &fd); 1204bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1205bf215546Sopenharmony_ci return vn_error(dev->instance, result); 1206bf215546Sopenharmony_ci } 1207bf215546Sopenharmony_ci 1208bf215546Sopenharmony_ci if (sync_file) { 1209bf215546Sopenharmony_ci vn_sync_payload_release(dev, &sem->temporary); 1210bf215546Sopenharmony_ci sem->payload = &sem->permanent; 1211bf215546Sopenharmony_ci 1212bf215546Sopenharmony_ci /* XXX implies wait operation on the host semaphore */ 1213bf215546Sopenharmony_ci } 1214bf215546Sopenharmony_ci 1215bf215546Sopenharmony_ci *pFd = fd; 1216bf215546Sopenharmony_ci return VK_SUCCESS; 1217bf215546Sopenharmony_ci} 1218bf215546Sopenharmony_ci 1219bf215546Sopenharmony_ci/* event commands */ 1220bf215546Sopenharmony_ci 1221bf215546Sopenharmony_cistatic VkResult 1222bf215546Sopenharmony_civn_event_feedback_init(struct vn_device *dev, struct vn_event *ev) 1223bf215546Sopenharmony_ci{ 1224bf215546Sopenharmony_ci struct vn_feedback_slot *slot; 1225bf215546Sopenharmony_ci 1226bf215546Sopenharmony_ci if (VN_PERF(NO_EVENT_FEEDBACK)) 1227bf215546Sopenharmony_ci return VK_SUCCESS; 1228bf215546Sopenharmony_ci 1229bf215546Sopenharmony_ci slot = vn_feedback_pool_alloc(&dev->feedback_pool, VN_FEEDBACK_TYPE_EVENT); 1230bf215546Sopenharmony_ci if (!slot) 1231bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 1232bf215546Sopenharmony_ci 1233bf215546Sopenharmony_ci /* newly created event object is in the unsignaled state */ 1234bf215546Sopenharmony_ci vn_feedback_set_status(slot, VK_EVENT_RESET); 1235bf215546Sopenharmony_ci 1236bf215546Sopenharmony_ci ev->feedback_slot = slot; 1237bf215546Sopenharmony_ci 1238bf215546Sopenharmony_ci return VK_SUCCESS; 1239bf215546Sopenharmony_ci} 1240bf215546Sopenharmony_ci 1241bf215546Sopenharmony_cistatic inline void 1242bf215546Sopenharmony_civn_event_feedback_fini(struct vn_device *dev, struct vn_event *ev) 1243bf215546Sopenharmony_ci{ 1244bf215546Sopenharmony_ci if (ev->feedback_slot) 1245bf215546Sopenharmony_ci vn_feedback_pool_free(&dev->feedback_pool, ev->feedback_slot); 1246bf215546Sopenharmony_ci} 1247bf215546Sopenharmony_ci 1248bf215546Sopenharmony_ciVkResult 1249bf215546Sopenharmony_civn_CreateEvent(VkDevice device, 1250bf215546Sopenharmony_ci const VkEventCreateInfo *pCreateInfo, 1251bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 1252bf215546Sopenharmony_ci VkEvent *pEvent) 1253bf215546Sopenharmony_ci{ 1254bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1255bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1256bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 1257bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 1258bf215546Sopenharmony_ci 1259bf215546Sopenharmony_ci struct vn_event *ev = vk_zalloc(alloc, sizeof(*ev), VN_DEFAULT_ALIGN, 1260bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 1261bf215546Sopenharmony_ci if (!ev) 1262bf215546Sopenharmony_ci return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY); 1263bf215546Sopenharmony_ci 1264bf215546Sopenharmony_ci vn_object_base_init(&ev->base, VK_OBJECT_TYPE_EVENT, &dev->base); 1265bf215546Sopenharmony_ci 1266bf215546Sopenharmony_ci /* feedback is only needed to speed up host operations */ 1267bf215546Sopenharmony_ci if (!(pCreateInfo->flags & VK_EVENT_CREATE_DEVICE_ONLY_BIT)) { 1268bf215546Sopenharmony_ci VkResult result = vn_event_feedback_init(dev, ev); 1269bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1270bf215546Sopenharmony_ci return vn_error(dev->instance, result); 1271bf215546Sopenharmony_ci } 1272bf215546Sopenharmony_ci 1273bf215546Sopenharmony_ci VkEvent ev_handle = vn_event_to_handle(ev); 1274bf215546Sopenharmony_ci vn_async_vkCreateEvent(dev->instance, device, pCreateInfo, NULL, 1275bf215546Sopenharmony_ci &ev_handle); 1276bf215546Sopenharmony_ci 1277bf215546Sopenharmony_ci *pEvent = ev_handle; 1278bf215546Sopenharmony_ci 1279bf215546Sopenharmony_ci return VK_SUCCESS; 1280bf215546Sopenharmony_ci} 1281bf215546Sopenharmony_ci 1282bf215546Sopenharmony_civoid 1283bf215546Sopenharmony_civn_DestroyEvent(VkDevice device, 1284bf215546Sopenharmony_ci VkEvent event, 1285bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 1286bf215546Sopenharmony_ci{ 1287bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1288bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1289bf215546Sopenharmony_ci struct vn_event *ev = vn_event_from_handle(event); 1290bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc = 1291bf215546Sopenharmony_ci pAllocator ? pAllocator : &dev->base.base.alloc; 1292bf215546Sopenharmony_ci 1293bf215546Sopenharmony_ci if (!ev) 1294bf215546Sopenharmony_ci return; 1295bf215546Sopenharmony_ci 1296bf215546Sopenharmony_ci vn_async_vkDestroyEvent(dev->instance, device, event, NULL); 1297bf215546Sopenharmony_ci 1298bf215546Sopenharmony_ci vn_event_feedback_fini(dev, ev); 1299bf215546Sopenharmony_ci 1300bf215546Sopenharmony_ci vn_object_base_fini(&ev->base); 1301bf215546Sopenharmony_ci vk_free(alloc, ev); 1302bf215546Sopenharmony_ci} 1303bf215546Sopenharmony_ci 1304bf215546Sopenharmony_ciVkResult 1305bf215546Sopenharmony_civn_GetEventStatus(VkDevice device, VkEvent event) 1306bf215546Sopenharmony_ci{ 1307bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1308bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1309bf215546Sopenharmony_ci struct vn_event *ev = vn_event_from_handle(event); 1310bf215546Sopenharmony_ci VkResult result; 1311bf215546Sopenharmony_ci 1312bf215546Sopenharmony_ci if (ev->feedback_slot) 1313bf215546Sopenharmony_ci result = vn_feedback_get_status(ev->feedback_slot); 1314bf215546Sopenharmony_ci else 1315bf215546Sopenharmony_ci result = vn_call_vkGetEventStatus(dev->instance, device, event); 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_ci return vn_result(dev->instance, result); 1318bf215546Sopenharmony_ci} 1319bf215546Sopenharmony_ci 1320bf215546Sopenharmony_ciVkResult 1321bf215546Sopenharmony_civn_SetEvent(VkDevice device, VkEvent event) 1322bf215546Sopenharmony_ci{ 1323bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1324bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1325bf215546Sopenharmony_ci struct vn_event *ev = vn_event_from_handle(event); 1326bf215546Sopenharmony_ci 1327bf215546Sopenharmony_ci if (ev->feedback_slot) { 1328bf215546Sopenharmony_ci vn_feedback_set_status(ev->feedback_slot, VK_EVENT_SET); 1329bf215546Sopenharmony_ci vn_async_vkSetEvent(dev->instance, device, event); 1330bf215546Sopenharmony_ci } else { 1331bf215546Sopenharmony_ci VkResult result = vn_call_vkSetEvent(dev->instance, device, event); 1332bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1333bf215546Sopenharmony_ci return vn_error(dev->instance, result); 1334bf215546Sopenharmony_ci } 1335bf215546Sopenharmony_ci 1336bf215546Sopenharmony_ci return VK_SUCCESS; 1337bf215546Sopenharmony_ci} 1338bf215546Sopenharmony_ci 1339bf215546Sopenharmony_ciVkResult 1340bf215546Sopenharmony_civn_ResetEvent(VkDevice device, VkEvent event) 1341bf215546Sopenharmony_ci{ 1342bf215546Sopenharmony_ci VN_TRACE_FUNC(); 1343bf215546Sopenharmony_ci struct vn_device *dev = vn_device_from_handle(device); 1344bf215546Sopenharmony_ci struct vn_event *ev = vn_event_from_handle(event); 1345bf215546Sopenharmony_ci 1346bf215546Sopenharmony_ci if (ev->feedback_slot) { 1347bf215546Sopenharmony_ci vn_feedback_reset_status(ev->feedback_slot); 1348bf215546Sopenharmony_ci vn_async_vkResetEvent(dev->instance, device, event); 1349bf215546Sopenharmony_ci } else { 1350bf215546Sopenharmony_ci VkResult result = vn_call_vkResetEvent(dev->instance, device, event); 1351bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1352bf215546Sopenharmony_ci return vn_error(dev->instance, result); 1353bf215546Sopenharmony_ci } 1354bf215546Sopenharmony_ci 1355bf215546Sopenharmony_ci return VK_SUCCESS; 1356bf215546Sopenharmony_ci} 1357