mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 04:40:09 +01:00
anv: Add a basic implementation of VK_KHX_external_semaphore
This patch adds an implementation based on DRM BOs. We don't actually advertise the extension yet because we want to add a couple more paths first. Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
This commit is contained in:
parent
a8296dbd5a
commit
031f57eba3
4 changed files with 187 additions and 9 deletions
|
|
@ -1402,8 +1402,9 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
|
||||||
VkResult result = VK_SUCCESS;
|
VkResult result = VK_SUCCESS;
|
||||||
for (uint32_t i = 0; i < num_in_semaphores; i++) {
|
for (uint32_t i = 0; i < num_in_semaphores; i++) {
|
||||||
ANV_FROM_HANDLE(anv_semaphore, semaphore, in_semaphores[i]);
|
ANV_FROM_HANDLE(anv_semaphore, semaphore, in_semaphores[i]);
|
||||||
assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE);
|
struct anv_semaphore_impl *impl =
|
||||||
struct anv_semaphore_impl *impl = &semaphore->permanent;
|
semaphore->temporary.type != ANV_SEMAPHORE_TYPE_NONE ?
|
||||||
|
&semaphore->temporary : &semaphore->permanent;
|
||||||
|
|
||||||
switch (impl->type) {
|
switch (impl->type) {
|
||||||
case ANV_SEMAPHORE_TYPE_BO:
|
case ANV_SEMAPHORE_TYPE_BO:
|
||||||
|
|
@ -1419,8 +1420,21 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
|
||||||
|
|
||||||
for (uint32_t i = 0; i < num_out_semaphores; i++) {
|
for (uint32_t i = 0; i < num_out_semaphores; i++) {
|
||||||
ANV_FROM_HANDLE(anv_semaphore, semaphore, out_semaphores[i]);
|
ANV_FROM_HANDLE(anv_semaphore, semaphore, out_semaphores[i]);
|
||||||
assert(semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE);
|
|
||||||
struct anv_semaphore_impl *impl = &semaphore->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_semaphore_impl *impl =
|
||||||
|
semaphore->temporary.type != ANV_SEMAPHORE_TYPE_NONE ?
|
||||||
|
&semaphore->temporary : &semaphore->permanent;
|
||||||
|
|
||||||
switch (impl->type) {
|
switch (impl->type) {
|
||||||
case ANV_SEMAPHORE_TYPE_BO:
|
case ANV_SEMAPHORE_TYPE_BO:
|
||||||
|
|
@ -1440,6 +1454,20 @@ anv_cmd_buffer_execbuf(struct anv_device *device,
|
||||||
|
|
||||||
result = anv_device_execbuf(device, &execbuf.execbuf, execbuf.bos);
|
result = anv_device_execbuf(device, &execbuf.execbuf, execbuf.bos);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < num_in_semaphores; i++) {
|
||||||
|
ANV_FROM_HANDLE(anv_semaphore, semaphore, in_semaphores[i]);
|
||||||
|
/* 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."
|
||||||
|
*
|
||||||
|
* This has to happen after the execbuf in case we close any syncobjs in
|
||||||
|
* the process.
|
||||||
|
*/
|
||||||
|
anv_semaphore_reset_temporary(device, semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
anv_execbuf_finish(&execbuf, &device->alloc);
|
anv_execbuf_finish(&execbuf, &device->alloc);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,9 @@ EXTENSIONS = [
|
||||||
Extension('VK_KHR_external_memory', 1, True),
|
Extension('VK_KHR_external_memory', 1, True),
|
||||||
Extension('VK_KHR_external_memory_capabilities', 1, True),
|
Extension('VK_KHR_external_memory_capabilities', 1, True),
|
||||||
Extension('VK_KHR_external_memory_fd', 1, True),
|
Extension('VK_KHR_external_memory_fd', 1, True),
|
||||||
|
Extension('VK_KHR_external_semaphore', 1, False),
|
||||||
|
Extension('VK_KHR_external_semaphore_capabilities', 1, False),
|
||||||
|
Extension('VK_KHR_external_semaphore_fd', 1, False),
|
||||||
Extension('VK_KHR_get_memory_requirements2', 1, True),
|
Extension('VK_KHR_get_memory_requirements2', 1, True),
|
||||||
Extension('VK_KHR_get_physical_device_properties2', 1, True),
|
Extension('VK_KHR_get_physical_device_properties2', 1, True),
|
||||||
Extension('VK_KHR_get_surface_capabilities2', 1, True),
|
Extension('VK_KHR_get_surface_capabilities2', 1, True),
|
||||||
|
|
|
||||||
|
|
@ -1765,6 +1765,9 @@ struct anv_semaphore {
|
||||||
struct anv_semaphore_impl temporary;
|
struct anv_semaphore_impl temporary;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void anv_semaphore_reset_temporary(struct anv_device *device,
|
||||||
|
struct anv_semaphore *semaphore);
|
||||||
|
|
||||||
struct anv_shader_module {
|
struct anv_shader_module {
|
||||||
unsigned char sha1[20];
|
unsigned char sha1[20];
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
|
|
||||||
|
|
@ -528,11 +528,38 @@ VkResult anv_CreateSemaphore(
|
||||||
if (semaphore == NULL)
|
if (semaphore == NULL)
|
||||||
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||||
|
|
||||||
/* The DRM execbuffer ioctl always execute in-oder so long as you stay
|
const VkExportSemaphoreCreateInfoKHR *export =
|
||||||
* on the same ring. Since we don't expose the blit engine as a DMA
|
vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_CREATE_INFO_KHR);
|
||||||
* queue, a dummy no-op semaphore is a perfectly valid implementation.
|
VkExternalSemaphoreHandleTypeFlagsKHR handleTypes =
|
||||||
*/
|
export ? export->handleTypes : 0;
|
||||||
semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DUMMY;
|
|
||||||
|
if (handleTypes == 0) {
|
||||||
|
/* The DRM execbuffer ioctl always execute in-oder so long as you stay
|
||||||
|
* on the same ring. Since we don't expose the blit engine as a DMA
|
||||||
|
* queue, a dummy no-op semaphore is a perfectly valid implementation.
|
||||||
|
*/
|
||||||
|
semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DUMMY;
|
||||||
|
} else if (handleTypes & VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR) {
|
||||||
|
assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR);
|
||||||
|
|
||||||
|
semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO;
|
||||||
|
VkResult result = anv_bo_cache_alloc(device, &device->bo_cache,
|
||||||
|
4096, &semaphore->permanent.bo);
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
vk_free2(&device->alloc, pAllocator, semaphore);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're going to use this as a fence, we need to *not* have the
|
||||||
|
* EXEC_OBJECT_ASYNC bit set.
|
||||||
|
*/
|
||||||
|
assert(!(semaphore->permanent.bo->flags & EXEC_OBJECT_ASYNC));
|
||||||
|
} else {
|
||||||
|
assert(!"Unknown handle type");
|
||||||
|
vk_free2(&device->alloc, pAllocator, semaphore);
|
||||||
|
return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
|
||||||
|
}
|
||||||
|
|
||||||
semaphore->temporary.type = ANV_SEMAPHORE_TYPE_NONE;
|
semaphore->temporary.type = ANV_SEMAPHORE_TYPE_NONE;
|
||||||
|
|
||||||
*pSemaphore = anv_semaphore_to_handle(semaphore);
|
*pSemaphore = anv_semaphore_to_handle(semaphore);
|
||||||
|
|
@ -558,6 +585,17 @@ anv_semaphore_impl_cleanup(struct anv_device *device,
|
||||||
unreachable("Invalid semaphore type");
|
unreachable("Invalid semaphore type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
anv_semaphore_reset_temporary(struct anv_device *device,
|
||||||
|
struct anv_semaphore *semaphore)
|
||||||
|
{
|
||||||
|
if (semaphore->temporary.type == ANV_SEMAPHORE_TYPE_NONE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
anv_semaphore_impl_cleanup(device, &semaphore->temporary);
|
||||||
|
semaphore->temporary.type = ANV_SEMAPHORE_TYPE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
void anv_DestroySemaphore(
|
void anv_DestroySemaphore(
|
||||||
VkDevice _device,
|
VkDevice _device,
|
||||||
VkSemaphore _semaphore,
|
VkSemaphore _semaphore,
|
||||||
|
|
@ -574,3 +612,109 @@ void anv_DestroySemaphore(
|
||||||
|
|
||||||
vk_free2(&device->alloc, pAllocator, semaphore);
|
vk_free2(&device->alloc, pAllocator, semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void anv_GetPhysicalDeviceExternalSemaphorePropertiesKHR(
|
||||||
|
VkPhysicalDevice physicalDevice,
|
||||||
|
const VkPhysicalDeviceExternalSemaphoreInfoKHR* pExternalSemaphoreInfo,
|
||||||
|
VkExternalSemaphorePropertiesKHR* pExternalSemaphoreProperties)
|
||||||
|
{
|
||||||
|
switch (pExternalSemaphoreInfo->handleType) {
|
||||||
|
case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR:
|
||||||
|
pExternalSemaphoreProperties->exportFromImportedHandleTypes =
|
||||||
|
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
|
||||||
|
pExternalSemaphoreProperties->compatibleHandleTypes =
|
||||||
|
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
|
||||||
|
pExternalSemaphoreProperties->externalSemaphoreFeatures =
|
||||||
|
VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHR |
|
||||||
|
VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHR;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
|
||||||
|
pExternalSemaphoreProperties->compatibleHandleTypes = 0;
|
||||||
|
pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult anv_ImportSemaphoreFdKHR(
|
||||||
|
VkDevice _device,
|
||||||
|
const VkImportSemaphoreFdInfoKHR* pImportSemaphoreFdInfo)
|
||||||
|
{
|
||||||
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||||
|
ANV_FROM_HANDLE(anv_semaphore, semaphore, pImportSemaphoreFdInfo->semaphore);
|
||||||
|
int fd = pImportSemaphoreFdInfo->fd;
|
||||||
|
|
||||||
|
struct anv_semaphore_impl new_impl = {
|
||||||
|
.type = ANV_SEMAPHORE_TYPE_NONE,
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (pImportSemaphoreFdInfo->handleType) {
|
||||||
|
case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: {
|
||||||
|
new_impl.type = ANV_SEMAPHORE_TYPE_BO;
|
||||||
|
|
||||||
|
VkResult result = anv_bo_cache_import(device, &device->bo_cache,
|
||||||
|
fd, 4096, &new_impl.bo);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* If we're going to use this as a fence, we need to *not* have the
|
||||||
|
* EXEC_OBJECT_ASYNC bit set.
|
||||||
|
*/
|
||||||
|
assert(!(new_impl.bo->flags & EXEC_OBJECT_ASYNC));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pImportSemaphoreFdInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR) {
|
||||||
|
anv_semaphore_impl_cleanup(device, &semaphore->temporary);
|
||||||
|
semaphore->temporary = new_impl;
|
||||||
|
} else {
|
||||||
|
anv_semaphore_impl_cleanup(device, &semaphore->permanent);
|
||||||
|
semaphore->permanent = new_impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult anv_GetSemaphoreFdKHR(
|
||||||
|
VkDevice _device,
|
||||||
|
const VkSemaphoreGetFdInfoKHR* pGetFdInfo,
|
||||||
|
int* pFd)
|
||||||
|
{
|
||||||
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||||
|
ANV_FROM_HANDLE(anv_semaphore, semaphore, pGetFdInfo->semaphore);
|
||||||
|
VkResult result;
|
||||||
|
|
||||||
|
assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR);
|
||||||
|
|
||||||
|
struct anv_semaphore_impl *impl =
|
||||||
|
semaphore->temporary.type != ANV_SEMAPHORE_TYPE_NONE ?
|
||||||
|
&semaphore->temporary : &semaphore->permanent;
|
||||||
|
|
||||||
|
switch (impl->type) {
|
||||||
|
case ANV_SEMAPHORE_TYPE_BO:
|
||||||
|
result = anv_bo_cache_export(device, &device->bo_cache, impl->bo, pFd);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return result;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* From the Vulkan 1.0.53 spec:
|
||||||
|
*
|
||||||
|
* "Export operations have the same transference as the specified handle
|
||||||
|
* type’s import operations. [...] If the semaphore was using a
|
||||||
|
* temporarily imported payload, the semaphore’s prior permanent payload
|
||||||
|
* will be restored.
|
||||||
|
*/
|
||||||
|
if (impl == &semaphore->temporary)
|
||||||
|
anv_semaphore_impl_cleanup(device, impl);
|
||||||
|
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue