From: Kristian H. Kristensen Date: Mon, 20 Jul 2020 19:47:57 +0000 (-0700) Subject: turnip: Move remaining drm code to tu_drm.c X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=commitdiff_plain;h=4b9c0cd821ae5ca1221c71c5b32de94cc8efb070 turnip: Move remaining drm code to tu_drm.c This moves the semaphore implementation and tu_QueueSubmit to tu_drm.c, such that that's the only file including xf86drm.h and msm_drm.h. This way, the entire kernel interface is contained in tu_drm.c Part-of: --- diff --git a/src/freedreno/vulkan/tu_device.c b/src/freedreno/vulkan/tu_device.c index b4ae1268d7e..ddc4db143d5 100644 --- a/src/freedreno/vulkan/tu_device.c +++ b/src/freedreno/vulkan/tu_device.c @@ -47,10 +47,6 @@ /* for fd_get_driver/device_uuid() */ #include "freedreno/common/freedreno_uuid.h" -static void -tu_semaphore_remove_temp(struct tu_device *device, - struct tu_semaphore *sem); - static int tu_device_get_cache_uuid(uint16_t family, void *uuid) { @@ -1328,183 +1324,6 @@ tu_GetDeviceQueue(VkDevice _device, tu_GetDeviceQueue2(_device, &info, pQueue); } -static VkResult -tu_get_semaphore_syncobjs(const VkSemaphore *sems, - uint32_t sem_count, - bool wait, - struct drm_msm_gem_submit_syncobj **out, - uint32_t *out_count) -{ - uint32_t syncobj_count = 0; - struct drm_msm_gem_submit_syncobj *syncobjs; - - for (uint32_t i = 0; i < sem_count; ++i) { - TU_FROM_HANDLE(tu_semaphore, sem, sems[i]); - - struct tu_semaphore_part *part = - sem->temporary.kind != TU_SEMAPHORE_NONE ? - &sem->temporary : &sem->permanent; - - if (part->kind == TU_SEMAPHORE_SYNCOBJ) - ++syncobj_count; - } - - *out = NULL; - *out_count = syncobj_count; - if (!syncobj_count) - return VK_SUCCESS; - - *out = syncobjs = calloc(syncobj_count, sizeof (*syncobjs)); - if (!syncobjs) - return VK_ERROR_OUT_OF_HOST_MEMORY; - - for (uint32_t i = 0, j = 0; i < sem_count; ++i) { - TU_FROM_HANDLE(tu_semaphore, sem, sems[i]); - - struct tu_semaphore_part *part = - sem->temporary.kind != TU_SEMAPHORE_NONE ? - &sem->temporary : &sem->permanent; - - if (part->kind == TU_SEMAPHORE_SYNCOBJ) { - syncobjs[j].handle = part->syncobj; - syncobjs[j].flags = wait ? MSM_SUBMIT_SYNCOBJ_RESET : 0; - ++j; - } - } - - return VK_SUCCESS; -} - - -static void -tu_semaphores_remove_temp(struct tu_device *device, - const VkSemaphore *sems, - uint32_t sem_count) -{ - for (uint32_t i = 0; i < sem_count; ++i) { - TU_FROM_HANDLE(tu_semaphore, sem, sems[i]); - tu_semaphore_remove_temp(device, sem); - } -} - -VkResult -tu_QueueSubmit(VkQueue _queue, - uint32_t submitCount, - const VkSubmitInfo *pSubmits, - VkFence _fence) -{ - TU_FROM_HANDLE(tu_queue, queue, _queue); - VkResult result; - - for (uint32_t i = 0; i < submitCount; ++i) { - const VkSubmitInfo *submit = pSubmits + i; - const bool last_submit = (i == submitCount - 1); - struct drm_msm_gem_submit_syncobj *in_syncobjs = NULL, *out_syncobjs = NULL; - uint32_t nr_in_syncobjs, nr_out_syncobjs; - struct tu_bo_list bo_list; - tu_bo_list_init(&bo_list); - - result = tu_get_semaphore_syncobjs(pSubmits[i].pWaitSemaphores, - pSubmits[i].waitSemaphoreCount, - false, &in_syncobjs, &nr_in_syncobjs); - if (result != VK_SUCCESS) { - return tu_device_set_lost(queue->device, - "failed to allocate space for semaphore submission\n"); - } - - result = tu_get_semaphore_syncobjs(pSubmits[i].pSignalSemaphores, - pSubmits[i].signalSemaphoreCount, - false, &out_syncobjs, &nr_out_syncobjs); - if (result != VK_SUCCESS) { - free(in_syncobjs); - return tu_device_set_lost(queue->device, - "failed to allocate space for semaphore submission\n"); - } - - uint32_t entry_count = 0; - for (uint32_t j = 0; j < submit->commandBufferCount; ++j) { - TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]); - entry_count += cmdbuf->cs.entry_count; - } - - struct drm_msm_gem_submit_cmd cmds[entry_count]; - uint32_t entry_idx = 0; - for (uint32_t j = 0; j < submit->commandBufferCount; ++j) { - TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]); - struct tu_cs *cs = &cmdbuf->cs; - for (unsigned i = 0; i < cs->entry_count; ++i, ++entry_idx) { - cmds[entry_idx].type = MSM_SUBMIT_CMD_BUF; - cmds[entry_idx].submit_idx = - tu_bo_list_add(&bo_list, cs->entries[i].bo, - MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_DUMP); - cmds[entry_idx].submit_offset = cs->entries[i].offset; - cmds[entry_idx].size = cs->entries[i].size; - cmds[entry_idx].pad = 0; - cmds[entry_idx].nr_relocs = 0; - cmds[entry_idx].relocs = 0; - } - - tu_bo_list_merge(&bo_list, &cmdbuf->bo_list); - } - - uint32_t flags = MSM_PIPE_3D0; - if (nr_in_syncobjs) { - flags |= MSM_SUBMIT_SYNCOBJ_IN; - } - if (nr_out_syncobjs) { - flags |= MSM_SUBMIT_SYNCOBJ_OUT; - } - - if (last_submit) { - flags |= MSM_SUBMIT_FENCE_FD_OUT; - } - - struct drm_msm_gem_submit req = { - .flags = flags, - .queueid = queue->msm_queue_id, - .bos = (uint64_t)(uintptr_t) bo_list.bo_infos, - .nr_bos = bo_list.count, - .cmds = (uint64_t)(uintptr_t)cmds, - .nr_cmds = entry_count, - .in_syncobjs = (uint64_t)(uintptr_t)in_syncobjs, - .out_syncobjs = (uint64_t)(uintptr_t)out_syncobjs, - .nr_in_syncobjs = nr_in_syncobjs, - .nr_out_syncobjs = nr_out_syncobjs, - .syncobj_stride = sizeof(struct drm_msm_gem_submit_syncobj), - }; - - int ret = drmCommandWriteRead(queue->device->physical_device->local_fd, - DRM_MSM_GEM_SUBMIT, - &req, sizeof(req)); - if (ret) { - free(in_syncobjs); - free(out_syncobjs); - return tu_device_set_lost(queue->device, "submit failed: %s\n", - strerror(errno)); - } - - tu_bo_list_destroy(&bo_list); - free(in_syncobjs); - free(out_syncobjs); - - tu_semaphores_remove_temp(queue->device, pSubmits[i].pWaitSemaphores, - pSubmits[i].waitSemaphoreCount); - if (last_submit) { - /* no need to merge fences as queue execution is serialized */ - tu_fence_update_fd(&queue->submit_fence, req.fence_fd); - } else if (last_submit) { - close(req.fence_fd); - } - } - - if (_fence != VK_NULL_HANDLE) { - TU_FROM_HANDLE(tu_fence, fence, _fence); - tu_fence_copy(fence, &queue->submit_fence); - } - - return VK_SUCCESS; -} - VkResult tu_QueueWaitIdle(VkQueue _queue) { @@ -1911,80 +1730,6 @@ tu_QueueBindSparse(VkQueue _queue, return VK_SUCCESS; } -// Queue semaphore functions - - -static void -tu_semaphore_part_destroy(struct tu_device *device, - struct tu_semaphore_part *part) -{ - switch(part->kind) { - case TU_SEMAPHORE_NONE: - break; - case TU_SEMAPHORE_SYNCOBJ: - drmSyncobjDestroy(device->physical_device->local_fd, part->syncobj); - break; - } - part->kind = TU_SEMAPHORE_NONE; -} - -static void -tu_semaphore_remove_temp(struct tu_device *device, - struct tu_semaphore *sem) -{ - if (sem->temporary.kind != TU_SEMAPHORE_NONE) { - tu_semaphore_part_destroy(device, &sem->temporary); - } -} - -VkResult -tu_CreateSemaphore(VkDevice _device, - const VkSemaphoreCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkSemaphore *pSemaphore) -{ - TU_FROM_HANDLE(tu_device, device, _device); - - struct tu_semaphore *sem = - vk_object_alloc(&device->vk, pAllocator, sizeof(*sem), - VK_OBJECT_TYPE_SEMAPHORE); - if (!sem) - return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); - - const VkExportSemaphoreCreateInfo *export = - vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_CREATE_INFO); - VkExternalSemaphoreHandleTypeFlags handleTypes = - export ? export->handleTypes : 0; - - sem->permanent.kind = TU_SEMAPHORE_NONE; - sem->temporary.kind = TU_SEMAPHORE_NONE; - - if (handleTypes) { - if (drmSyncobjCreate(device->physical_device->local_fd, 0, &sem->permanent.syncobj) < 0) { - vk_free2(&device->vk.alloc, pAllocator, sem); - return VK_ERROR_OUT_OF_HOST_MEMORY; - } - sem->permanent.kind = TU_SEMAPHORE_SYNCOBJ; - } - *pSemaphore = tu_semaphore_to_handle(sem); - return VK_SUCCESS; -} - -void -tu_DestroySemaphore(VkDevice _device, - VkSemaphore _semaphore, - const VkAllocationCallbacks *pAllocator) -{ - TU_FROM_HANDLE(tu_device, device, _device); - TU_FROM_HANDLE(tu_semaphore, sem, _semaphore); - if (!_semaphore) - return; - - tu_semaphore_part_destroy(device, &sem->permanent); - tu_semaphore_part_destroy(device, &sem->temporary); - - vk_object_free(&device->vk, pAllocator, sem); -} VkResult tu_CreateEvent(VkDevice _device, @@ -2344,134 +2089,6 @@ tu_GetFenceFdKHR(VkDevice _device, return VK_SUCCESS; } -VkResult -tu_ImportSemaphoreFdKHR(VkDevice _device, - const VkImportSemaphoreFdInfoKHR *pImportSemaphoreFdInfo) -{ - TU_FROM_HANDLE(tu_device, device, _device); - TU_FROM_HANDLE(tu_semaphore, sem, pImportSemaphoreFdInfo->semaphore); - int ret; - struct tu_semaphore_part *dst = NULL; - - if (pImportSemaphoreFdInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT) { - dst = &sem->temporary; - } else { - dst = &sem->permanent; - } - - uint32_t syncobj = dst->kind == TU_SEMAPHORE_SYNCOBJ ? dst->syncobj : 0; - - switch(pImportSemaphoreFdInfo->handleType) { - case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: { - uint32_t old_syncobj = syncobj; - ret = drmSyncobjFDToHandle(device->physical_device->local_fd, pImportSemaphoreFdInfo->fd, &syncobj); - if (ret == 0) { - close(pImportSemaphoreFdInfo->fd); - if (old_syncobj) - drmSyncobjDestroy(device->physical_device->local_fd, old_syncobj); - } - break; - } - case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: { - if (!syncobj) { - ret = drmSyncobjCreate(device->physical_device->local_fd, 0, &syncobj); - if (ret) - break; - } - if (pImportSemaphoreFdInfo->fd == -1) { - ret = drmSyncobjSignal(device->physical_device->local_fd, &syncobj, 1); - } else { - ret = drmSyncobjImportSyncFile(device->physical_device->local_fd, syncobj, pImportSemaphoreFdInfo->fd); - } - if (!ret) - close(pImportSemaphoreFdInfo->fd); - break; - } - default: - unreachable("Unhandled semaphore handle type"); - } - - if (ret) { - return VK_ERROR_INVALID_EXTERNAL_HANDLE; - } - dst->syncobj = syncobj; - dst->kind = TU_SEMAPHORE_SYNCOBJ; - - return VK_SUCCESS; -} - -VkResult -tu_GetSemaphoreFdKHR(VkDevice _device, - const VkSemaphoreGetFdInfoKHR *pGetFdInfo, - int *pFd) -{ - TU_FROM_HANDLE(tu_device, device, _device); - TU_FROM_HANDLE(tu_semaphore, sem, pGetFdInfo->semaphore); - int ret; - uint32_t syncobj_handle; - - if (sem->temporary.kind != TU_SEMAPHORE_NONE) { - assert(sem->temporary.kind == TU_SEMAPHORE_SYNCOBJ); - syncobj_handle = sem->temporary.syncobj; - } else { - assert(sem->permanent.kind == TU_SEMAPHORE_SYNCOBJ); - syncobj_handle = sem->permanent.syncobj; - } - - switch(pGetFdInfo->handleType) { - case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: - ret = drmSyncobjHandleToFD(device->physical_device->local_fd, syncobj_handle, pFd); - break; - case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: - ret = drmSyncobjExportSyncFile(device->physical_device->local_fd, syncobj_handle, pFd); - if (!ret) { - if (sem->temporary.kind != TU_SEMAPHORE_NONE) { - tu_semaphore_part_destroy(device, &sem->temporary); - } else { - drmSyncobjReset(device->physical_device->local_fd, &syncobj_handle, 1); - } - } - break; - default: - unreachable("Unhandled semaphore handle type"); - } - - if (ret) - return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); - return VK_SUCCESS; -} - - -static bool tu_has_syncobj(struct tu_physical_device *pdev) -{ - uint64_t value; - if (drmGetCap(pdev->local_fd, DRM_CAP_SYNCOBJ, &value)) - return false; - return value && pdev->msm_major_version == 1 && pdev->msm_minor_version >= 6; -} - -void -tu_GetPhysicalDeviceExternalSemaphoreProperties( - VkPhysicalDevice physicalDevice, - const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, - VkExternalSemaphoreProperties *pExternalSemaphoreProperties) -{ - TU_FROM_HANDLE(tu_physical_device, pdev, physicalDevice); - - if (tu_has_syncobj(pdev) && - (pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT || - pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) { - pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; - pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; - pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | - VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; - } else { - pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; - pExternalSemaphoreProperties->compatibleHandleTypes = 0; - pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; - } -} - void tu_GetPhysicalDeviceExternalFenceProperties( VkPhysicalDevice physicalDevice, diff --git a/src/freedreno/vulkan/tu_drm.c b/src/freedreno/vulkan/tu_drm.c index 7a5d410c7ca..339a72ad6d5 100644 --- a/src/freedreno/vulkan/tu_drm.c +++ b/src/freedreno/vulkan/tu_drm.c @@ -31,6 +31,8 @@ #include #include +#include "vk_util.h" + #include "drm-uapi/msm_drm.h" static int @@ -386,3 +388,379 @@ tu_enumerate_devices(struct tu_instance *instance) return result; } +// Queue semaphore functions + +static void +tu_semaphore_part_destroy(struct tu_device *device, + struct tu_semaphore_part *part) +{ + switch(part->kind) { + case TU_SEMAPHORE_NONE: + break; + case TU_SEMAPHORE_SYNCOBJ: + drmSyncobjDestroy(device->physical_device->local_fd, part->syncobj); + break; + } + part->kind = TU_SEMAPHORE_NONE; +} + +static void +tu_semaphore_remove_temp(struct tu_device *device, + struct tu_semaphore *sem) +{ + if (sem->temporary.kind != TU_SEMAPHORE_NONE) { + tu_semaphore_part_destroy(device, &sem->temporary); + } +} + +static VkResult +tu_get_semaphore_syncobjs(const VkSemaphore *sems, + uint32_t sem_count, + bool wait, + struct drm_msm_gem_submit_syncobj **out, + uint32_t *out_count) +{ + uint32_t syncobj_count = 0; + struct drm_msm_gem_submit_syncobj *syncobjs; + + for (uint32_t i = 0; i < sem_count; ++i) { + TU_FROM_HANDLE(tu_semaphore, sem, sems[i]); + + struct tu_semaphore_part *part = + sem->temporary.kind != TU_SEMAPHORE_NONE ? + &sem->temporary : &sem->permanent; + + if (part->kind == TU_SEMAPHORE_SYNCOBJ) + ++syncobj_count; + } + + *out = NULL; + *out_count = syncobj_count; + if (!syncobj_count) + return VK_SUCCESS; + + *out = syncobjs = calloc(syncobj_count, sizeof (*syncobjs)); + if (!syncobjs) + return VK_ERROR_OUT_OF_HOST_MEMORY; + + for (uint32_t i = 0, j = 0; i < sem_count; ++i) { + TU_FROM_HANDLE(tu_semaphore, sem, sems[i]); + + struct tu_semaphore_part *part = + sem->temporary.kind != TU_SEMAPHORE_NONE ? + &sem->temporary : &sem->permanent; + + if (part->kind == TU_SEMAPHORE_SYNCOBJ) { + syncobjs[j].handle = part->syncobj; + syncobjs[j].flags = wait ? MSM_SUBMIT_SYNCOBJ_RESET : 0; + ++j; + } + } + + return VK_SUCCESS; +} + +static void +tu_semaphores_remove_temp(struct tu_device *device, + const VkSemaphore *sems, + uint32_t sem_count) +{ + for (uint32_t i = 0; i < sem_count; ++i) { + TU_FROM_HANDLE(tu_semaphore, sem, sems[i]); + tu_semaphore_remove_temp(device, sem); + } +} + +VkResult +tu_CreateSemaphore(VkDevice _device, + const VkSemaphoreCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkSemaphore *pSemaphore) +{ + TU_FROM_HANDLE(tu_device, device, _device); + + struct tu_semaphore *sem = + vk_object_alloc(&device->vk, pAllocator, sizeof(*sem), + VK_OBJECT_TYPE_SEMAPHORE); + if (!sem) + return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + + const VkExportSemaphoreCreateInfo *export = + vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_CREATE_INFO); + VkExternalSemaphoreHandleTypeFlags handleTypes = + export ? export->handleTypes : 0; + + sem->permanent.kind = TU_SEMAPHORE_NONE; + sem->temporary.kind = TU_SEMAPHORE_NONE; + + if (handleTypes) { + if (drmSyncobjCreate(device->physical_device->local_fd, 0, &sem->permanent.syncobj) < 0) { + vk_free2(&device->vk.alloc, pAllocator, sem); + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + sem->permanent.kind = TU_SEMAPHORE_SYNCOBJ; + } + *pSemaphore = tu_semaphore_to_handle(sem); + return VK_SUCCESS; +} + +void +tu_DestroySemaphore(VkDevice _device, + VkSemaphore _semaphore, + const VkAllocationCallbacks *pAllocator) +{ + TU_FROM_HANDLE(tu_device, device, _device); + TU_FROM_HANDLE(tu_semaphore, sem, _semaphore); + if (!_semaphore) + return; + + tu_semaphore_part_destroy(device, &sem->permanent); + tu_semaphore_part_destroy(device, &sem->temporary); + + vk_object_free(&device->vk, pAllocator, sem); +} + +VkResult +tu_ImportSemaphoreFdKHR(VkDevice _device, + const VkImportSemaphoreFdInfoKHR *pImportSemaphoreFdInfo) +{ + TU_FROM_HANDLE(tu_device, device, _device); + TU_FROM_HANDLE(tu_semaphore, sem, pImportSemaphoreFdInfo->semaphore); + int ret; + struct tu_semaphore_part *dst = NULL; + + if (pImportSemaphoreFdInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT) { + dst = &sem->temporary; + } else { + dst = &sem->permanent; + } + + uint32_t syncobj = dst->kind == TU_SEMAPHORE_SYNCOBJ ? dst->syncobj : 0; + + switch(pImportSemaphoreFdInfo->handleType) { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: { + uint32_t old_syncobj = syncobj; + ret = drmSyncobjFDToHandle(device->physical_device->local_fd, pImportSemaphoreFdInfo->fd, &syncobj); + if (ret == 0) { + close(pImportSemaphoreFdInfo->fd); + if (old_syncobj) + drmSyncobjDestroy(device->physical_device->local_fd, old_syncobj); + } + break; + } + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: { + if (!syncobj) { + ret = drmSyncobjCreate(device->physical_device->local_fd, 0, &syncobj); + if (ret) + break; + } + if (pImportSemaphoreFdInfo->fd == -1) { + ret = drmSyncobjSignal(device->physical_device->local_fd, &syncobj, 1); + } else { + ret = drmSyncobjImportSyncFile(device->physical_device->local_fd, syncobj, pImportSemaphoreFdInfo->fd); + } + if (!ret) + close(pImportSemaphoreFdInfo->fd); + break; + } + default: + unreachable("Unhandled semaphore handle type"); + } + + if (ret) { + return VK_ERROR_INVALID_EXTERNAL_HANDLE; + } + dst->syncobj = syncobj; + dst->kind = TU_SEMAPHORE_SYNCOBJ; + + return VK_SUCCESS; +} + +VkResult +tu_GetSemaphoreFdKHR(VkDevice _device, + const VkSemaphoreGetFdInfoKHR *pGetFdInfo, + int *pFd) +{ + TU_FROM_HANDLE(tu_device, device, _device); + TU_FROM_HANDLE(tu_semaphore, sem, pGetFdInfo->semaphore); + int ret; + uint32_t syncobj_handle; + + if (sem->temporary.kind != TU_SEMAPHORE_NONE) { + assert(sem->temporary.kind == TU_SEMAPHORE_SYNCOBJ); + syncobj_handle = sem->temporary.syncobj; + } else { + assert(sem->permanent.kind == TU_SEMAPHORE_SYNCOBJ); + syncobj_handle = sem->permanent.syncobj; + } + + switch(pGetFdInfo->handleType) { + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: + ret = drmSyncobjHandleToFD(device->physical_device->local_fd, syncobj_handle, pFd); + break; + case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: + ret = drmSyncobjExportSyncFile(device->physical_device->local_fd, syncobj_handle, pFd); + if (!ret) { + if (sem->temporary.kind != TU_SEMAPHORE_NONE) { + tu_semaphore_part_destroy(device, &sem->temporary); + } else { + drmSyncobjReset(device->physical_device->local_fd, &syncobj_handle, 1); + } + } + break; + default: + unreachable("Unhandled semaphore handle type"); + } + + if (ret) + return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); + return VK_SUCCESS; +} + +static bool tu_has_syncobj(struct tu_physical_device *pdev) +{ + uint64_t value; + if (drmGetCap(pdev->local_fd, DRM_CAP_SYNCOBJ, &value)) + return false; + return value && pdev->msm_major_version == 1 && pdev->msm_minor_version >= 6; +} + +void +tu_GetPhysicalDeviceExternalSemaphoreProperties( + VkPhysicalDevice physicalDevice, + const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, + VkExternalSemaphoreProperties *pExternalSemaphoreProperties) +{ + TU_FROM_HANDLE(tu_physical_device, pdev, physicalDevice); + + if (tu_has_syncobj(pdev) && + (pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT || + pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) { + pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; + pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT | + VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT; + } else { + pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; + pExternalSemaphoreProperties->compatibleHandleTypes = 0; + pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; + } +} + +VkResult +tu_QueueSubmit(VkQueue _queue, + uint32_t submitCount, + const VkSubmitInfo *pSubmits, + VkFence _fence) +{ + TU_FROM_HANDLE(tu_queue, queue, _queue); + VkResult result; + + for (uint32_t i = 0; i < submitCount; ++i) { + const VkSubmitInfo *submit = pSubmits + i; + const bool last_submit = (i == submitCount - 1); + struct drm_msm_gem_submit_syncobj *in_syncobjs = NULL, *out_syncobjs = NULL; + uint32_t nr_in_syncobjs, nr_out_syncobjs; + struct tu_bo_list bo_list; + tu_bo_list_init(&bo_list); + + result = tu_get_semaphore_syncobjs(pSubmits[i].pWaitSemaphores, + pSubmits[i].waitSemaphoreCount, + false, &in_syncobjs, &nr_in_syncobjs); + if (result != VK_SUCCESS) { + return tu_device_set_lost(queue->device, + "failed to allocate space for semaphore submission\n"); + } + + result = tu_get_semaphore_syncobjs(pSubmits[i].pSignalSemaphores, + pSubmits[i].signalSemaphoreCount, + false, &out_syncobjs, &nr_out_syncobjs); + if (result != VK_SUCCESS) { + free(in_syncobjs); + return tu_device_set_lost(queue->device, + "failed to allocate space for semaphore submission\n"); + } + + uint32_t entry_count = 0; + for (uint32_t j = 0; j < submit->commandBufferCount; ++j) { + TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]); + entry_count += cmdbuf->cs.entry_count; + } + + struct drm_msm_gem_submit_cmd cmds[entry_count]; + uint32_t entry_idx = 0; + for (uint32_t j = 0; j < submit->commandBufferCount; ++j) { + TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]); + struct tu_cs *cs = &cmdbuf->cs; + for (unsigned i = 0; i < cs->entry_count; ++i, ++entry_idx) { + cmds[entry_idx].type = MSM_SUBMIT_CMD_BUF; + cmds[entry_idx].submit_idx = + tu_bo_list_add(&bo_list, cs->entries[i].bo, + MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_DUMP); + cmds[entry_idx].submit_offset = cs->entries[i].offset; + cmds[entry_idx].size = cs->entries[i].size; + cmds[entry_idx].pad = 0; + cmds[entry_idx].nr_relocs = 0; + cmds[entry_idx].relocs = 0; + } + + tu_bo_list_merge(&bo_list, &cmdbuf->bo_list); + } + + uint32_t flags = MSM_PIPE_3D0; + if (nr_in_syncobjs) { + flags |= MSM_SUBMIT_SYNCOBJ_IN; + } + if (nr_out_syncobjs) { + flags |= MSM_SUBMIT_SYNCOBJ_OUT; + } + + if (last_submit) { + flags |= MSM_SUBMIT_FENCE_FD_OUT; + } + + struct drm_msm_gem_submit req = { + .flags = flags, + .queueid = queue->msm_queue_id, + .bos = (uint64_t)(uintptr_t) bo_list.bo_infos, + .nr_bos = bo_list.count, + .cmds = (uint64_t)(uintptr_t)cmds, + .nr_cmds = entry_count, + .in_syncobjs = (uint64_t)(uintptr_t)in_syncobjs, + .out_syncobjs = (uint64_t)(uintptr_t)out_syncobjs, + .nr_in_syncobjs = nr_in_syncobjs, + .nr_out_syncobjs = nr_out_syncobjs, + .syncobj_stride = sizeof(struct drm_msm_gem_submit_syncobj), + }; + + int ret = drmCommandWriteRead(queue->device->physical_device->local_fd, + DRM_MSM_GEM_SUBMIT, + &req, sizeof(req)); + if (ret) { + free(in_syncobjs); + free(out_syncobjs); + return tu_device_set_lost(queue->device, "submit failed: %s\n", + strerror(errno)); + } + + tu_bo_list_destroy(&bo_list); + free(in_syncobjs); + free(out_syncobjs); + + tu_semaphores_remove_temp(queue->device, pSubmits[i].pWaitSemaphores, + pSubmits[i].waitSemaphoreCount); + if (last_submit) { + /* no need to merge fences as queue execution is serialized */ + tu_fence_update_fd(&queue->submit_fence, req.fence_fd); + } else if (last_submit) { + close(req.fence_fd); + } + } + + if (_fence != VK_NULL_HANDLE) { + TU_FROM_HANDLE(tu_fence, fence, _fence); + tu_fence_copy(fence, &queue->submit_fence); + } + + return VK_SUCCESS; +}