2021-10-19 04:36:44 +01:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2021 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "vk_fence.h"
|
|
|
|
|
|
|
|
|
|
#include "util/os_time.h"
|
|
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include "vk_common_entrypoints.h"
|
|
|
|
|
#include "vk_device.h"
|
|
|
|
|
#include "vk_log.h"
|
|
|
|
|
#include "vk_physical_device.h"
|
|
|
|
|
#include "vk_util.h"
|
|
|
|
|
|
|
|
|
|
static VkExternalFenceHandleTypeFlags
|
|
|
|
|
vk_sync_fence_import_types(const struct vk_sync_type *type)
|
|
|
|
|
{
|
|
|
|
|
VkExternalFenceHandleTypeFlags handle_types = 0;
|
|
|
|
|
|
|
|
|
|
if (type->import_opaque_fd)
|
|
|
|
|
handle_types |= VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
|
|
|
|
|
|
|
|
|
|
if (type->import_sync_file)
|
|
|
|
|
handle_types |= VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
|
|
|
|
|
|
|
|
|
|
return handle_types;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static VkExternalFenceHandleTypeFlags
|
|
|
|
|
vk_sync_fence_export_types(const struct vk_sync_type *type)
|
|
|
|
|
{
|
|
|
|
|
VkExternalFenceHandleTypeFlags handle_types = 0;
|
|
|
|
|
|
|
|
|
|
if (type->export_opaque_fd)
|
|
|
|
|
handle_types |= VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
|
|
|
|
|
|
|
|
|
|
if (type->export_sync_file)
|
|
|
|
|
handle_types |= VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT;
|
|
|
|
|
|
|
|
|
|
return handle_types;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static VkExternalFenceHandleTypeFlags
|
|
|
|
|
vk_sync_fence_handle_types(const struct vk_sync_type *type)
|
|
|
|
|
{
|
|
|
|
|
return vk_sync_fence_export_types(type) &
|
|
|
|
|
vk_sync_fence_import_types(type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct vk_sync_type *
|
|
|
|
|
get_fence_sync_type(struct vk_physical_device *pdevice,
|
|
|
|
|
VkExternalFenceHandleTypeFlags handle_types)
|
|
|
|
|
{
|
|
|
|
|
static const enum vk_sync_features req_features =
|
|
|
|
|
VK_SYNC_FEATURE_BINARY |
|
|
|
|
|
VK_SYNC_FEATURE_CPU_WAIT |
|
|
|
|
|
VK_SYNC_FEATURE_CPU_RESET;
|
|
|
|
|
|
|
|
|
|
for (const struct vk_sync_type *const *t =
|
|
|
|
|
pdevice->supported_sync_types; *t; t++) {
|
|
|
|
|
if (req_features & ~(*t)->features)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (handle_types & ~vk_sync_fence_handle_types(*t))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
return *t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
|
vk_fence_create(struct vk_device *device,
|
|
|
|
|
const VkFenceCreateInfo *pCreateInfo,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
struct vk_fence **fence_out)
|
|
|
|
|
{
|
|
|
|
|
struct vk_fence *fence;
|
|
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO);
|
|
|
|
|
|
|
|
|
|
const VkExportFenceCreateInfo *export =
|
|
|
|
|
vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO);
|
|
|
|
|
VkExternalFenceHandleTypeFlags handle_types =
|
|
|
|
|
export ? export->handleTypes : 0;
|
|
|
|
|
|
|
|
|
|
const struct vk_sync_type *sync_type =
|
|
|
|
|
get_fence_sync_type(device->physical, handle_types);
|
|
|
|
|
if (sync_type == NULL) {
|
|
|
|
|
/* We should always be able to get a fence type for internal */
|
|
|
|
|
assert(get_fence_sync_type(device->physical, 0) != NULL);
|
|
|
|
|
return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
|
|
|
|
|
"Combination of external handle types is unsupported "
|
|
|
|
|
"for VkFence creation.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Allocate a vk_fence + vk_sync implementation. Because the permanent
|
|
|
|
|
* field of vk_fence is the base field of the vk_sync implementation, we
|
|
|
|
|
* can make the 2 structures overlap.
|
|
|
|
|
*/
|
|
|
|
|
size_t size = offsetof(struct vk_fence, permanent) + sync_type->size;
|
|
|
|
|
fence = vk_object_zalloc(device, pAllocator, size, VK_OBJECT_TYPE_FENCE);
|
|
|
|
|
if (fence == NULL)
|
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
|
|
enum vk_sync_flags sync_flags = 0;
|
|
|
|
|
if (handle_types)
|
|
|
|
|
sync_flags |= VK_SYNC_IS_SHAREABLE;
|
|
|
|
|
|
|
|
|
|
bool signaled = pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT;
|
|
|
|
|
VkResult result = vk_sync_init(device, &fence->permanent,
|
|
|
|
|
sync_type, sync_flags, signaled);
|
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
|
vk_object_free(device, pAllocator, fence);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*fence_out = fence;
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
vk_common_CreateFence(VkDevice _device,
|
|
|
|
|
const VkFenceCreateInfo *pCreateInfo,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
VkFence *pFence)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
|
|
|
struct vk_fence *fence;
|
|
|
|
|
|
|
|
|
|
VkResult result = vk_fence_create(device, pCreateInfo, pAllocator, &fence);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
*pFence = vk_fence_to_handle(fence);
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
vk_fence_reset_temporary(struct vk_device *device,
|
|
|
|
|
struct vk_fence *fence)
|
|
|
|
|
{
|
|
|
|
|
if (fence->temporary == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
vk_sync_destroy(device, fence->temporary);
|
|
|
|
|
fence->temporary = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
vk_fence_destroy(struct vk_device *device,
|
|
|
|
|
struct vk_fence *fence,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
|
{
|
|
|
|
|
vk_fence_reset_temporary(device, fence);
|
|
|
|
|
vk_sync_finish(device, &fence->permanent);
|
|
|
|
|
|
|
|
|
|
vk_object_free(device, pAllocator, fence);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
|
|
|
vk_common_DestroyFence(VkDevice _device,
|
|
|
|
|
VkFence _fence,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
|
|
|
VK_FROM_HANDLE(vk_fence, fence, _fence);
|
|
|
|
|
|
|
|
|
|
if (fence == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
vk_fence_destroy(device, fence, pAllocator);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
vk_common_ResetFences(VkDevice _device,
|
|
|
|
|
uint32_t fenceCount,
|
|
|
|
|
const VkFence *pFences)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < fenceCount; i++) {
|
|
|
|
|
VK_FROM_HANDLE(vk_fence, fence, pFences[i]);
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.2.194 spec:
|
|
|
|
|
*
|
|
|
|
|
* "If any member of pFences currently has its payload imported with
|
|
|
|
|
* temporary permanence, that fence’s prior permanent payload is
|
|
|
|
|
* first restored. The remaining operations described therefore
|
|
|
|
|
* operate on the restored payload."
|
|
|
|
|
*/
|
|
|
|
|
vk_fence_reset_temporary(device, fence);
|
|
|
|
|
|
|
|
|
|
VkResult result = vk_sync_reset(device, &fence->permanent);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
vk_common_GetFenceStatus(VkDevice _device,
|
|
|
|
|
VkFence _fence)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
|
|
|
VK_FROM_HANDLE(vk_fence, fence, _fence);
|
|
|
|
|
|
|
|
|
|
if (vk_device_is_lost(device))
|
|
|
|
|
return VK_ERROR_DEVICE_LOST;
|
|
|
|
|
|
|
|
|
|
VkResult result = vk_sync_wait(device, vk_fence_get_active_sync(fence),
|
|
|
|
|
0 /* wait_value */,
|
|
|
|
|
VK_SYNC_WAIT_COMPLETE,
|
|
|
|
|
0 /* abs_timeout_ns */);
|
|
|
|
|
if (result == VK_TIMEOUT)
|
|
|
|
|
return VK_NOT_READY;
|
|
|
|
|
else
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
vk_common_WaitForFences(VkDevice _device,
|
|
|
|
|
uint32_t fenceCount,
|
|
|
|
|
const VkFence *pFences,
|
|
|
|
|
VkBool32 waitAll,
|
|
|
|
|
uint64_t timeout)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
|
|
|
|
|
|
|
|
if (vk_device_is_lost(device))
|
|
|
|
|
return VK_ERROR_DEVICE_LOST;
|
|
|
|
|
|
|
|
|
|
if (fenceCount == 0)
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
|
|
uint64_t abs_timeout_ns = os_time_get_absolute_timeout(timeout);
|
|
|
|
|
|
|
|
|
|
STACK_ARRAY(struct vk_sync_wait, waits, fenceCount);
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < fenceCount; i++) {
|
|
|
|
|
VK_FROM_HANDLE(vk_fence, fence, pFences[i]);
|
|
|
|
|
waits[i] = (struct vk_sync_wait) {
|
|
|
|
|
.sync = vk_fence_get_active_sync(fence),
|
2022-07-01 13:02:59 +01:00
|
|
|
|
.stage_mask = ~(VkPipelineStageFlags2)0,
|
2021-10-19 04:36:44 +01:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum vk_sync_wait_flags wait_flags = VK_SYNC_WAIT_COMPLETE;
|
|
|
|
|
if (!waitAll)
|
|
|
|
|
wait_flags |= VK_SYNC_WAIT_ANY;
|
|
|
|
|
|
|
|
|
|
VkResult result = vk_sync_wait_many(device, fenceCount, waits,
|
|
|
|
|
wait_flags, abs_timeout_ns);
|
|
|
|
|
|
|
|
|
|
STACK_ARRAY_FINISH(waits);
|
|
|
|
|
|
|
|
|
|
VkResult device_status = vk_device_check_status(device);
|
|
|
|
|
if (device_status != VK_SUCCESS)
|
|
|
|
|
return device_status;
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR void VKAPI_CALL
|
|
|
|
|
vk_common_GetPhysicalDeviceExternalFenceProperties(
|
|
|
|
|
VkPhysicalDevice physicalDevice,
|
|
|
|
|
const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
|
|
|
|
|
VkExternalFenceProperties *pExternalFenceProperties)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
|
|
|
|
|
|
|
|
|
|
assert(pExternalFenceInfo->sType ==
|
|
|
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_FENCE_INFO);
|
|
|
|
|
const VkExternalFenceHandleTypeFlagBits handle_type =
|
|
|
|
|
pExternalFenceInfo->handleType;
|
|
|
|
|
|
|
|
|
|
const struct vk_sync_type *sync_type =
|
|
|
|
|
get_fence_sync_type(pdevice, handle_type);
|
|
|
|
|
if (sync_type == NULL) {
|
|
|
|
|
pExternalFenceProperties->exportFromImportedHandleTypes = 0;
|
|
|
|
|
pExternalFenceProperties->compatibleHandleTypes = 0;
|
|
|
|
|
pExternalFenceProperties->externalFenceFeatures = 0;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkExternalFenceHandleTypeFlagBits import =
|
|
|
|
|
vk_sync_fence_import_types(sync_type);
|
|
|
|
|
VkExternalFenceHandleTypeFlagBits export =
|
|
|
|
|
vk_sync_fence_export_types(sync_type);
|
|
|
|
|
|
|
|
|
|
if (handle_type != VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT) {
|
|
|
|
|
const struct vk_sync_type *opaque_sync_type =
|
|
|
|
|
get_fence_sync_type(pdevice, VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT);
|
|
|
|
|
|
|
|
|
|
/* If we're a different vk_sync_type than the one selected when only
|
|
|
|
|
* OPAQUE_FD is set, then we can't import/export OPAQUE_FD. Put
|
|
|
|
|
* differently, there can only be one OPAQUE_FD sync type.
|
|
|
|
|
*/
|
|
|
|
|
if (sync_type != opaque_sync_type) {
|
|
|
|
|
import &= ~VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
|
|
|
|
|
export &= ~VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkExternalFenceHandleTypeFlags compatible = import & export;
|
|
|
|
|
VkExternalFenceFeatureFlags features = 0;
|
|
|
|
|
if (handle_type & export)
|
|
|
|
|
features |= VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT;
|
|
|
|
|
if (handle_type & import)
|
|
|
|
|
features |= VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT;
|
|
|
|
|
|
|
|
|
|
pExternalFenceProperties->exportFromImportedHandleTypes = export;
|
|
|
|
|
pExternalFenceProperties->compatibleHandleTypes = compatible;
|
|
|
|
|
pExternalFenceProperties->externalFenceFeatures = features;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
vk_common_ImportFenceFdKHR(VkDevice _device,
|
|
|
|
|
const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
|
|
|
VK_FROM_HANDLE(vk_fence, fence, pImportFenceFdInfo->fence);
|
|
|
|
|
|
|
|
|
|
assert(pImportFenceFdInfo->sType ==
|
|
|
|
|
VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR);
|
|
|
|
|
|
|
|
|
|
const int fd = pImportFenceFdInfo->fd;
|
|
|
|
|
const VkExternalFenceHandleTypeFlagBits handle_type =
|
|
|
|
|
pImportFenceFdInfo->handleType;
|
|
|
|
|
|
|
|
|
|
struct vk_sync *temporary = NULL, *sync;
|
|
|
|
|
if (pImportFenceFdInfo->flags & VK_FENCE_IMPORT_TEMPORARY_BIT) {
|
|
|
|
|
const struct vk_sync_type *sync_type =
|
|
|
|
|
get_fence_sync_type(device->physical, handle_type);
|
|
|
|
|
|
|
|
|
|
VkResult result = vk_sync_create(device, sync_type, 0 /* flags */,
|
|
|
|
|
0 /* initial_value */, &temporary);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
sync = temporary;
|
|
|
|
|
} else {
|
|
|
|
|
sync = &fence->permanent;
|
|
|
|
|
}
|
|
|
|
|
assert(handle_type & vk_sync_fence_handle_types(sync->type));
|
|
|
|
|
|
|
|
|
|
VkResult result;
|
|
|
|
|
switch (pImportFenceFdInfo->handleType) {
|
|
|
|
|
case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
|
|
|
|
|
result = vk_sync_import_opaque_fd(device, sync, fd);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
|
|
|
|
|
result = vk_sync_import_sync_file(device, sync, fd);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
result = vk_error(fence, VK_ERROR_INVALID_EXTERNAL_HANDLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
|
if (temporary != NULL)
|
|
|
|
|
vk_sync_destroy(device, temporary);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.2.194 spec:
|
|
|
|
|
*
|
|
|
|
|
* "Importing a fence payload from a file descriptor transfers
|
|
|
|
|
* ownership of the file descriptor from the application to the
|
|
|
|
|
* Vulkan implementation. The application must not perform any
|
|
|
|
|
* operations on the file descriptor after a successful import."
|
|
|
|
|
*
|
|
|
|
|
* If the import fails, we leave the file descriptor open.
|
|
|
|
|
*/
|
|
|
|
|
if (fd != -1)
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
|
|
if (temporary) {
|
|
|
|
|
vk_fence_reset_temporary(device, fence);
|
|
|
|
|
fence->temporary = temporary;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
|
vk_common_GetFenceFdKHR(VkDevice _device,
|
|
|
|
|
const VkFenceGetFdInfoKHR *pGetFdInfo,
|
|
|
|
|
int *pFd)
|
|
|
|
|
{
|
|
|
|
|
VK_FROM_HANDLE(vk_device, device, _device);
|
|
|
|
|
VK_FROM_HANDLE(vk_fence, fence, pGetFdInfo->fence);
|
|
|
|
|
|
|
|
|
|
assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR);
|
|
|
|
|
|
|
|
|
|
struct vk_sync *sync = vk_fence_get_active_sync(fence);
|
|
|
|
|
|
|
|
|
|
VkResult result;
|
|
|
|
|
switch (pGetFdInfo->handleType) {
|
|
|
|
|
case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT:
|
|
|
|
|
result = vk_sync_export_opaque_fd(device, sync, pFd);
|
|
|
|
|
if (unlikely(result != VK_SUCCESS))
|
|
|
|
|
return result;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT:
|
2021-10-19 20:27:25 +01:00
|
|
|
|
/* There's no direct spec quote for this but the same rules as for
|
|
|
|
|
* semaphore export apply. We can't export a sync file from a fence
|
|
|
|
|
* if the fence event hasn't been submitted to the kernel yet.
|
|
|
|
|
*/
|
2022-03-24 22:49:19 +00:00
|
|
|
|
if (vk_device_supports_threaded_submit(device)) {
|
2021-10-19 20:27:25 +01:00
|
|
|
|
result = vk_sync_wait(device, sync, 0,
|
|
|
|
|
VK_SYNC_WAIT_PENDING,
|
|
|
|
|
UINT64_MAX);
|
|
|
|
|
if (unlikely(result != VK_SUCCESS))
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-19 04:36:44 +01:00
|
|
|
|
result = vk_sync_export_sync_file(device, sync, pFd);
|
|
|
|
|
if (unlikely(result != VK_SUCCESS))
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.2.194 spec:
|
|
|
|
|
*
|
|
|
|
|
* "Export operations have the same transference as the specified
|
|
|
|
|
* handle type’s import operations. Additionally, exporting a fence
|
|
|
|
|
* payload to a handle with copy transference has the same side
|
|
|
|
|
* effects on the source fence’s payload as executing a fence reset
|
|
|
|
|
* operation."
|
|
|
|
|
*
|
|
|
|
|
* In other words, exporting a sync file also resets the fence. We
|
|
|
|
|
* only care about this for the permanent payload because the temporary
|
|
|
|
|
* payload will be destroyed below.
|
|
|
|
|
*/
|
|
|
|
|
if (sync == &fence->permanent) {
|
|
|
|
|
result = vk_sync_reset(device, sync);
|
|
|
|
|
if (unlikely(result != VK_SUCCESS))
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
unreachable("Invalid fence export handle type");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* From the Vulkan 1.2.194 spec:
|
|
|
|
|
*
|
|
|
|
|
* "Export operations have the same transference as the specified
|
|
|
|
|
* handle type’s import operations. [...] If the fence was using a
|
|
|
|
|
* temporarily imported payload, the fence’s prior permanent payload
|
|
|
|
|
* will be restored.
|
|
|
|
|
*/
|
|
|
|
|
vk_fence_reset_temporary(device, fence);
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif /* !defined(_WIN32) */
|