Browse Source

anv: Implement VK_KHR_external_fence

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
tags/17.3-branchpoint
Jason Ekstrand 8 years ago
parent
commit
49c59c88eb
3 changed files with 161 additions and 5 deletions
  1. 17
    2
      src/intel/vulkan/anv_batch_chain.c
  2. 5
    0
      src/intel/vulkan/anv_extensions.py
  3. 139
    3
      src/intel/vulkan/anv_queue.c

+ 17
- 2
src/intel/vulkan/anv_batch_chain.c View File

@@ -1549,8 +1549,20 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
}

if (fence) {
assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
struct anv_fence_impl *impl = &fence->permanent;
/* Under most circumstances, out fences won't be temporary. However,
* the spec does allow it for opaque_fd. From the Vulkan 1.0.53 spec:
*
* "If the import is temporary, the implementation must restore the
* semaphore to its prior permanent state after submitting the next
* semaphore wait operation."
*
* The spec says nothing whatsoever about signal operations on
* temporarily imported semaphores so it appears they are allowed.
* There are also CTS tests that require this to work.
*/
struct anv_fence_impl *impl =
fence->temporary.type != ANV_FENCE_TYPE_NONE ?
&fence->temporary : &fence->permanent;

switch (impl->type) {
case ANV_FENCE_TYPE_BO:
@@ -1617,6 +1629,9 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
}

if (fence && fence->permanent.type == ANV_FENCE_TYPE_BO) {
/* BO fences can't be shared, so they can't be temporary. */
assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);

/* Once the execbuf has returned, we need to set the fence state to
* SUBMITTED. We can't do this before calling execbuf because
* anv_GetFenceStatus does take the global device lock before checking

+ 5
- 0
src/intel/vulkan/anv_extensions.py View File

@@ -47,6 +47,11 @@ class Extension:
EXTENSIONS = [
Extension('VK_KHR_dedicated_allocation', 1, True),
Extension('VK_KHR_descriptor_update_template', 1, True),
Extension('VK_KHR_external_fence', 1,
'device->has_syncobj_wait'),
Extension('VK_KHR_external_fence_capabilities', 1, True),
Extension('VK_KHR_external_fence_fd', 1,
'device->has_syncobj_wait'),
Extension('VK_KHR_external_memory', 1, True),
Extension('VK_KHR_external_memory_capabilities', 1, True),
Extension('VK_KHR_external_memory_fd', 1, True),

+ 139
- 3
src/intel/vulkan/anv_queue.c View File

@@ -349,7 +349,18 @@ VkResult anv_ResetFences(
for (uint32_t i = 0; i < fenceCount; i++) {
ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);

assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
/* From the Vulkan 1.0.53 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.
*/
if (fence->temporary.type != ANV_FENCE_TYPE_NONE) {
anv_fence_impl_cleanup(device, &fence->temporary);
fence->temporary.type = ANV_FENCE_TYPE_NONE;
}

struct anv_fence_impl *impl = &fence->permanent;

switch (impl->type) {
@@ -379,11 +390,14 @@ VkResult anv_GetFenceStatus(
if (unlikely(device->lost))
return VK_ERROR_DEVICE_LOST;

assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
struct anv_fence_impl *impl = &fence->permanent;
struct anv_fence_impl *impl =
fence->temporary.type != ANV_FENCE_TYPE_NONE ?
&fence->temporary : &fence->permanent;

switch (impl->type) {
case ANV_FENCE_TYPE_BO:
/* BO fences don't support import/export */
assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
switch (impl->bo.state) {
case ANV_BO_FENCE_STATE_RESET:
/* If it hasn't even been sent off to the GPU yet, it's not ready */
@@ -665,6 +679,128 @@ VkResult anv_WaitForFences(
}
}

void anv_GetPhysicalDeviceExternalFencePropertiesKHR(
VkPhysicalDevice physicalDevice,
const VkPhysicalDeviceExternalFenceInfoKHR* pExternalFenceInfo,
VkExternalFencePropertiesKHR* pExternalFenceProperties)
{
ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);

switch (pExternalFenceInfo->handleType) {
case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
if (device->has_syncobj_wait) {
pExternalFenceProperties->exportFromImportedHandleTypes =
VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
pExternalFenceProperties->compatibleHandleTypes =
VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
pExternalFenceProperties->externalFenceFeatures =
VK_EXTERNAL_FENCE_FEATURE_EXPORTABLE_BIT_KHR |
VK_EXTERNAL_FENCE_FEATURE_IMPORTABLE_BIT_KHR;
return;
}
break;

default:
break;
}

pExternalFenceProperties->exportFromImportedHandleTypes = 0;
pExternalFenceProperties->compatibleHandleTypes = 0;
pExternalFenceProperties->externalFenceFeatures = 0;
}

VkResult anv_ImportFenceFdKHR(
VkDevice _device,
const VkImportFenceFdInfoKHR* pImportFenceFdInfo)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_fence, fence, pImportFenceFdInfo->fence);
int fd = pImportFenceFdInfo->fd;

assert(pImportFenceFdInfo->sType ==
VK_STRUCTURE_TYPE_IMPORT_FENCE_FD_INFO_KHR);

struct anv_fence_impl new_impl = {
.type = ANV_FENCE_TYPE_NONE,
};

switch (pImportFenceFdInfo->handleType) {
case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
new_impl.type = ANV_FENCE_TYPE_SYNCOBJ;

new_impl.syncobj = anv_gem_syncobj_fd_to_handle(device, fd);
if (!new_impl.syncobj)
return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);

/* From the Vulkan 1.0.53 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.
*/
close(fd);
break;

default:
return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
}

if (pImportFenceFdInfo->flags & VK_FENCE_IMPORT_TEMPORARY_BIT_KHR) {
anv_fence_impl_cleanup(device, &fence->temporary);
fence->temporary = new_impl;
} else {
anv_fence_impl_cleanup(device, &fence->permanent);
fence->permanent = new_impl;
}

return VK_SUCCESS;
}

VkResult anv_GetFenceFdKHR(
VkDevice _device,
const VkFenceGetFdInfoKHR* pGetFdInfo,
int* pFd)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_fence, fence, pGetFdInfo->fence);

assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR);

struct anv_fence_impl *impl =
fence->temporary.type != ANV_FENCE_TYPE_NONE ?
&fence->temporary : &fence->permanent;

assert(impl->type == ANV_FENCE_TYPE_SYNCOBJ);
switch (pGetFdInfo->handleType) {
case VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: {
int fd = anv_gem_syncobj_handle_to_fd(device, impl->syncobj);
if (fd < 0)
return vk_error(VK_ERROR_TOO_MANY_OBJECTS);

*pFd = fd;
break;
}

default:
unreachable("Invalid fence export handle type");
}

/* From the Vulkan 1.0.53 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.
*/
if (impl == &fence->temporary)
anv_fence_impl_cleanup(device, impl);

return VK_SUCCESS;
}

// Queue semaphore functions

VkResult anv_CreateSemaphore(

Loading…
Cancel
Save