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_semaphore.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "util/os_time.h" 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci#ifndef _WIN32 29bf215546Sopenharmony_ci#include <unistd.h> 30bf215546Sopenharmony_ci#endif 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "vk_common_entrypoints.h" 33bf215546Sopenharmony_ci#include "vk_device.h" 34bf215546Sopenharmony_ci#include "vk_log.h" 35bf215546Sopenharmony_ci#include "vk_physical_device.h" 36bf215546Sopenharmony_ci#include "vk_util.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_cistatic VkExternalSemaphoreHandleTypeFlags 39bf215546Sopenharmony_civk_sync_semaphore_import_types(const struct vk_sync_type *type, 40bf215546Sopenharmony_ci VkSemaphoreType semaphore_type) 41bf215546Sopenharmony_ci{ 42bf215546Sopenharmony_ci VkExternalSemaphoreHandleTypeFlags handle_types = 0; 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci if (type->import_opaque_fd) 45bf215546Sopenharmony_ci handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci if (type->export_sync_file && semaphore_type == VK_SEMAPHORE_TYPE_BINARY) 48bf215546Sopenharmony_ci handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci return handle_types; 51bf215546Sopenharmony_ci} 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic VkExternalSemaphoreHandleTypeFlags 54bf215546Sopenharmony_civk_sync_semaphore_export_types(const struct vk_sync_type *type, 55bf215546Sopenharmony_ci VkSemaphoreType semaphore_type) 56bf215546Sopenharmony_ci{ 57bf215546Sopenharmony_ci VkExternalSemaphoreHandleTypeFlags handle_types = 0; 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci if (type->export_opaque_fd) 60bf215546Sopenharmony_ci handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci if (type->export_sync_file && semaphore_type == VK_SEMAPHORE_TYPE_BINARY) 63bf215546Sopenharmony_ci handle_types |= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; 64bf215546Sopenharmony_ci 65bf215546Sopenharmony_ci return handle_types; 66bf215546Sopenharmony_ci} 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_cistatic VkExternalSemaphoreHandleTypeFlags 69bf215546Sopenharmony_civk_sync_semaphore_handle_types(const struct vk_sync_type *type, 70bf215546Sopenharmony_ci VkSemaphoreType semaphore_type) 71bf215546Sopenharmony_ci{ 72bf215546Sopenharmony_ci return vk_sync_semaphore_export_types(type, semaphore_type) & 73bf215546Sopenharmony_ci vk_sync_semaphore_import_types(type, semaphore_type); 74bf215546Sopenharmony_ci} 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_cistatic const struct vk_sync_type * 77bf215546Sopenharmony_ciget_semaphore_sync_type(struct vk_physical_device *pdevice, 78bf215546Sopenharmony_ci VkSemaphoreType semaphore_type, 79bf215546Sopenharmony_ci VkExternalSemaphoreHandleTypeFlags handle_types) 80bf215546Sopenharmony_ci{ 81bf215546Sopenharmony_ci assert(semaphore_type == VK_SEMAPHORE_TYPE_BINARY || 82bf215546Sopenharmony_ci semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE); 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci enum vk_sync_features req_features = VK_SYNC_FEATURE_GPU_WAIT; 85bf215546Sopenharmony_ci if (semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE) { 86bf215546Sopenharmony_ci req_features |= VK_SYNC_FEATURE_TIMELINE | 87bf215546Sopenharmony_ci VK_SYNC_FEATURE_CPU_WAIT; 88bf215546Sopenharmony_ci } else { 89bf215546Sopenharmony_ci req_features |= VK_SYNC_FEATURE_BINARY; 90bf215546Sopenharmony_ci } 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci for (const struct vk_sync_type *const *t = 93bf215546Sopenharmony_ci pdevice->supported_sync_types; *t; t++) { 94bf215546Sopenharmony_ci if (req_features & ~(*t)->features) 95bf215546Sopenharmony_ci continue; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci if (handle_types & ~vk_sync_semaphore_handle_types(*t, semaphore_type)) 98bf215546Sopenharmony_ci continue; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci return *t; 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci return NULL; 104bf215546Sopenharmony_ci} 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_cistatic VkSemaphoreType 107bf215546Sopenharmony_ciget_semaphore_type(const void *pNext, uint64_t *initial_value) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci const VkSemaphoreTypeCreateInfo *type_info = 110bf215546Sopenharmony_ci vk_find_struct_const(pNext, SEMAPHORE_TYPE_CREATE_INFO); 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci if (!type_info) 113bf215546Sopenharmony_ci return VK_SEMAPHORE_TYPE_BINARY; 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci if (initial_value) 116bf215546Sopenharmony_ci *initial_value = type_info->initialValue; 117bf215546Sopenharmony_ci return type_info->semaphoreType; 118bf215546Sopenharmony_ci} 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 121bf215546Sopenharmony_civk_common_CreateSemaphore(VkDevice _device, 122bf215546Sopenharmony_ci const VkSemaphoreCreateInfo *pCreateInfo, 123bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 124bf215546Sopenharmony_ci VkSemaphore *pSemaphore) 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 127bf215546Sopenharmony_ci struct vk_semaphore *semaphore; 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO); 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci uint64_t initial_value = 0; 132bf215546Sopenharmony_ci const VkSemaphoreType semaphore_type = 133bf215546Sopenharmony_ci get_semaphore_type(pCreateInfo->pNext, &initial_value); 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci if (semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE) 136bf215546Sopenharmony_ci assert(device->timeline_mode != VK_DEVICE_TIMELINE_MODE_NONE); 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci const VkExportSemaphoreCreateInfo *export = 139bf215546Sopenharmony_ci vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_CREATE_INFO); 140bf215546Sopenharmony_ci VkExternalSemaphoreHandleTypeFlags handle_types = 141bf215546Sopenharmony_ci export ? export->handleTypes : 0; 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci const struct vk_sync_type *sync_type = 144bf215546Sopenharmony_ci get_semaphore_sync_type(device->physical, semaphore_type, handle_types); 145bf215546Sopenharmony_ci if (sync_type == NULL) { 146bf215546Sopenharmony_ci /* We should always be able to get a semaphore type for internal */ 147bf215546Sopenharmony_ci assert(get_semaphore_sync_type(device->physical, semaphore_type, 0) != NULL); 148bf215546Sopenharmony_ci return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE, 149bf215546Sopenharmony_ci "Combination of external handle types is unsupported " 150bf215546Sopenharmony_ci "for VkSemaphore creation."); 151bf215546Sopenharmony_ci } 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci /* If the timeline mode is ASSISTED, then any permanent binary semaphore 154bf215546Sopenharmony_ci * types need to be able to support move. We don't require this for 155bf215546Sopenharmony_ci * temporary unless that temporary is also used as a semaphore signal 156bf215546Sopenharmony_ci * operation which is much trickier to assert early. 157bf215546Sopenharmony_ci */ 158bf215546Sopenharmony_ci if (semaphore_type == VK_SEMAPHORE_TYPE_BINARY && 159bf215546Sopenharmony_ci vk_device_supports_threaded_submit(device)) 160bf215546Sopenharmony_ci assert(sync_type->move); 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci /* Allocate a vk_semaphore + vk_sync implementation. Because the permanent 163bf215546Sopenharmony_ci * field of vk_semaphore is the base field of the vk_sync implementation, 164bf215546Sopenharmony_ci * we can make the 2 structures overlap. 165bf215546Sopenharmony_ci */ 166bf215546Sopenharmony_ci size_t size = offsetof(struct vk_semaphore, permanent) + sync_type->size; 167bf215546Sopenharmony_ci semaphore = vk_object_zalloc(device, pAllocator, size, 168bf215546Sopenharmony_ci VK_OBJECT_TYPE_SEMAPHORE); 169bf215546Sopenharmony_ci if (semaphore == NULL) 170bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci semaphore->type = semaphore_type; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci enum vk_sync_flags sync_flags = 0; 175bf215546Sopenharmony_ci if (semaphore_type == VK_SEMAPHORE_TYPE_TIMELINE) 176bf215546Sopenharmony_ci sync_flags |= VK_SYNC_IS_TIMELINE; 177bf215546Sopenharmony_ci if (handle_types) 178bf215546Sopenharmony_ci sync_flags |= VK_SYNC_IS_SHAREABLE; 179bf215546Sopenharmony_ci 180bf215546Sopenharmony_ci VkResult result = vk_sync_init(device, &semaphore->permanent, 181bf215546Sopenharmony_ci sync_type, sync_flags, initial_value); 182bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 183bf215546Sopenharmony_ci vk_object_free(device, pAllocator, semaphore); 184bf215546Sopenharmony_ci return result; 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci *pSemaphore = vk_semaphore_to_handle(semaphore); 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci return VK_SUCCESS; 190bf215546Sopenharmony_ci} 191bf215546Sopenharmony_ci 192bf215546Sopenharmony_civoid 193bf215546Sopenharmony_civk_semaphore_reset_temporary(struct vk_device *device, 194bf215546Sopenharmony_ci struct vk_semaphore *semaphore) 195bf215546Sopenharmony_ci{ 196bf215546Sopenharmony_ci if (semaphore->temporary == NULL) 197bf215546Sopenharmony_ci return; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci vk_sync_destroy(device, semaphore->temporary); 200bf215546Sopenharmony_ci semaphore->temporary = NULL; 201bf215546Sopenharmony_ci} 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 204bf215546Sopenharmony_civk_common_DestroySemaphore(VkDevice _device, 205bf215546Sopenharmony_ci VkSemaphore _semaphore, 206bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 207bf215546Sopenharmony_ci{ 208bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 209bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_semaphore, semaphore, _semaphore); 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci if (semaphore == NULL) 212bf215546Sopenharmony_ci return; 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci vk_semaphore_reset_temporary(device, semaphore); 215bf215546Sopenharmony_ci vk_sync_finish(device, &semaphore->permanent); 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci vk_object_free(device, pAllocator, semaphore); 218bf215546Sopenharmony_ci} 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 221bf215546Sopenharmony_civk_common_GetPhysicalDeviceExternalSemaphoreProperties( 222bf215546Sopenharmony_ci VkPhysicalDevice physicalDevice, 223bf215546Sopenharmony_ci const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, 224bf215546Sopenharmony_ci VkExternalSemaphoreProperties *pExternalSemaphoreProperties) 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci assert(pExternalSemaphoreInfo->sType == 229bf215546Sopenharmony_ci VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO); 230bf215546Sopenharmony_ci const VkExternalSemaphoreHandleTypeFlagBits handle_type = 231bf215546Sopenharmony_ci pExternalSemaphoreInfo->handleType; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci const VkSemaphoreType semaphore_type = 234bf215546Sopenharmony_ci get_semaphore_type(pExternalSemaphoreInfo->pNext, NULL); 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci const struct vk_sync_type *sync_type = 237bf215546Sopenharmony_ci get_semaphore_sync_type(pdevice, semaphore_type, handle_type); 238bf215546Sopenharmony_ci if (sync_type == NULL) { 239bf215546Sopenharmony_ci pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; 240bf215546Sopenharmony_ci pExternalSemaphoreProperties->compatibleHandleTypes = 0; 241bf215546Sopenharmony_ci pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; 242bf215546Sopenharmony_ci return; 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci VkExternalSemaphoreHandleTypeFlagBits import = 246bf215546Sopenharmony_ci vk_sync_semaphore_import_types(sync_type, semaphore_type); 247bf215546Sopenharmony_ci VkExternalSemaphoreHandleTypeFlagBits export = 248bf215546Sopenharmony_ci vk_sync_semaphore_export_types(sync_type, semaphore_type); 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci if (handle_type != VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT) { 251bf215546Sopenharmony_ci const struct vk_sync_type *opaque_sync_type = 252bf215546Sopenharmony_ci get_semaphore_sync_type(pdevice, semaphore_type, 253bf215546Sopenharmony_ci VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT); 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci /* If we're a different vk_sync_type than the one selected when only 256bf215546Sopenharmony_ci * OPAQUE_FD is set, then we can't import/export OPAQUE_FD. Put 257bf215546Sopenharmony_ci * differently, there can only be one OPAQUE_FD sync type. 258bf215546Sopenharmony_ci */ 259bf215546Sopenharmony_ci if (sync_type != opaque_sync_type) { 260bf215546Sopenharmony_ci import &= ~VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; 261bf215546Sopenharmony_ci export &= ~VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT; 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci } 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci VkExternalSemaphoreHandleTypeFlags compatible = import & export; 266bf215546Sopenharmony_ci VkExternalSemaphoreFeatureFlags features = 0; 267bf215546Sopenharmony_ci if (handle_type & export) 268bf215546Sopenharmony_ci features |= VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT; 269bf215546Sopenharmony_ci if (handle_type & import) 270bf215546Sopenharmony_ci features |= VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_ci pExternalSemaphoreProperties->exportFromImportedHandleTypes = export; 273bf215546Sopenharmony_ci pExternalSemaphoreProperties->compatibleHandleTypes = compatible; 274bf215546Sopenharmony_ci pExternalSemaphoreProperties->externalSemaphoreFeatures = features; 275bf215546Sopenharmony_ci} 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 278bf215546Sopenharmony_civk_common_GetSemaphoreCounterValue(VkDevice _device, 279bf215546Sopenharmony_ci VkSemaphore _semaphore, 280bf215546Sopenharmony_ci uint64_t *pValue) 281bf215546Sopenharmony_ci{ 282bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 283bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_semaphore, semaphore, _semaphore); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci if (vk_device_is_lost(device)) 286bf215546Sopenharmony_ci return VK_ERROR_DEVICE_LOST; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci struct vk_sync *sync = vk_semaphore_get_active_sync(semaphore); 289bf215546Sopenharmony_ci return vk_sync_get_value(device, sync, pValue); 290bf215546Sopenharmony_ci} 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 293bf215546Sopenharmony_civk_common_WaitSemaphores(VkDevice _device, 294bf215546Sopenharmony_ci const VkSemaphoreWaitInfo *pWaitInfo, 295bf215546Sopenharmony_ci uint64_t timeout) 296bf215546Sopenharmony_ci{ 297bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci if (vk_device_is_lost(device)) 300bf215546Sopenharmony_ci return VK_ERROR_DEVICE_LOST; 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci if (pWaitInfo->semaphoreCount == 0) 303bf215546Sopenharmony_ci return VK_SUCCESS; 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci uint64_t abs_timeout_ns = os_time_get_absolute_timeout(timeout); 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci const uint32_t wait_count = pWaitInfo->semaphoreCount; 308bf215546Sopenharmony_ci STACK_ARRAY(struct vk_sync_wait, waits, pWaitInfo->semaphoreCount); 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci for (uint32_t i = 0; i < wait_count; i++) { 311bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_semaphore, semaphore, pWaitInfo->pSemaphores[i]); 312bf215546Sopenharmony_ci assert(semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE); 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci waits[i] = (struct vk_sync_wait) { 315bf215546Sopenharmony_ci .sync = vk_semaphore_get_active_sync(semaphore), 316bf215546Sopenharmony_ci .stage_mask = ~(VkPipelineStageFlags2)0, 317bf215546Sopenharmony_ci .wait_value = pWaitInfo->pValues[i], 318bf215546Sopenharmony_ci }; 319bf215546Sopenharmony_ci } 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci enum vk_sync_wait_flags wait_flags = VK_SYNC_WAIT_COMPLETE; 322bf215546Sopenharmony_ci if (pWaitInfo->flags & VK_SEMAPHORE_WAIT_ANY_BIT) 323bf215546Sopenharmony_ci wait_flags |= VK_SYNC_WAIT_ANY; 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci VkResult result = vk_sync_wait_many(device, wait_count, waits, 326bf215546Sopenharmony_ci wait_flags, abs_timeout_ns); 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci STACK_ARRAY_FINISH(waits); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci VkResult device_status = vk_device_check_status(device); 331bf215546Sopenharmony_ci if (device_status != VK_SUCCESS) 332bf215546Sopenharmony_ci return device_status; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci return result; 335bf215546Sopenharmony_ci} 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 338bf215546Sopenharmony_civk_common_SignalSemaphore(VkDevice _device, 339bf215546Sopenharmony_ci const VkSemaphoreSignalInfo *pSignalInfo) 340bf215546Sopenharmony_ci{ 341bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 342bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_semaphore, semaphore, pSignalInfo->semaphore); 343bf215546Sopenharmony_ci struct vk_sync *sync = vk_semaphore_get_active_sync(semaphore); 344bf215546Sopenharmony_ci VkResult result; 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci /* From the Vulkan 1.2.194 spec: 347bf215546Sopenharmony_ci * 348bf215546Sopenharmony_ci * UID-VkSemaphoreSignalInfo-semaphore-03257 349bf215546Sopenharmony_ci * 350bf215546Sopenharmony_ci * "semaphore must have been created with a VkSemaphoreType of 351bf215546Sopenharmony_ci * VK_SEMAPHORE_TYPE_TIMELINE." 352bf215546Sopenharmony_ci */ 353bf215546Sopenharmony_ci assert(semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE); 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci /* From the Vulkan 1.2.194 spec: 356bf215546Sopenharmony_ci * 357bf215546Sopenharmony_ci * VUID-VkSemaphoreSignalInfo-value-03258 358bf215546Sopenharmony_ci * 359bf215546Sopenharmony_ci * "value must have a value greater than the current value of the 360bf215546Sopenharmony_ci * semaphore" 361bf215546Sopenharmony_ci * 362bf215546Sopenharmony_ci * Since 0 is the lowest possible semaphore timeline value, we can assert 363bf215546Sopenharmony_ci * that a non-zero signal value is provided. 364bf215546Sopenharmony_ci */ 365bf215546Sopenharmony_ci if (unlikely(pSignalInfo->value == 0)) { 366bf215546Sopenharmony_ci return vk_device_set_lost(device, 367bf215546Sopenharmony_ci "Tried to signal a timeline with value 0"); 368bf215546Sopenharmony_ci } 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci result = vk_sync_signal(device, sync, pSignalInfo->value); 371bf215546Sopenharmony_ci if (unlikely(result != VK_SUCCESS)) 372bf215546Sopenharmony_ci return result; 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci if (device->submit_mode == VK_QUEUE_SUBMIT_MODE_DEFERRED) { 375bf215546Sopenharmony_ci result = vk_device_flush(device); 376bf215546Sopenharmony_ci if (unlikely(result != VK_SUCCESS)) 377bf215546Sopenharmony_ci return result; 378bf215546Sopenharmony_ci } 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci return VK_SUCCESS; 381bf215546Sopenharmony_ci} 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci#ifndef _WIN32 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 386bf215546Sopenharmony_civk_common_ImportSemaphoreFdKHR(VkDevice _device, 387bf215546Sopenharmony_ci const VkImportSemaphoreFdInfoKHR *pImportSemaphoreFdInfo) 388bf215546Sopenharmony_ci{ 389bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 390bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_semaphore, semaphore, pImportSemaphoreFdInfo->semaphore); 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci assert(pImportSemaphoreFdInfo->sType == 393bf215546Sopenharmony_ci VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR); 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci const int fd = pImportSemaphoreFdInfo->fd; 396bf215546Sopenharmony_ci const VkExternalSemaphoreHandleTypeFlagBits handle_type = 397bf215546Sopenharmony_ci pImportSemaphoreFdInfo->handleType; 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_ci struct vk_sync *temporary = NULL, *sync; 400bf215546Sopenharmony_ci if (pImportSemaphoreFdInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT) { 401bf215546Sopenharmony_ci /* From the Vulkan 1.2.194 spec: 402bf215546Sopenharmony_ci * 403bf215546Sopenharmony_ci * VUID-VkImportSemaphoreFdInfoKHR-flags-03323 404bf215546Sopenharmony_ci * 405bf215546Sopenharmony_ci * "If flags contains VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, the 406bf215546Sopenharmony_ci * VkSemaphoreTypeCreateInfo::semaphoreType field of the semaphore 407bf215546Sopenharmony_ci * from which handle or name was exported must not be 408bf215546Sopenharmony_ci * VK_SEMAPHORE_TYPE_TIMELINE" 409bf215546Sopenharmony_ci */ 410bf215546Sopenharmony_ci if (unlikely(semaphore->type == VK_SEMAPHORE_TYPE_TIMELINE)) { 411bf215546Sopenharmony_ci return vk_errorf(device, VK_ERROR_UNKNOWN, 412bf215546Sopenharmony_ci "Cannot temporarily import into a timeline " 413bf215546Sopenharmony_ci "semaphore"); 414bf215546Sopenharmony_ci } 415bf215546Sopenharmony_ci 416bf215546Sopenharmony_ci const struct vk_sync_type *sync_type = 417bf215546Sopenharmony_ci get_semaphore_sync_type(device->physical, semaphore->type, handle_type); 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci VkResult result = vk_sync_create(device, sync_type, 0 /* flags */, 420bf215546Sopenharmony_ci 0 /* initial_value */, &temporary); 421bf215546Sopenharmony_ci if (result != VK_SUCCESS) 422bf215546Sopenharmony_ci return result; 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci sync = temporary; 425bf215546Sopenharmony_ci } else { 426bf215546Sopenharmony_ci sync = &semaphore->permanent; 427bf215546Sopenharmony_ci } 428bf215546Sopenharmony_ci assert(handle_type & 429bf215546Sopenharmony_ci vk_sync_semaphore_handle_types(sync->type, semaphore->type)); 430bf215546Sopenharmony_ci 431bf215546Sopenharmony_ci VkResult result; 432bf215546Sopenharmony_ci switch (pImportSemaphoreFdInfo->handleType) { 433bf215546Sopenharmony_ci case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: 434bf215546Sopenharmony_ci result = vk_sync_import_opaque_fd(device, sync, fd); 435bf215546Sopenharmony_ci break; 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_ci case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: 438bf215546Sopenharmony_ci result = vk_sync_import_sync_file(device, sync, fd); 439bf215546Sopenharmony_ci break; 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci default: 442bf215546Sopenharmony_ci result = vk_error(semaphore, VK_ERROR_INVALID_EXTERNAL_HANDLE); 443bf215546Sopenharmony_ci } 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 446bf215546Sopenharmony_ci if (temporary != NULL) 447bf215546Sopenharmony_ci vk_sync_destroy(device, temporary); 448bf215546Sopenharmony_ci return result; 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci /* From the Vulkan 1.2.194 spec: 452bf215546Sopenharmony_ci * 453bf215546Sopenharmony_ci * "Importing a semaphore payload from a file descriptor transfers 454bf215546Sopenharmony_ci * ownership of the file descriptor from the application to the Vulkan 455bf215546Sopenharmony_ci * implementation. The application must not perform any operations on 456bf215546Sopenharmony_ci * the file descriptor after a successful import." 457bf215546Sopenharmony_ci * 458bf215546Sopenharmony_ci * If the import fails, we leave the file descriptor open. 459bf215546Sopenharmony_ci */ 460bf215546Sopenharmony_ci if (fd != -1) 461bf215546Sopenharmony_ci close(fd); 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci /* From a spec correctness point of view, we could probably replace the 464bf215546Sopenharmony_ci * semaphore's temporary payload with the new vk_sync at the top. However, 465bf215546Sopenharmony_ci * we choose to be nice to applications and only replace the semaphore if 466bf215546Sopenharmony_ci * the import succeeded. 467bf215546Sopenharmony_ci */ 468bf215546Sopenharmony_ci if (temporary) { 469bf215546Sopenharmony_ci vk_semaphore_reset_temporary(device, semaphore); 470bf215546Sopenharmony_ci semaphore->temporary = temporary; 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci return VK_SUCCESS; 474bf215546Sopenharmony_ci} 475bf215546Sopenharmony_ci 476bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 477bf215546Sopenharmony_civk_common_GetSemaphoreFdKHR(VkDevice _device, 478bf215546Sopenharmony_ci const VkSemaphoreGetFdInfoKHR *pGetFdInfo, 479bf215546Sopenharmony_ci int *pFd) 480bf215546Sopenharmony_ci{ 481bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_device, device, _device); 482bf215546Sopenharmony_ci VK_FROM_HANDLE(vk_semaphore, semaphore, pGetFdInfo->semaphore); 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR); 485bf215546Sopenharmony_ci 486bf215546Sopenharmony_ci struct vk_sync *sync = vk_semaphore_get_active_sync(semaphore); 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci VkResult result; 489bf215546Sopenharmony_ci switch (pGetFdInfo->handleType) { 490bf215546Sopenharmony_ci case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: 491bf215546Sopenharmony_ci result = vk_sync_export_opaque_fd(device, sync, pFd); 492bf215546Sopenharmony_ci if (result != VK_SUCCESS) 493bf215546Sopenharmony_ci return result; 494bf215546Sopenharmony_ci break; 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: 497bf215546Sopenharmony_ci /* From the Vulkan 1.2.194 spec: 498bf215546Sopenharmony_ci * 499bf215546Sopenharmony_ci * VUID-VkSemaphoreGetFdInfoKHR-handleType-03253 500bf215546Sopenharmony_ci * 501bf215546Sopenharmony_ci * "If handleType refers to a handle type with copy payload 502bf215546Sopenharmony_ci * transference semantics, semaphore must have been created with a 503bf215546Sopenharmony_ci * VkSemaphoreType of VK_SEMAPHORE_TYPE_BINARY." 504bf215546Sopenharmony_ci */ 505bf215546Sopenharmony_ci if (unlikely(semaphore->type != VK_SEMAPHORE_TYPE_BINARY)) { 506bf215546Sopenharmony_ci return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE, 507bf215546Sopenharmony_ci "Cannot export a timeline semaphore as SYNC_FD"); 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci /* From the Vulkan 1.2.194 spec: 511bf215546Sopenharmony_ci * VUID-VkSemaphoreGetFdInfoKHR-handleType-03254 512bf215546Sopenharmony_ci * 513bf215546Sopenharmony_ci * "If handleType refers to a handle type with copy payload 514bf215546Sopenharmony_ci * transference semantics, semaphore must have an associated 515bf215546Sopenharmony_ci * semaphore signal operation that has been submitted for execution 516bf215546Sopenharmony_ci * and any semaphore signal operations on which it depends (if any) 517bf215546Sopenharmony_ci * must have also been submitted for execution." 518bf215546Sopenharmony_ci * 519bf215546Sopenharmony_ci * If we have real timelines, it's possible that the time point doesn't 520bf215546Sopenharmony_ci * exist yet and is waiting for one of our submit threads to trigger. 521bf215546Sopenharmony_ci * However, thanks to the above bit of spec text, that wait should never 522bf215546Sopenharmony_ci * block for long. 523bf215546Sopenharmony_ci */ 524bf215546Sopenharmony_ci if (vk_device_supports_threaded_submit(device)) { 525bf215546Sopenharmony_ci result = vk_sync_wait(device, sync, 0, 526bf215546Sopenharmony_ci VK_SYNC_WAIT_PENDING, 527bf215546Sopenharmony_ci UINT64_MAX); 528bf215546Sopenharmony_ci if (unlikely(result != VK_SUCCESS)) 529bf215546Sopenharmony_ci return result; 530bf215546Sopenharmony_ci } 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci result = vk_sync_export_sync_file(device, sync, pFd); 533bf215546Sopenharmony_ci if (unlikely(result != VK_SUCCESS)) 534bf215546Sopenharmony_ci return result; 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci /* From the Vulkan 1.2.194 spec: 537bf215546Sopenharmony_ci * 538bf215546Sopenharmony_ci * "Export operations have the same transference as the specified 539bf215546Sopenharmony_ci * handle type’s import operations. Additionally, exporting a 540bf215546Sopenharmony_ci * semaphore payload to a handle with copy transference has the same 541bf215546Sopenharmony_ci * side effects on the source semaphore’s payload as executing a 542bf215546Sopenharmony_ci * semaphore wait operation." 543bf215546Sopenharmony_ci * 544bf215546Sopenharmony_ci * In other words, exporting a sync file also resets the semaphore. We 545bf215546Sopenharmony_ci * only care about this for the permanent payload because the temporary 546bf215546Sopenharmony_ci * payload will be destroyed below. 547bf215546Sopenharmony_ci */ 548bf215546Sopenharmony_ci if (sync == &semaphore->permanent) { 549bf215546Sopenharmony_ci result = vk_sync_reset(device, sync); 550bf215546Sopenharmony_ci if (unlikely(result != VK_SUCCESS)) 551bf215546Sopenharmony_ci return result; 552bf215546Sopenharmony_ci } 553bf215546Sopenharmony_ci break; 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci default: 556bf215546Sopenharmony_ci unreachable("Invalid semaphore export handle type"); 557bf215546Sopenharmony_ci } 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci /* From the Vulkan 1.2.194 spec: 560bf215546Sopenharmony_ci * 561bf215546Sopenharmony_ci * "Export operations have the same transference as the specified 562bf215546Sopenharmony_ci * handle type’s import operations. [...] If the semaphore was using 563bf215546Sopenharmony_ci * a temporarily imported payload, the semaphore’s prior permanent 564bf215546Sopenharmony_ci * payload will be restored." 565bf215546Sopenharmony_ci */ 566bf215546Sopenharmony_ci vk_semaphore_reset_temporary(device, semaphore); 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci return VK_SUCCESS; 569bf215546Sopenharmony_ci} 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci#endif /* !defined(_WIN32) */ 572