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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5999>
This commit is contained in:
parent
7dfeae1a45
commit
4b9c0cd821
|
@ -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,
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include <sys/mman.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue