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