mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-23 04:40:09 +01:00
anv: Implement VK_KHX_external_semaphore_fd
This implementation allocates a 4k BO for each semaphore that can be exported using OPAQUE_FD and uses the kernel's already-existing synchronization mechanism on BOs. Reviewed-by: Chad Versace <chadversary@chromium.org>
This commit is contained in:
parent
ef2e427d78
commit
4201cc2dd3
5 changed files with 199 additions and 16 deletions
|
|
@ -982,6 +982,7 @@ static VkResult
|
||||||
anv_execbuf_add_bo(struct anv_execbuf *exec,
|
anv_execbuf_add_bo(struct anv_execbuf *exec,
|
||||||
struct anv_bo *bo,
|
struct anv_bo *bo,
|
||||||
struct anv_reloc_list *relocs,
|
struct anv_reloc_list *relocs,
|
||||||
|
uint32_t extra_flags,
|
||||||
const VkAllocationCallbacks *alloc)
|
const VkAllocationCallbacks *alloc)
|
||||||
{
|
{
|
||||||
struct drm_i915_gem_exec_object2 *obj = NULL;
|
struct drm_i915_gem_exec_object2 *obj = NULL;
|
||||||
|
|
@ -1036,7 +1037,7 @@ anv_execbuf_add_bo(struct anv_execbuf *exec,
|
||||||
obj->relocs_ptr = 0;
|
obj->relocs_ptr = 0;
|
||||||
obj->alignment = 0;
|
obj->alignment = 0;
|
||||||
obj->offset = bo->offset;
|
obj->offset = bo->offset;
|
||||||
obj->flags = bo->flags;
|
obj->flags = bo->flags | extra_flags;
|
||||||
obj->rsvd1 = 0;
|
obj->rsvd1 = 0;
|
||||||
obj->rsvd2 = 0;
|
obj->rsvd2 = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -1052,7 +1053,8 @@ anv_execbuf_add_bo(struct anv_execbuf *exec,
|
||||||
for (size_t i = 0; i < relocs->num_relocs; i++) {
|
for (size_t i = 0; i < relocs->num_relocs; i++) {
|
||||||
/* A quick sanity check on relocations */
|
/* A quick sanity check on relocations */
|
||||||
assert(relocs->relocs[i].offset < bo->size);
|
assert(relocs->relocs[i].offset < bo->size);
|
||||||
anv_execbuf_add_bo(exec, relocs->reloc_bos[i], NULL, alloc);
|
anv_execbuf_add_bo(exec, relocs->reloc_bos[i], NULL,
|
||||||
|
extra_flags, alloc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1261,7 +1263,7 @@ setup_execbuf_for_cmd_buffer(struct anv_execbuf *execbuf,
|
||||||
adjust_relocations_from_state_pool(ss_pool, &cmd_buffer->surface_relocs,
|
adjust_relocations_from_state_pool(ss_pool, &cmd_buffer->surface_relocs,
|
||||||
cmd_buffer->last_ss_pool_center);
|
cmd_buffer->last_ss_pool_center);
|
||||||
VkResult result =
|
VkResult result =
|
||||||
anv_execbuf_add_bo(execbuf, &ss_pool->bo, &cmd_buffer->surface_relocs,
|
anv_execbuf_add_bo(execbuf, &ss_pool->bo, &cmd_buffer->surface_relocs, 0,
|
||||||
&cmd_buffer->device->alloc);
|
&cmd_buffer->device->alloc);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1274,7 +1276,7 @@ setup_execbuf_for_cmd_buffer(struct anv_execbuf *execbuf,
|
||||||
adjust_relocations_to_state_pool(ss_pool, &(*bbo)->bo, &(*bbo)->relocs,
|
adjust_relocations_to_state_pool(ss_pool, &(*bbo)->bo, &(*bbo)->relocs,
|
||||||
cmd_buffer->last_ss_pool_center);
|
cmd_buffer->last_ss_pool_center);
|
||||||
|
|
||||||
result = anv_execbuf_add_bo(execbuf, &(*bbo)->bo, &(*bbo)->relocs,
|
result = anv_execbuf_add_bo(execbuf, &(*bbo)->bo, &(*bbo)->relocs, 0,
|
||||||
&cmd_buffer->device->alloc);
|
&cmd_buffer->device->alloc);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -1387,12 +1389,51 @@ setup_execbuf_for_cmd_buffer(struct anv_execbuf *execbuf,
|
||||||
|
|
||||||
VkResult
|
VkResult
|
||||||
anv_cmd_buffer_execbuf(struct anv_device *device,
|
anv_cmd_buffer_execbuf(struct anv_device *device,
|
||||||
struct anv_cmd_buffer *cmd_buffer)
|
struct anv_cmd_buffer *cmd_buffer,
|
||||||
|
const VkSemaphore *in_semaphores,
|
||||||
|
uint32_t num_in_semaphores,
|
||||||
|
const VkSemaphore *out_semaphores,
|
||||||
|
uint32_t num_out_semaphores)
|
||||||
{
|
{
|
||||||
struct anv_execbuf execbuf;
|
struct anv_execbuf execbuf;
|
||||||
anv_execbuf_init(&execbuf);
|
anv_execbuf_init(&execbuf);
|
||||||
|
|
||||||
VkResult result = setup_execbuf_for_cmd_buffer(&execbuf, cmd_buffer);
|
VkResult result = VK_SUCCESS;
|
||||||
|
for (uint32_t i = 0; i < num_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 = &semaphore->permanent;
|
||||||
|
|
||||||
|
switch (impl->type) {
|
||||||
|
case ANV_SEMAPHORE_TYPE_BO:
|
||||||
|
result = anv_execbuf_add_bo(&execbuf, impl->bo, NULL,
|
||||||
|
0, &device->alloc);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return result;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < num_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;
|
||||||
|
|
||||||
|
switch (impl->type) {
|
||||||
|
case ANV_SEMAPHORE_TYPE_BO:
|
||||||
|
result = anv_execbuf_add_bo(&execbuf, impl->bo, NULL,
|
||||||
|
EXEC_OBJECT_WRITE, &device->alloc);
|
||||||
|
if (result != VK_SUCCESS)
|
||||||
|
return result;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = setup_execbuf_for_cmd_buffer(&execbuf, cmd_buffer);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -378,6 +378,10 @@ static const VkExtensionProperties device_extensions[] = {
|
||||||
.extensionName = VK_KHX_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
|
.extensionName = VK_KHX_EXTERNAL_SEMAPHORE_EXTENSION_NAME,
|
||||||
.specVersion = 1,
|
.specVersion = 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.extensionName = VK_KHX_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME,
|
||||||
|
.specVersion = 1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.extensionName = VK_KHX_MULTIVIEW_EXTENSION_NAME,
|
.extensionName = VK_KHX_MULTIVIEW_EXTENSION_NAME,
|
||||||
.specVersion = 1,
|
.specVersion = 1,
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ SUPPORTED_EXTENSIONS = [
|
||||||
'VK_KHX_external_memory_fd',
|
'VK_KHX_external_memory_fd',
|
||||||
'VK_KHX_external_semaphore',
|
'VK_KHX_external_semaphore',
|
||||||
'VK_KHX_external_semaphore_capabilities',
|
'VK_KHX_external_semaphore_capabilities',
|
||||||
|
'VK_KHX_external_semaphore_fd',
|
||||||
'VK_KHX_multiview',
|
'VK_KHX_multiview',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1618,7 +1618,11 @@ void anv_cmd_buffer_add_secondary(struct anv_cmd_buffer *primary,
|
||||||
struct anv_cmd_buffer *secondary);
|
struct anv_cmd_buffer *secondary);
|
||||||
void anv_cmd_buffer_prepare_execbuf(struct anv_cmd_buffer *cmd_buffer);
|
void anv_cmd_buffer_prepare_execbuf(struct anv_cmd_buffer *cmd_buffer);
|
||||||
VkResult anv_cmd_buffer_execbuf(struct anv_device *device,
|
VkResult anv_cmd_buffer_execbuf(struct anv_device *device,
|
||||||
struct anv_cmd_buffer *cmd_buffer);
|
struct anv_cmd_buffer *cmd_buffer,
|
||||||
|
const VkSemaphore *in_semaphores,
|
||||||
|
uint32_t num_in_semaphores,
|
||||||
|
const VkSemaphore *out_semaphores,
|
||||||
|
uint32_t num_out_semaphores);
|
||||||
|
|
||||||
VkResult anv_cmd_buffer_reset(struct anv_cmd_buffer *cmd_buffer);
|
VkResult anv_cmd_buffer_reset(struct anv_cmd_buffer *cmd_buffer);
|
||||||
|
|
||||||
|
|
@ -1708,11 +1712,19 @@ struct anv_event {
|
||||||
|
|
||||||
enum anv_semaphore_type {
|
enum anv_semaphore_type {
|
||||||
ANV_SEMAPHORE_TYPE_NONE = 0,
|
ANV_SEMAPHORE_TYPE_NONE = 0,
|
||||||
ANV_SEMAPHORE_TYPE_DUMMY
|
ANV_SEMAPHORE_TYPE_DUMMY,
|
||||||
|
ANV_SEMAPHORE_TYPE_BO,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct anv_semaphore_impl {
|
struct anv_semaphore_impl {
|
||||||
enum anv_semaphore_type type;
|
enum anv_semaphore_type type;
|
||||||
|
|
||||||
|
/* A BO representing this semaphore when type == ANV_SEMAPHORE_TYPE_BO.
|
||||||
|
* This BO will be added to the object list on any execbuf2 calls for
|
||||||
|
* which this semaphore is used as a wait or signal fence. When used as
|
||||||
|
* a signal fence, the EXEC_OBJECT_WRITE flag will be set.
|
||||||
|
*/
|
||||||
|
struct anv_bo *bo;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct anv_semaphore {
|
struct anv_semaphore {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@
|
||||||
* This file implements VkQueue, VkFence, and VkSemaphore
|
* This file implements VkQueue, VkFence, and VkSemaphore
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/eventfd.h>
|
||||||
|
|
||||||
#include "anv_private.h"
|
#include "anv_private.h"
|
||||||
#include "util/vk_util.h"
|
#include "util/vk_util.h"
|
||||||
|
|
||||||
|
|
@ -161,7 +165,23 @@ VkResult anv_QueueSubmit(
|
||||||
assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
|
||||||
assert(!anv_batch_has_error(&cmd_buffer->batch));
|
assert(!anv_batch_has_error(&cmd_buffer->batch));
|
||||||
|
|
||||||
result = anv_cmd_buffer_execbuf(device, cmd_buffer);
|
const VkSemaphore *in_semaphores = NULL, *out_semaphores = NULL;
|
||||||
|
uint32_t num_in_semaphores = 0, num_out_semaphores = 0;
|
||||||
|
if (j == 0) {
|
||||||
|
/* Only the first batch gets the in semaphores */
|
||||||
|
in_semaphores = pSubmits[i].pWaitSemaphores;
|
||||||
|
num_in_semaphores = pSubmits[i].waitSemaphoreCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == pSubmits[i].commandBufferCount - 1) {
|
||||||
|
/* Only the last batch gets the out semaphores */
|
||||||
|
out_semaphores = pSubmits[i].pSignalSemaphores;
|
||||||
|
num_out_semaphores = pSubmits[i].signalSemaphoreCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = anv_cmd_buffer_execbuf(device, cmd_buffer,
|
||||||
|
in_semaphores, num_in_semaphores,
|
||||||
|
out_semaphores, num_out_semaphores);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
@ -513,14 +533,33 @@ VkResult anv_CreateSemaphore(
|
||||||
VkExternalSemaphoreHandleTypeFlagsKHX handleTypes =
|
VkExternalSemaphoreHandleTypeFlagsKHX handleTypes =
|
||||||
export ? export->handleTypes : 0;
|
export ? export->handleTypes : 0;
|
||||||
|
|
||||||
/* External semaphores are not yet supported */
|
if (handleTypes == 0) {
|
||||||
assert(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_KHX) {
|
||||||
|
assert(handleTypes == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX);
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
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_KHX);
|
||||||
|
}
|
||||||
|
|
||||||
/* The DRM execbuffer ioctl always execute in-oder, even between
|
|
||||||
* different rings. As such, a dummy no-op semaphore is a perfectly
|
|
||||||
* valid implementation.
|
|
||||||
*/
|
|
||||||
semaphore->permanent.type = ANV_SEMAPHORE_TYPE_DUMMY;
|
|
||||||
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);
|
||||||
|
|
@ -528,6 +567,24 @@ VkResult anv_CreateSemaphore(
|
||||||
return VK_SUCCESS;
|
return VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
anv_semaphore_impl_cleanup(struct anv_device *device,
|
||||||
|
struct anv_semaphore_impl *impl)
|
||||||
|
{
|
||||||
|
switch (impl->type) {
|
||||||
|
case ANV_SEMAPHORE_TYPE_NONE:
|
||||||
|
case ANV_SEMAPHORE_TYPE_DUMMY:
|
||||||
|
/* Dummy. Nothing to do */
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ANV_SEMAPHORE_TYPE_BO:
|
||||||
|
anv_bo_cache_release(device, &device->bo_cache, impl->bo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable("Invalid semaphore type");
|
||||||
|
}
|
||||||
|
|
||||||
void anv_DestroySemaphore(
|
void anv_DestroySemaphore(
|
||||||
VkDevice _device,
|
VkDevice _device,
|
||||||
VkSemaphore _semaphore,
|
VkSemaphore _semaphore,
|
||||||
|
|
@ -539,6 +596,9 @@ void anv_DestroySemaphore(
|
||||||
if (semaphore == NULL)
|
if (semaphore == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
anv_semaphore_impl_cleanup(device, &semaphore->temporary);
|
||||||
|
anv_semaphore_impl_cleanup(device, &semaphore->permanent);
|
||||||
|
|
||||||
vk_free2(&device->alloc, pAllocator, semaphore);
|
vk_free2(&device->alloc, pAllocator, semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -548,9 +608,74 @@ void anv_GetPhysicalDeviceExternalSemaphorePropertiesKHX(
|
||||||
VkExternalSemaphorePropertiesKHX* pExternalSemaphoreProperties)
|
VkExternalSemaphorePropertiesKHX* pExternalSemaphoreProperties)
|
||||||
{
|
{
|
||||||
switch (pExternalSemaphoreInfo->handleType) {
|
switch (pExternalSemaphoreInfo->handleType) {
|
||||||
|
case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX:
|
||||||
|
pExternalSemaphoreProperties->exportFromImportedHandleTypes =
|
||||||
|
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX;
|
||||||
|
pExternalSemaphoreProperties->compatibleHandleTypes =
|
||||||
|
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX;
|
||||||
|
pExternalSemaphoreProperties->externalSemaphoreFeatures =
|
||||||
|
VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT_KHX |
|
||||||
|
VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT_KHX;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
|
pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
|
||||||
pExternalSemaphoreProperties->compatibleHandleTypes = 0;
|
pExternalSemaphoreProperties->compatibleHandleTypes = 0;
|
||||||
pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
|
pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkResult anv_ImportSemaphoreFdKHX(
|
||||||
|
VkDevice _device,
|
||||||
|
const VkImportSemaphoreFdInfoKHX* pImportSemaphoreFdInfo)
|
||||||
|
{
|
||||||
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||||
|
ANV_FROM_HANDLE(anv_semaphore, semaphore, pImportSemaphoreFdInfo->semaphore);
|
||||||
|
|
||||||
|
switch (pImportSemaphoreFdInfo->handleType) {
|
||||||
|
case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHX: {
|
||||||
|
struct anv_bo *bo;
|
||||||
|
VkResult result = anv_bo_cache_import(device, &device->bo_cache,
|
||||||
|
pImportSemaphoreFdInfo->fd, 4096,
|
||||||
|
&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.
|
||||||
|
*/
|
||||||
|
bo->flags &= ~EXEC_OBJECT_ASYNC;
|
||||||
|
|
||||||
|
anv_semaphore_impl_cleanup(device, &semaphore->permanent);
|
||||||
|
|
||||||
|
semaphore->permanent.type = ANV_SEMAPHORE_TYPE_BO;
|
||||||
|
semaphore->permanent.bo = bo;
|
||||||
|
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VkResult anv_GetSemaphoreFdKHX(
|
||||||
|
VkDevice _device,
|
||||||
|
VkSemaphore _semaphore,
|
||||||
|
VkExternalSemaphoreHandleTypeFlagBitsKHX handleType,
|
||||||
|
int* pFd)
|
||||||
|
{
|
||||||
|
ANV_FROM_HANDLE(anv_device, device, _device);
|
||||||
|
ANV_FROM_HANDLE(anv_semaphore, semaphore, _semaphore);
|
||||||
|
|
||||||
|
switch (semaphore->permanent.type) {
|
||||||
|
case ANV_SEMAPHORE_TYPE_BO:
|
||||||
|
return anv_bo_cache_export(device, &device->bo_cache,
|
||||||
|
semaphore->permanent.bo, pFd);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX);
|
||||||
|
}
|
||||||
|
|
||||||
|
return VK_SUCCESS;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue