xref: /aosp_15_r20/external/mesa3d/src/vulkan/runtime/vk_fence.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2021 Intel Corporation
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*61046927SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include "vk_fence.h"
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #include "util/os_time.h"
27*61046927SAndroid Build Coastguard Worker #include "util/perf/cpu_trace.h"
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker #ifndef _WIN32
30*61046927SAndroid Build Coastguard Worker #include <unistd.h>
31*61046927SAndroid Build Coastguard Worker #endif
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include "vk_common_entrypoints.h"
34*61046927SAndroid Build Coastguard Worker #include "vk_device.h"
35*61046927SAndroid Build Coastguard Worker #include "vk_log.h"
36*61046927SAndroid Build Coastguard Worker #include "vk_physical_device.h"
37*61046927SAndroid Build Coastguard Worker #include "vk_util.h"
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker static VkExternalFenceHandleTypeFlags
vk_sync_fence_import_types(const struct vk_sync_type * type)40*61046927SAndroid Build Coastguard Worker vk_sync_fence_import_types(const struct vk_sync_type *type)
41*61046927SAndroid Build Coastguard Worker {
42*61046927SAndroid Build Coastguard Worker    VkExternalFenceHandleTypeFlags handle_types = 0;
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker    if (type->import_opaque_fd)
45*61046927SAndroid Build Coastguard Worker       handle_types |= VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker    if (type->import_sync_file)
48*61046927SAndroid Build Coastguard Worker       handle_types |= VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker    return handle_types;
51*61046927SAndroid Build Coastguard Worker }
52*61046927SAndroid Build Coastguard Worker 
53*61046927SAndroid Build Coastguard Worker static VkExternalFenceHandleTypeFlags
vk_sync_fence_export_types(const struct vk_sync_type * type)54*61046927SAndroid Build Coastguard Worker vk_sync_fence_export_types(const struct vk_sync_type *type)
55*61046927SAndroid Build Coastguard Worker {
56*61046927SAndroid Build Coastguard Worker    VkExternalFenceHandleTypeFlags handle_types = 0;
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker    if (type->export_opaque_fd)
59*61046927SAndroid Build Coastguard Worker       handle_types |= VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker    if (type->export_sync_file)
62*61046927SAndroid Build Coastguard Worker       handle_types |= VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker    return handle_types;
65*61046927SAndroid Build Coastguard Worker }
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker static VkExternalFenceHandleTypeFlags
vk_sync_fence_handle_types(const struct vk_sync_type * type)68*61046927SAndroid Build Coastguard Worker vk_sync_fence_handle_types(const struct vk_sync_type *type)
69*61046927SAndroid Build Coastguard Worker {
70*61046927SAndroid Build Coastguard Worker    return vk_sync_fence_export_types(type) &
71*61046927SAndroid Build Coastguard Worker           vk_sync_fence_import_types(type);
72*61046927SAndroid Build Coastguard Worker }
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker static const struct vk_sync_type *
get_fence_sync_type(struct vk_physical_device * pdevice,VkExternalFenceHandleTypeFlags handle_types)75*61046927SAndroid Build Coastguard Worker get_fence_sync_type(struct vk_physical_device *pdevice,
76*61046927SAndroid Build Coastguard Worker                     VkExternalFenceHandleTypeFlags handle_types)
77*61046927SAndroid Build Coastguard Worker {
78*61046927SAndroid Build Coastguard Worker    static const enum vk_sync_features req_features =
79*61046927SAndroid Build Coastguard Worker       VK_SYNC_FEATURE_BINARY |
80*61046927SAndroid Build Coastguard Worker       VK_SYNC_FEATURE_CPU_WAIT |
81*61046927SAndroid Build Coastguard Worker       VK_SYNC_FEATURE_CPU_RESET;
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker    for (const struct vk_sync_type *const *t =
84*61046927SAndroid Build Coastguard Worker         pdevice->supported_sync_types; *t; t++) {
85*61046927SAndroid Build Coastguard Worker       if (req_features & ~(*t)->features)
86*61046927SAndroid Build Coastguard Worker          continue;
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker       if (handle_types & ~vk_sync_fence_handle_types(*t))
89*61046927SAndroid Build Coastguard Worker          continue;
90*61046927SAndroid Build Coastguard Worker 
91*61046927SAndroid Build Coastguard Worker       return *t;
92*61046927SAndroid Build Coastguard Worker    }
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker    return NULL;
95*61046927SAndroid Build Coastguard Worker }
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker VkResult
vk_fence_create(struct vk_device * device,const VkFenceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,struct vk_fence ** fence_out)98*61046927SAndroid Build Coastguard Worker vk_fence_create(struct vk_device *device,
99*61046927SAndroid Build Coastguard Worker                 const VkFenceCreateInfo *pCreateInfo,
100*61046927SAndroid Build Coastguard Worker                 const VkAllocationCallbacks *pAllocator,
101*61046927SAndroid Build Coastguard Worker                 struct vk_fence **fence_out)
102*61046927SAndroid Build Coastguard Worker {
103*61046927SAndroid Build Coastguard Worker    struct vk_fence *fence;
104*61046927SAndroid Build Coastguard Worker 
105*61046927SAndroid Build Coastguard Worker    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker    const VkExportFenceCreateInfo *export =
108*61046927SAndroid Build Coastguard Worker       vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO);
109*61046927SAndroid Build Coastguard Worker    VkExternalFenceHandleTypeFlags handle_types =
110*61046927SAndroid Build Coastguard Worker       export ? export->handleTypes : 0;
111*61046927SAndroid Build Coastguard Worker 
112*61046927SAndroid Build Coastguard Worker    const struct vk_sync_type *sync_type =
113*61046927SAndroid Build Coastguard Worker       get_fence_sync_type(device->physical, handle_types);
114*61046927SAndroid Build Coastguard Worker    if (sync_type == NULL) {
115*61046927SAndroid Build Coastguard Worker       /* We should always be able to get a fence type for internal */
116*61046927SAndroid Build Coastguard Worker       assert(get_fence_sync_type(device->physical, 0) != NULL);
117*61046927SAndroid Build Coastguard Worker       return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
118*61046927SAndroid Build Coastguard Worker                        "Combination of external handle types is unsupported "
119*61046927SAndroid Build Coastguard Worker                        "for VkFence creation.");
120*61046927SAndroid Build Coastguard Worker    }
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    /* Allocate a vk_fence + vk_sync implementation. Because the permanent
123*61046927SAndroid Build Coastguard Worker     * field of vk_fence is the base field of the vk_sync implementation, we
124*61046927SAndroid Build Coastguard Worker     * can make the 2 structures overlap.
125*61046927SAndroid Build Coastguard Worker     */
126*61046927SAndroid Build Coastguard Worker    size_t size = offsetof(struct vk_fence, permanent) + sync_type->size;
127*61046927SAndroid Build Coastguard Worker    fence = vk_object_zalloc(device, pAllocator, size, VK_OBJECT_TYPE_FENCE);
128*61046927SAndroid Build Coastguard Worker    if (fence == NULL)
129*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
130*61046927SAndroid Build Coastguard Worker 
131*61046927SAndroid Build Coastguard Worker    enum vk_sync_flags sync_flags = 0;
132*61046927SAndroid Build Coastguard Worker    if (handle_types)
133*61046927SAndroid Build Coastguard Worker       sync_flags |= VK_SYNC_IS_SHAREABLE;
134*61046927SAndroid Build Coastguard Worker 
135*61046927SAndroid Build Coastguard Worker    bool signaled = pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT;
136*61046927SAndroid Build Coastguard Worker    VkResult result = vk_sync_init(device, &fence->permanent,
137*61046927SAndroid Build Coastguard Worker                                   sync_type, sync_flags, signaled);
138*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
139*61046927SAndroid Build Coastguard Worker       vk_object_free(device, pAllocator, fence);
140*61046927SAndroid Build Coastguard Worker       return result;
141*61046927SAndroid Build Coastguard Worker    }
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker    *fence_out = fence;
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
146*61046927SAndroid Build Coastguard Worker }
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateFence(VkDevice _device,const VkFenceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkFence * pFence)149*61046927SAndroid Build Coastguard Worker vk_common_CreateFence(VkDevice _device,
150*61046927SAndroid Build Coastguard Worker                       const VkFenceCreateInfo *pCreateInfo,
151*61046927SAndroid Build Coastguard Worker                       const VkAllocationCallbacks *pAllocator,
152*61046927SAndroid Build Coastguard Worker                       VkFence *pFence)
153*61046927SAndroid Build Coastguard Worker {
154*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
155*61046927SAndroid Build Coastguard Worker    struct vk_fence *fence = NULL;
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    VkResult result = vk_fence_create(device, pCreateInfo, pAllocator, &fence);
158*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
159*61046927SAndroid Build Coastguard Worker       return result;
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker    *pFence = vk_fence_to_handle(fence);
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
164*61046927SAndroid Build Coastguard Worker }
165*61046927SAndroid Build Coastguard Worker 
166*61046927SAndroid Build Coastguard Worker void
vk_fence_reset_temporary(struct vk_device * device,struct vk_fence * fence)167*61046927SAndroid Build Coastguard Worker vk_fence_reset_temporary(struct vk_device *device,
168*61046927SAndroid Build Coastguard Worker                          struct vk_fence *fence)
169*61046927SAndroid Build Coastguard Worker {
170*61046927SAndroid Build Coastguard Worker    if (fence->temporary == NULL)
171*61046927SAndroid Build Coastguard Worker       return;
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker    vk_sync_destroy(device, fence->temporary);
174*61046927SAndroid Build Coastguard Worker    fence->temporary = NULL;
175*61046927SAndroid Build Coastguard Worker }
176*61046927SAndroid Build Coastguard Worker 
177*61046927SAndroid Build Coastguard Worker void
vk_fence_destroy(struct vk_device * device,struct vk_fence * fence,const VkAllocationCallbacks * pAllocator)178*61046927SAndroid Build Coastguard Worker vk_fence_destroy(struct vk_device *device,
179*61046927SAndroid Build Coastguard Worker                  struct vk_fence *fence,
180*61046927SAndroid Build Coastguard Worker                  const VkAllocationCallbacks *pAllocator)
181*61046927SAndroid Build Coastguard Worker {
182*61046927SAndroid Build Coastguard Worker    vk_fence_reset_temporary(device, fence);
183*61046927SAndroid Build Coastguard Worker    vk_sync_finish(device, &fence->permanent);
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker    vk_object_free(device, pAllocator, fence);
186*61046927SAndroid Build Coastguard Worker }
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyFence(VkDevice _device,VkFence _fence,const VkAllocationCallbacks * pAllocator)189*61046927SAndroid Build Coastguard Worker vk_common_DestroyFence(VkDevice _device,
190*61046927SAndroid Build Coastguard Worker                        VkFence _fence,
191*61046927SAndroid Build Coastguard Worker                        const VkAllocationCallbacks *pAllocator)
192*61046927SAndroid Build Coastguard Worker {
193*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
194*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_fence, fence, _fence);
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker    if (fence == NULL)
197*61046927SAndroid Build Coastguard Worker       return;
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker    vk_fence_destroy(device, fence, pAllocator);
200*61046927SAndroid Build Coastguard Worker }
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_ResetFences(VkDevice _device,uint32_t fenceCount,const VkFence * pFences)203*61046927SAndroid Build Coastguard Worker vk_common_ResetFences(VkDevice _device,
204*61046927SAndroid Build Coastguard Worker                       uint32_t fenceCount,
205*61046927SAndroid Build Coastguard Worker                       const VkFence *pFences)
206*61046927SAndroid Build Coastguard Worker {
207*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < fenceCount; i++) {
210*61046927SAndroid Build Coastguard Worker       VK_FROM_HANDLE(vk_fence, fence, pFences[i]);
211*61046927SAndroid Build Coastguard Worker 
212*61046927SAndroid Build Coastguard Worker       /* From the Vulkan 1.2.194 spec:
213*61046927SAndroid Build Coastguard Worker        *
214*61046927SAndroid Build Coastguard Worker        *    "If any member of pFences currently has its payload imported with
215*61046927SAndroid Build Coastguard Worker        *    temporary permanence, that fence’s prior permanent payload is
216*61046927SAndroid Build Coastguard Worker        *    first restored. The remaining operations described therefore
217*61046927SAndroid Build Coastguard Worker        *    operate on the restored payload."
218*61046927SAndroid Build Coastguard Worker        */
219*61046927SAndroid Build Coastguard Worker       vk_fence_reset_temporary(device, fence);
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker       VkResult result = vk_sync_reset(device, &fence->permanent);
222*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
223*61046927SAndroid Build Coastguard Worker          return result;
224*61046927SAndroid Build Coastguard Worker    }
225*61046927SAndroid Build Coastguard Worker 
226*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
227*61046927SAndroid Build Coastguard Worker }
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_GetFenceStatus(VkDevice _device,VkFence _fence)230*61046927SAndroid Build Coastguard Worker vk_common_GetFenceStatus(VkDevice _device,
231*61046927SAndroid Build Coastguard Worker                          VkFence _fence)
232*61046927SAndroid Build Coastguard Worker {
233*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
234*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_fence, fence, _fence);
235*61046927SAndroid Build Coastguard Worker 
236*61046927SAndroid Build Coastguard Worker    if (vk_device_is_lost(device))
237*61046927SAndroid Build Coastguard Worker       return VK_ERROR_DEVICE_LOST;
238*61046927SAndroid Build Coastguard Worker 
239*61046927SAndroid Build Coastguard Worker    VkResult result = vk_sync_wait(device, vk_fence_get_active_sync(fence),
240*61046927SAndroid Build Coastguard Worker                                   0 /* wait_value */,
241*61046927SAndroid Build Coastguard Worker                                   VK_SYNC_WAIT_COMPLETE,
242*61046927SAndroid Build Coastguard Worker                                   0 /* abs_timeout_ns */);
243*61046927SAndroid Build Coastguard Worker    if (result == VK_TIMEOUT)
244*61046927SAndroid Build Coastguard Worker       return VK_NOT_READY;
245*61046927SAndroid Build Coastguard Worker    else
246*61046927SAndroid Build Coastguard Worker       return result;
247*61046927SAndroid Build Coastguard Worker }
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_WaitForFences(VkDevice _device,uint32_t fenceCount,const VkFence * pFences,VkBool32 waitAll,uint64_t timeout)250*61046927SAndroid Build Coastguard Worker vk_common_WaitForFences(VkDevice _device,
251*61046927SAndroid Build Coastguard Worker                         uint32_t fenceCount,
252*61046927SAndroid Build Coastguard Worker                         const VkFence *pFences,
253*61046927SAndroid Build Coastguard Worker                         VkBool32 waitAll,
254*61046927SAndroid Build Coastguard Worker                         uint64_t timeout)
255*61046927SAndroid Build Coastguard Worker {
256*61046927SAndroid Build Coastguard Worker    MESA_TRACE_FUNC();
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker    if (vk_device_is_lost(device))
261*61046927SAndroid Build Coastguard Worker       return VK_ERROR_DEVICE_LOST;
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker    if (fenceCount == 0)
264*61046927SAndroid Build Coastguard Worker       return VK_SUCCESS;
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker    uint64_t abs_timeout_ns = os_time_get_absolute_timeout(timeout);
267*61046927SAndroid Build Coastguard Worker 
268*61046927SAndroid Build Coastguard Worker    STACK_ARRAY(struct vk_sync_wait, waits, fenceCount);
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < fenceCount; i++) {
271*61046927SAndroid Build Coastguard Worker       VK_FROM_HANDLE(vk_fence, fence, pFences[i]);
272*61046927SAndroid Build Coastguard Worker       waits[i] = (struct vk_sync_wait) {
273*61046927SAndroid Build Coastguard Worker          .sync = vk_fence_get_active_sync(fence),
274*61046927SAndroid Build Coastguard Worker          .stage_mask = ~(VkPipelineStageFlags2)0,
275*61046927SAndroid Build Coastguard Worker       };
276*61046927SAndroid Build Coastguard Worker    }
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker    enum vk_sync_wait_flags wait_flags = VK_SYNC_WAIT_COMPLETE;
279*61046927SAndroid Build Coastguard Worker    if (!waitAll)
280*61046927SAndroid Build Coastguard Worker       wait_flags |= VK_SYNC_WAIT_ANY;
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker    VkResult result = vk_sync_wait_many(device, fenceCount, waits,
283*61046927SAndroid Build Coastguard Worker                                        wait_flags, abs_timeout_ns);
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker    STACK_ARRAY_FINISH(waits);
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker    VkResult device_status = vk_device_check_status(device);
288*61046927SAndroid Build Coastguard Worker    if (device_status != VK_SUCCESS)
289*61046927SAndroid Build Coastguard Worker       return device_status;
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    return result;
292*61046927SAndroid Build Coastguard Worker }
293*61046927SAndroid Build Coastguard Worker 
294*61046927SAndroid Build Coastguard Worker VKAPI_ATTR void VKAPI_CALL
vk_common_GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalFenceInfo * pExternalFenceInfo,VkExternalFenceProperties * pExternalFenceProperties)295*61046927SAndroid Build Coastguard Worker vk_common_GetPhysicalDeviceExternalFenceProperties(
296*61046927SAndroid Build Coastguard Worker    VkPhysicalDevice physicalDevice,
297*61046927SAndroid Build Coastguard Worker    const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
298*61046927SAndroid Build Coastguard Worker    VkExternalFenceProperties *pExternalFenceProperties)
299*61046927SAndroid Build Coastguard Worker {
300*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker    assert(pExternalFenceInfo->sType ==
303*61046927SAndroid Build Coastguard Worker           VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO);
304*61046927SAndroid Build Coastguard Worker    const VkExternalFenceHandleTypeFlagBits handle_type =
305*61046927SAndroid Build Coastguard Worker       pExternalFenceInfo->handleType;
306*61046927SAndroid Build Coastguard Worker 
307*61046927SAndroid Build Coastguard Worker    const struct vk_sync_type *sync_type =
308*61046927SAndroid Build Coastguard Worker       get_fence_sync_type(pdevice, handle_type);
309*61046927SAndroid Build Coastguard Worker    if (sync_type == NULL) {
310*61046927SAndroid Build Coastguard Worker       pExternalFenceProperties->exportFromImportedHandleTypes = 0;
311*61046927SAndroid Build Coastguard Worker       pExternalFenceProperties->compatibleHandleTypes = 0;
312*61046927SAndroid Build Coastguard Worker       pExternalFenceProperties->externalFenceFeatures = 0;
313*61046927SAndroid Build Coastguard Worker       return;
314*61046927SAndroid Build Coastguard Worker    }
315*61046927SAndroid Build Coastguard Worker 
316*61046927SAndroid Build Coastguard Worker    VkExternalFenceHandleTypeFlagBits import =
317*61046927SAndroid Build Coastguard Worker       vk_sync_fence_import_types(sync_type);
318*61046927SAndroid Build Coastguard Worker    VkExternalFenceHandleTypeFlagBits export =
319*61046927SAndroid Build Coastguard Worker       vk_sync_fence_export_types(sync_type);
320*61046927SAndroid Build Coastguard Worker 
321*61046927SAndroid Build Coastguard Worker    if (handle_type != VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT) {
322*61046927SAndroid Build Coastguard Worker       const struct vk_sync_type *opaque_sync_type =
323*61046927SAndroid Build Coastguard Worker          get_fence_sync_type(pdevice, VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT);
324*61046927SAndroid Build Coastguard Worker 
325*61046927SAndroid Build Coastguard Worker       /* If we're a different vk_sync_type than the one selected when only
326*61046927SAndroid Build Coastguard Worker        * OPAQUE_FD is set, then we can't import/export OPAQUE_FD.  Put
327*61046927SAndroid Build Coastguard Worker        * differently, there can only be one OPAQUE_FD sync type.
328*61046927SAndroid Build Coastguard Worker        */
329*61046927SAndroid Build Coastguard Worker       if (sync_type != opaque_sync_type) {
330*61046927SAndroid Build Coastguard Worker          import &= ~VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
331*61046927SAndroid Build Coastguard Worker          export &= ~VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
332*61046927SAndroid Build Coastguard Worker       }
333*61046927SAndroid Build Coastguard Worker    }
334*61046927SAndroid Build Coastguard Worker 
335*61046927SAndroid Build Coastguard Worker    VkExternalFenceHandleTypeFlags compatible = import & export;
336*61046927SAndroid Build Coastguard Worker    VkExternalFenceFeatureFlags features = 0;
337*61046927SAndroid Build Coastguard Worker    if (handle_type & export)
338*61046927SAndroid Build Coastguard Worker       features |= VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT;
339*61046927SAndroid Build Coastguard Worker    if (handle_type & import)
340*61046927SAndroid Build Coastguard Worker       features |= VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT;
341*61046927SAndroid Build Coastguard Worker 
342*61046927SAndroid Build Coastguard Worker    pExternalFenceProperties->exportFromImportedHandleTypes = export;
343*61046927SAndroid Build Coastguard Worker    pExternalFenceProperties->compatibleHandleTypes = compatible;
344*61046927SAndroid Build Coastguard Worker    pExternalFenceProperties->externalFenceFeatures = features;
345*61046927SAndroid Build Coastguard Worker }
346*61046927SAndroid Build Coastguard Worker 
347*61046927SAndroid Build Coastguard Worker #ifndef _WIN32
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_ImportFenceFdKHR(VkDevice _device,const VkImportFenceFdInfoKHR * pImportFenceFdInfo)350*61046927SAndroid Build Coastguard Worker vk_common_ImportFenceFdKHR(VkDevice _device,
351*61046927SAndroid Build Coastguard Worker                            const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
352*61046927SAndroid Build Coastguard Worker {
353*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
354*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_fence, fence, pImportFenceFdInfo->fence);
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker    assert(pImportFenceFdInfo->sType ==
357*61046927SAndroid Build Coastguard Worker           VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR);
358*61046927SAndroid Build Coastguard Worker 
359*61046927SAndroid Build Coastguard Worker    const int fd = pImportFenceFdInfo->fd;
360*61046927SAndroid Build Coastguard Worker    const VkExternalFenceHandleTypeFlagBits handle_type =
361*61046927SAndroid Build Coastguard Worker       pImportFenceFdInfo->handleType;
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker    struct vk_sync *temporary = NULL, *sync;
364*61046927SAndroid Build Coastguard Worker    if (pImportFenceFdInfo->flags & VK_FENCE_IMPORT_TEMPORARY_BIT) {
365*61046927SAndroid Build Coastguard Worker       const struct vk_sync_type *sync_type =
366*61046927SAndroid Build Coastguard Worker          get_fence_sync_type(device->physical, handle_type);
367*61046927SAndroid Build Coastguard Worker 
368*61046927SAndroid Build Coastguard Worker       VkResult result = vk_sync_create(device, sync_type, 0 /* flags */,
369*61046927SAndroid Build Coastguard Worker                                        0 /* initial_value */, &temporary);
370*61046927SAndroid Build Coastguard Worker       if (result != VK_SUCCESS)
371*61046927SAndroid Build Coastguard Worker          return result;
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker       sync = temporary;
374*61046927SAndroid Build Coastguard Worker    } else {
375*61046927SAndroid Build Coastguard Worker       sync = &fence->permanent;
376*61046927SAndroid Build Coastguard Worker    }
377*61046927SAndroid Build Coastguard Worker    assert(handle_type & vk_sync_fence_handle_types(sync->type));
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker    VkResult result;
380*61046927SAndroid Build Coastguard Worker    switch (pImportFenceFdInfo->handleType) {
381*61046927SAndroid Build Coastguard Worker    case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
382*61046927SAndroid Build Coastguard Worker       result = vk_sync_import_opaque_fd(device, sync, fd);
383*61046927SAndroid Build Coastguard Worker       break;
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker    case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
386*61046927SAndroid Build Coastguard Worker       result = vk_sync_import_sync_file(device, sync, fd);
387*61046927SAndroid Build Coastguard Worker       break;
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker    default:
390*61046927SAndroid Build Coastguard Worker       result = vk_error(fence, VK_ERROR_INVALID_EXTERNAL_HANDLE);
391*61046927SAndroid Build Coastguard Worker    }
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
394*61046927SAndroid Build Coastguard Worker       if (temporary != NULL)
395*61046927SAndroid Build Coastguard Worker          vk_sync_destroy(device, temporary);
396*61046927SAndroid Build Coastguard Worker       return result;
397*61046927SAndroid Build Coastguard Worker    }
398*61046927SAndroid Build Coastguard Worker 
399*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.2.194 spec:
400*61046927SAndroid Build Coastguard Worker     *
401*61046927SAndroid Build Coastguard Worker     *    "Importing a fence payload from a file descriptor transfers
402*61046927SAndroid Build Coastguard Worker     *    ownership of the file descriptor from the application to the
403*61046927SAndroid Build Coastguard Worker     *    Vulkan implementation. The application must not perform any
404*61046927SAndroid Build Coastguard Worker     *    operations on the file descriptor after a successful import."
405*61046927SAndroid Build Coastguard Worker     *
406*61046927SAndroid Build Coastguard Worker     * If the import fails, we leave the file descriptor open.
407*61046927SAndroid Build Coastguard Worker     */
408*61046927SAndroid Build Coastguard Worker    if (fd != -1)
409*61046927SAndroid Build Coastguard Worker       close(fd);
410*61046927SAndroid Build Coastguard Worker 
411*61046927SAndroid Build Coastguard Worker    if (temporary) {
412*61046927SAndroid Build Coastguard Worker       vk_fence_reset_temporary(device, fence);
413*61046927SAndroid Build Coastguard Worker       fence->temporary = temporary;
414*61046927SAndroid Build Coastguard Worker    }
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
417*61046927SAndroid Build Coastguard Worker }
418*61046927SAndroid Build Coastguard Worker 
419*61046927SAndroid Build Coastguard Worker VKAPI_ATTR VkResult VKAPI_CALL
vk_common_GetFenceFdKHR(VkDevice _device,const VkFenceGetFdInfoKHR * pGetFdInfo,int * pFd)420*61046927SAndroid Build Coastguard Worker vk_common_GetFenceFdKHR(VkDevice _device,
421*61046927SAndroid Build Coastguard Worker                         const VkFenceGetFdInfoKHR *pGetFdInfo,
422*61046927SAndroid Build Coastguard Worker                         int *pFd)
423*61046927SAndroid Build Coastguard Worker {
424*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_device, device, _device);
425*61046927SAndroid Build Coastguard Worker    VK_FROM_HANDLE(vk_fence, fence, pGetFdInfo->fence);
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker    assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR);
428*61046927SAndroid Build Coastguard Worker 
429*61046927SAndroid Build Coastguard Worker    struct vk_sync *sync = vk_fence_get_active_sync(fence);
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker    VkResult result;
432*61046927SAndroid Build Coastguard Worker    switch (pGetFdInfo->handleType) {
433*61046927SAndroid Build Coastguard Worker    case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
434*61046927SAndroid Build Coastguard Worker       result = vk_sync_export_opaque_fd(device, sync, pFd);
435*61046927SAndroid Build Coastguard Worker       if (unlikely(result != VK_SUCCESS))
436*61046927SAndroid Build Coastguard Worker          return result;
437*61046927SAndroid Build Coastguard Worker       break;
438*61046927SAndroid Build Coastguard Worker 
439*61046927SAndroid Build Coastguard Worker    case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
440*61046927SAndroid Build Coastguard Worker       /* There's no direct spec quote for this but the same rules as for
441*61046927SAndroid Build Coastguard Worker        * semaphore export apply.  We can't export a sync file from a fence
442*61046927SAndroid Build Coastguard Worker        * if the fence event hasn't been submitted to the kernel yet.
443*61046927SAndroid Build Coastguard Worker        */
444*61046927SAndroid Build Coastguard Worker       if (vk_device_supports_threaded_submit(device)) {
445*61046927SAndroid Build Coastguard Worker          result = vk_sync_wait(device, sync, 0,
446*61046927SAndroid Build Coastguard Worker                                VK_SYNC_WAIT_PENDING,
447*61046927SAndroid Build Coastguard Worker                                UINT64_MAX);
448*61046927SAndroid Build Coastguard Worker          if (unlikely(result != VK_SUCCESS))
449*61046927SAndroid Build Coastguard Worker             return result;
450*61046927SAndroid Build Coastguard Worker       }
451*61046927SAndroid Build Coastguard Worker 
452*61046927SAndroid Build Coastguard Worker       result = vk_sync_export_sync_file(device, sync, pFd);
453*61046927SAndroid Build Coastguard Worker       if (unlikely(result != VK_SUCCESS))
454*61046927SAndroid Build Coastguard Worker          return result;
455*61046927SAndroid Build Coastguard Worker 
456*61046927SAndroid Build Coastguard Worker       /* From the Vulkan 1.2.194 spec:
457*61046927SAndroid Build Coastguard Worker        *
458*61046927SAndroid Build Coastguard Worker        *    "Export operations have the same transference as the specified
459*61046927SAndroid Build Coastguard Worker        *    handle type’s import operations. Additionally, exporting a fence
460*61046927SAndroid Build Coastguard Worker        *    payload to a handle with copy transference has the same side
461*61046927SAndroid Build Coastguard Worker        *    effects on the source fence’s payload as executing a fence reset
462*61046927SAndroid Build Coastguard Worker        *    operation."
463*61046927SAndroid Build Coastguard Worker        *
464*61046927SAndroid Build Coastguard Worker        * In other words, exporting a sync file also resets the fence.  We
465*61046927SAndroid Build Coastguard Worker        * only care about this for the permanent payload because the temporary
466*61046927SAndroid Build Coastguard Worker        * payload will be destroyed below.
467*61046927SAndroid Build Coastguard Worker        */
468*61046927SAndroid Build Coastguard Worker       if (sync == &fence->permanent) {
469*61046927SAndroid Build Coastguard Worker          result = vk_sync_reset(device, sync);
470*61046927SAndroid Build Coastguard Worker          if (unlikely(result != VK_SUCCESS))
471*61046927SAndroid Build Coastguard Worker             return result;
472*61046927SAndroid Build Coastguard Worker       }
473*61046927SAndroid Build Coastguard Worker       break;
474*61046927SAndroid Build Coastguard Worker 
475*61046927SAndroid Build Coastguard Worker    default:
476*61046927SAndroid Build Coastguard Worker       unreachable("Invalid fence export handle type");
477*61046927SAndroid Build Coastguard Worker    }
478*61046927SAndroid Build Coastguard Worker 
479*61046927SAndroid Build Coastguard Worker    /* From the Vulkan 1.2.194 spec:
480*61046927SAndroid Build Coastguard Worker     *
481*61046927SAndroid Build Coastguard Worker     *    "Export operations have the same transference as the specified
482*61046927SAndroid Build Coastguard Worker     *    handle type’s import operations. [...]  If the fence was using a
483*61046927SAndroid Build Coastguard Worker     *    temporarily imported payload, the fence’s prior permanent payload
484*61046927SAndroid Build Coastguard Worker     *    will be restored.
485*61046927SAndroid Build Coastguard Worker     */
486*61046927SAndroid Build Coastguard Worker    vk_fence_reset_temporary(device, fence);
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
489*61046927SAndroid Build Coastguard Worker }
490*61046927SAndroid Build Coastguard Worker 
491*61046927SAndroid Build Coastguard Worker #endif /* !defined(_WIN32) */
492