From 0f048c57828b3891d4af0b1adbc662edf53fb558 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 8 Mar 2022 22:13:20 -0600 Subject: [PATCH] panvk: Convert to the common sync/submit framework Acked-by: Boris Brezillon Part-of: --- src/panfrost/vulkan/meson.build | 1 - src/panfrost/vulkan/panvk_device.c | 22 ++ src/panfrost/vulkan/panvk_private.h | 33 +- src/panfrost/vulkan/panvk_sync.c | 420 -------------------------- src/panfrost/vulkan/panvk_vX_device.c | 166 +++++----- src/panfrost/vulkan/panvk_vX_device.h | 34 +++ src/panfrost/vulkan/panvk_wsi.c | 27 +- 7 files changed, 169 insertions(+), 534 deletions(-) delete mode 100644 src/panfrost/vulkan/panvk_sync.c create mode 100644 src/panfrost/vulkan/panvk_vX_device.h diff --git a/src/panfrost/vulkan/meson.build b/src/panfrost/vulkan/meson.build index 2471fd4641a..026a4d55e76 100644 --- a/src/panfrost/vulkan/meson.build +++ b/src/panfrost/vulkan/meson.build @@ -47,7 +47,6 @@ libpanvk_files = files( 'panvk_private.h', 'panvk_query.c', 'panvk_shader.c', - 'panvk_sync.c', 'panvk_util.c', 'panvk_wsi.c', ) diff --git a/src/panfrost/vulkan/panvk_device.c b/src/panfrost/vulkan/panvk_device.c index c790fc87910..c49f9c9b098 100644 --- a/src/panfrost/vulkan/panvk_device.c +++ b/src/panfrost/vulkan/panvk_device.c @@ -47,6 +47,7 @@ #include "util/disk_cache.h" #include "util/strtod.h" #include "vk_format.h" +#include "vk_drm_syncobj.h" #include "vk_util.h" #ifdef VK_USE_PLATFORM_WAYLAND_KHR @@ -340,6 +341,17 @@ panvk_physical_device_init(struct panvk_physical_device *device, panvk_get_driver_uuid(&device->device_uuid); panvk_get_device_uuid(&device->device_uuid); + device->drm_syncobj_type = vk_drm_syncobj_get_type(device->pdev.fd); + /* We don't support timelines in the uAPI yet and we don't want it getting + * suddenly turned on by vk_drm_syncobj_get_type() without us adding panvk + * code for it first. + */ + device->drm_syncobj_type.features &= ~VK_SYNC_FEATURE_TIMELINE; + + device->sync_types[0] = &device->drm_syncobj_type; + device->sync_types[1] = NULL; + device->vk.supported_sync_types = device->sync_types; + result = panvk_wsi_init(device); if (result != VK_SUCCESS) { vk_error(instance, result); @@ -943,6 +955,13 @@ panvk_queue_init(struct panvk_device *device, return VK_ERROR_OUT_OF_HOST_MEMORY; } + switch (pdev->arch) { + case 5: queue->vk.driver_submit = panvk_v5_queue_submit; break; + case 6: queue->vk.driver_submit = panvk_v6_queue_submit; break; + case 7: queue->vk.driver_submit = panvk_v7_queue_submit; break; + default: unreachable("Invalid arch"); + } + queue->sync = create.handle; return VK_SUCCESS; } @@ -1004,6 +1023,9 @@ panvk_CreateDevice(VkPhysicalDevice physicalDevice, device->instance = physical_device->instance; device->physical_device = physical_device; + const struct panfrost_device *pdev = &physical_device->pdev; + vk_device_set_drm_fd(&device->vk, pdev->fd); + for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { const VkDeviceQueueCreateInfo *queue_create = &pCreateInfo->pQueueCreateInfos[i]; diff --git a/src/panfrost/vulkan/panvk_private.h b/src/panfrost/vulkan/panvk_private.h index d4dbd74c935..c21caa3b4ed 100644 --- a/src/panfrost/vulkan/panvk_private.h +++ b/src/panfrost/vulkan/panvk_private.h @@ -58,6 +58,7 @@ #include "vk_object.h" #include "vk_physical_device.h" #include "vk_queue.h" +#include "vk_sync.h" #include "wsi_common.h" #include "drm-uapi/panfrost_drm.h" @@ -185,6 +186,9 @@ struct panvk_physical_device { uint8_t device_uuid[VK_UUID_SIZE]; uint8_t cache_uuid[VK_UUID_SIZE]; + struct vk_sync_type drm_syncobj_type; + const struct vk_sync_type *sync_types[2]; + struct wsi_device wsi_device; struct panvk_meta meta; @@ -289,10 +293,6 @@ struct panvk_batch { bool issued; }; -struct panvk_syncobj { - uint32_t permanent, temporary; -}; - enum panvk_event_op_type { PANVK_EVENT_OP_SET, PANVK_EVENT_OP_RESET, @@ -304,25 +304,6 @@ struct panvk_event_op { struct panvk_event *event; }; -struct panvk_fence { - struct vk_object_base base; - struct panvk_syncobj syncobj; -}; - -struct panvk_semaphore { - struct vk_object_base base; - struct panvk_syncobj syncobj; -}; - -int -panvk_signal_syncobjs(struct panvk_device *device, - struct panvk_syncobj *syncobj1, - struct panvk_syncobj *syncobj2); - -int -panvk_syncobj_to_fd(struct panvk_device *device, - struct panvk_syncobj *sync); - struct panvk_device_memory { struct vk_object_base base; struct panfrost_bo *bo; @@ -1054,7 +1035,6 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_descriptor_set, base, VkDescriptorSet, VK_O VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_descriptor_set_layout, base, VkDescriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT) VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_device_memory, base, VkDeviceMemory, VK_OBJECT_TYPE_DEVICE_MEMORY) -VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_fence, base, VkFence, VK_OBJECT_TYPE_FENCE) VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_event, base, VkEvent, VK_OBJECT_TYPE_EVENT) VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_framebuffer, base, VkFramebuffer, VK_OBJECT_TYPE_FRAMEBUFFER) VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_image, vk.base, VkImage, VK_OBJECT_TYPE_IMAGE) @@ -1064,7 +1044,6 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_pipeline, base, VkPipeline, VK_OBJECT_TYPE_ VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_pipeline_layout, base, VkPipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT) VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_render_pass, base, VkRenderPass, VK_OBJECT_TYPE_RENDER_PASS) VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_sampler, base, VkSampler, VK_OBJECT_TYPE_SAMPLER) -VK_DEFINE_NONDISP_HANDLE_CASTS(panvk_semaphore, base, VkSemaphore, VK_OBJECT_TYPE_SEMAPHORE) #define panvk_arch_name(name, version) panvk_## version ## _ ## name @@ -1088,12 +1067,14 @@ do { \ #endif #include "panvk_vX_cmd_buffer.h" #include "panvk_vX_cs.h" +#include "panvk_vX_device.h" #include "panvk_vX_meta.h" #else #define PAN_ARCH 5 #define panvk_per_arch(name) panvk_arch_name(name, v5) #include "panvk_vX_cmd_buffer.h" #include "panvk_vX_cs.h" +#include "panvk_vX_device.h" #include "panvk_vX_meta.h" #undef PAN_ARCH #undef panvk_per_arch @@ -1101,6 +1082,7 @@ do { \ #define panvk_per_arch(name) panvk_arch_name(name, v6) #include "panvk_vX_cmd_buffer.h" #include "panvk_vX_cs.h" +#include "panvk_vX_device.h" #include "panvk_vX_meta.h" #undef PAN_ARCH #undef panvk_per_arch @@ -1108,6 +1090,7 @@ do { \ #define panvk_per_arch(name) panvk_arch_name(name, v7) #include "panvk_vX_cmd_buffer.h" #include "panvk_vX_cs.h" +#include "panvk_vX_device.h" #include "panvk_vX_meta.h" #undef PAN_ARCH #undef panvk_per_arch diff --git a/src/panfrost/vulkan/panvk_sync.c b/src/panfrost/vulkan/panvk_sync.c deleted file mode 100644 index 91f905bd589..00000000000 --- a/src/panfrost/vulkan/panvk_sync.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright (C) 2021 Collabora Ltd. - * - * Derived from tu_drm.c which is: - * Copyright © 2018 Google, Inc. - * Copyright © 2015 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include - -#include "panvk_private.h" - -static VkResult -sync_create(struct panvk_device *device, - struct panvk_syncobj *sync, - bool signaled) -{ - const struct panfrost_device *pdev = &device->physical_device->pdev; - - struct drm_syncobj_create create = { - .flags = signaled ? DRM_SYNCOBJ_CREATE_SIGNALED : 0, - }; - - int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_CREATE, &create); - if (ret) - return VK_ERROR_OUT_OF_HOST_MEMORY; - - sync->permanent = create.handle; - - return VK_SUCCESS; -} - -static void -sync_set_temporary(struct panvk_device *device, struct panvk_syncobj *sync, - uint32_t syncobj) -{ - const struct panfrost_device *pdev = &device->physical_device->pdev; - - if (sync->temporary) { - struct drm_syncobj_destroy destroy = { .handle = sync->temporary }; - drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy); - } - - sync->temporary = syncobj; -} - -static void -sync_destroy(struct panvk_device *device, struct panvk_syncobj *sync) -{ - const struct panfrost_device *pdev = &device->physical_device->pdev; - - if (!sync) - return; - - sync_set_temporary(device, sync, 0); - struct drm_syncobj_destroy destroy = { .handle = sync->permanent }; - drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy); -} - -static VkResult -sync_import(struct panvk_device *device, struct panvk_syncobj *sync, - bool temporary, bool sync_fd, int fd) -{ - const struct panfrost_device *pdev = &device->physical_device->pdev; - int ret; - - if (!sync_fd) { - uint32_t *dst = temporary ? &sync->temporary : &sync->permanent; - - struct drm_syncobj_handle handle = { .fd = fd }; - ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &handle); - if (ret) - return VK_ERROR_INVALID_EXTERNAL_HANDLE; - - if (*dst) { - struct drm_syncobj_destroy destroy = { .handle = *dst }; - drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy); - } - *dst = handle.handle; - close(fd); - } else { - assert(temporary); - - struct drm_syncobj_create create = {}; - - if (fd == -1) - create.flags |= DRM_SYNCOBJ_CREATE_SIGNALED; - - ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_CREATE, &create); - if (ret) - return VK_ERROR_INVALID_EXTERNAL_HANDLE; - - if (fd != -1) { - struct drm_syncobj_handle handle = { - .fd = fd, - .handle = create.handle, - .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE, - }; - - ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &handle); - if (ret) { - struct drm_syncobj_destroy destroy = { .handle = create.handle }; - drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy); - return VK_ERROR_INVALID_EXTERNAL_HANDLE; - } - close(fd); - } - - sync_set_temporary(device, sync, create.handle); - } - - return VK_SUCCESS; -} - -static VkResult -sync_export(struct panvk_device *device, struct panvk_syncobj *sync, - bool sync_fd, int *p_fd) -{ - const struct panfrost_device *pdev = &device->physical_device->pdev; - - struct drm_syncobj_handle handle = { - .handle = sync->temporary ? : sync->permanent, - .flags = sync_fd ? DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE : 0, - .fd = -1, - }; - int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &handle); - if (ret) - return vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE); - - /* restore permanent payload on export */ - sync_set_temporary(device, sync, 0); - - *p_fd = handle.fd; - return VK_SUCCESS; -} - -VkResult -panvk_CreateSemaphore(VkDevice _device, - const VkSemaphoreCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkSemaphore *pSemaphore) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - struct panvk_semaphore *sem = - vk_object_zalloc(&device->vk, pAllocator, sizeof(*sem), - VK_OBJECT_TYPE_SEMAPHORE); - if (!sem) - return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - - VkResult ret = sync_create(device, &sem->syncobj, false); - if (ret != VK_SUCCESS) { - vk_free2(&device->vk.alloc, pAllocator, sync); - return ret; - } - - *pSemaphore = panvk_semaphore_to_handle(sem); - return VK_SUCCESS; -} - -void -panvk_DestroySemaphore(VkDevice _device, VkSemaphore _sem, const VkAllocationCallbacks *pAllocator) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - VK_FROM_HANDLE(panvk_semaphore, sem, _sem); - - sync_destroy(device, &sem->syncobj); - vk_object_free(&device->vk, pAllocator, sem); -} - -VkResult -panvk_ImportSemaphoreFdKHR(VkDevice _device, const VkImportSemaphoreFdInfoKHR *info) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - VK_FROM_HANDLE(panvk_semaphore, sem, info->semaphore); - bool temp = info->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT; - bool sync_fd = info->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; - - return sync_import(device, &sem->syncobj, temp, sync_fd, info->fd); -} - -VkResult -panvk_GetSemaphoreFdKHR(VkDevice _device, const VkSemaphoreGetFdInfoKHR *info, int *pFd) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - VK_FROM_HANDLE(panvk_semaphore, sem, info->semaphore); - bool sync_fd = info->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT; - - return sync_export(device, &sem->syncobj, sync_fd, pFd); -} - -VkResult -panvk_CreateFence(VkDevice _device, - const VkFenceCreateInfo *info, - const VkAllocationCallbacks *pAllocator, - VkFence *pFence) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - struct panvk_fence *fence = - vk_object_zalloc(&device->vk, pAllocator, sizeof(*fence), - VK_OBJECT_TYPE_FENCE); - if (!fence) - return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - - VkResult ret = sync_create(device, &fence->syncobj, - info->flags & VK_FENCE_CREATE_SIGNALED_BIT); - if (ret != VK_SUCCESS) { - vk_free2(&device->vk.alloc, pAllocator, fence); - return ret; - } - - *pFence = panvk_fence_to_handle(fence); - return VK_SUCCESS; -} - -void -panvk_DestroyFence(VkDevice _device, VkFence _fence, - const VkAllocationCallbacks *pAllocator) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - VK_FROM_HANDLE(panvk_fence, fence, _fence); - - if (!fence) - return; - - sync_destroy(device, &fence->syncobj); - vk_object_free(&device->vk, pAllocator, fence); -} - -VkResult -panvk_ImportFenceFdKHR(VkDevice _device, const VkImportFenceFdInfoKHR *info) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - VK_FROM_HANDLE(panvk_fence, fence, info->fence); - bool sync_fd = info->handleType == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; - bool temp = info->flags & VK_FENCE_IMPORT_TEMPORARY_BIT; - - return sync_import(device, &fence->syncobj, temp, sync_fd, info->fd); -} - -VkResult -panvk_GetFenceFdKHR(VkDevice _device, const VkFenceGetFdInfoKHR *info, int *pFd) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - VK_FROM_HANDLE(panvk_fence, fence, info->fence); - bool sync_fd = info->handleType == VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT; - - return sync_export(device, &fence->syncobj, sync_fd, pFd); -} - -static VkResult -drm_syncobj_wait(struct panvk_device *device, - const uint32_t *handles, uint32_t count_handles, - int64_t timeout_nsec, bool wait_all) -{ - const struct panfrost_device *pdev = &device->physical_device->pdev; - struct drm_syncobj_wait wait = { - .handles = (uint64_t) (uintptr_t) handles, - .count_handles = count_handles, - .timeout_nsec = timeout_nsec, - .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT | - (wait_all ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL : 0) - }; - - int ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait); - if (ret) { - if (errno == ETIME) - return VK_TIMEOUT; - - assert(0); - return VK_ERROR_DEVICE_LOST; /* TODO */ - } - return VK_SUCCESS; -} - -static uint64_t -gettime_ns(void) -{ - struct timespec current; - clock_gettime(CLOCK_MONOTONIC, ¤t); - return (uint64_t)current.tv_sec * 1000000000 + current.tv_nsec; -} - -/* and the kernel converts it right back to relative timeout - very smart UAPI */ -static uint64_t -absolute_timeout(uint64_t timeout) -{ - if (timeout == 0) - return 0; - uint64_t current_time = gettime_ns(); - uint64_t max_timeout = (uint64_t) INT64_MAX - current_time; - - timeout = MIN2(max_timeout, timeout); - - return (current_time + timeout); -} - -VkResult -panvk_WaitForFences(VkDevice _device, - uint32_t fenceCount, - const VkFence *pFences, - VkBool32 waitAll, - uint64_t timeout) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - - if (panvk_device_is_lost(device)) - return VK_ERROR_DEVICE_LOST; - - uint32_t handles[fenceCount]; - for (unsigned i = 0; i < fenceCount; ++i) { - VK_FROM_HANDLE(panvk_fence, fence, pFences[i]); - - if (fence->syncobj.temporary) { - handles[i] = fence->syncobj.temporary; - } else { - handles[i] = fence->syncobj.permanent; - } - } - - return drm_syncobj_wait(device, handles, fenceCount, absolute_timeout(timeout), waitAll); -} - -VkResult -panvk_ResetFences(VkDevice _device, uint32_t fenceCount, const VkFence *pFences) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - const struct panfrost_device *pdev = &device->physical_device->pdev; - int ret; - - uint32_t handles[fenceCount]; - for (unsigned i = 0; i < fenceCount; ++i) { - VK_FROM_HANDLE(panvk_fence, fence, pFences[i]); - - sync_set_temporary(device, &fence->syncobj, 0); - handles[i] = fence->syncobj.permanent; - } - - struct drm_syncobj_array objs = { - .handles = (uint64_t) (uintptr_t) handles, - .count_handles = fenceCount, - }; - - ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_RESET, &objs); - if (ret) { - panvk_device_set_lost(device, "DRM_IOCTL_SYNCOBJ_RESET failure: %s", - strerror(errno)); - } - - return VK_SUCCESS; -} - -VkResult -panvk_GetFenceStatus(VkDevice _device, VkFence _fence) -{ - VK_FROM_HANDLE(panvk_device, device, _device); - VK_FROM_HANDLE(panvk_fence, fence, _fence); - uint32_t handle = fence->syncobj.temporary ? : fence->syncobj.permanent; - VkResult result; - - result = drm_syncobj_wait(device, &handle, 1, 0, false); - if (result == VK_TIMEOUT) - result = VK_NOT_READY; - return result; -} - -int -panvk_signal_syncobjs(struct panvk_device *device, - struct panvk_syncobj *syncobj1, - struct panvk_syncobj *syncobj2) -{ - const struct panfrost_device *pdev = &device->physical_device->pdev; - uint32_t handles[2], count = 0; - - if (syncobj1) - handles[count++] = syncobj1->temporary ?: syncobj1->permanent; - - if (syncobj2) - handles[count++] = syncobj2->temporary ?: syncobj2->permanent; - - if (!count) - return 0; - - struct drm_syncobj_array objs = { - .handles = (uintptr_t) handles, - .count_handles = count - }; - - return drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &objs); -} - -int -panvk_syncobj_to_fd(struct panvk_device *device, struct panvk_syncobj *sync) -{ - const struct panfrost_device *pdev = &device->physical_device->pdev; - struct drm_syncobj_handle handle = { .handle = sync->permanent }; - int ret; - - ret = drmIoctl(pdev->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &handle); - - return ret ? -1 : handle.fd; -} diff --git a/src/panfrost/vulkan/panvk_vX_device.c b/src/panfrost/vulkan/panvk_vX_device.c index 78d968c0e4d..6944afea557 100644 --- a/src/panfrost/vulkan/panvk_vX_device.c +++ b/src/panfrost/vulkan/panvk_vX_device.c @@ -33,6 +33,8 @@ #include "panvk_private.h" #include "panvk_cs.h" +#include "vk_drm_syncobj.h" + static void panvk_queue_submit_batch(struct panvk_queue *queue, struct panvk_batch *batch, @@ -198,106 +200,102 @@ panvk_signal_event_syncobjs(struct panvk_queue *queue, struct panvk_batch *batch } VkResult -panvk_per_arch(QueueSubmit)(VkQueue _queue, - uint32_t submitCount, - const VkSubmitInfo *pSubmits, - VkFence _fence) +panvk_per_arch(queue_submit)(struct vk_queue *vk_queue, + struct vk_queue_submit *submit) { - VK_FROM_HANDLE(panvk_queue, queue, _queue); - VK_FROM_HANDLE(panvk_fence, fence, _fence); + struct panvk_queue *queue = + container_of(vk_queue, struct panvk_queue, vk); const struct panfrost_device *pdev = &queue->device->physical_device->pdev; - for (uint32_t i = 0; i < submitCount; ++i) { - const VkSubmitInfo *submit = pSubmits + i; - unsigned nr_semaphores = submit->waitSemaphoreCount + 1; - uint32_t semaphores[nr_semaphores]; - - semaphores[0] = queue->sync; - for (unsigned i = 0; i < submit->waitSemaphoreCount; i++) { - VK_FROM_HANDLE(panvk_semaphore, sem, submit->pWaitSemaphores[i]); + unsigned nr_semaphores = submit->wait_count + 1; + uint32_t semaphores[nr_semaphores]; - semaphores[i + 1] = sem->syncobj.temporary ? : sem->syncobj.permanent; - } + semaphores[0] = queue->sync; + for (unsigned i = 0; i < submit->wait_count; i++) { + assert(vk_sync_type_is_drm_syncobj(submit->waits[i].sync->type)); + struct vk_drm_syncobj *syncobj = + vk_sync_as_drm_syncobj(submit->waits[i].sync); - for (uint32_t j = 0; j < submit->commandBufferCount; ++j) { - VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, (submit->pCommandBuffers[j])); + semaphores[i + 1] = syncobj->syncobj; + } - list_for_each_entry(struct panvk_batch, batch, &cmdbuf->batches, node) { - /* FIXME: should be done at the batch level */ - unsigned nr_bos = - panvk_pool_num_bos(&cmdbuf->desc_pool) + - panvk_pool_num_bos(&cmdbuf->varying_pool) + - panvk_pool_num_bos(&cmdbuf->tls_pool) + - (batch->fb.info ? batch->fb.info->attachment_count : 0) + - (batch->blit.src ? 1 : 0) + - (batch->blit.dst ? 1 : 0) + - (batch->scoreboard.first_tiler ? 1 : 0) + 1; - unsigned bo_idx = 0; - uint32_t bos[nr_bos]; + for (uint32_t j = 0; j < submit->command_buffer_count; ++j) { + struct panvk_cmd_buffer *cmdbuf = + container_of(submit->command_buffers[j], struct panvk_cmd_buffer, vk); - panvk_pool_get_bo_handles(&cmdbuf->desc_pool, &bos[bo_idx]); - bo_idx += panvk_pool_num_bos(&cmdbuf->desc_pool); + list_for_each_entry(struct panvk_batch, batch, &cmdbuf->batches, node) { + /* FIXME: should be done at the batch level */ + unsigned nr_bos = + panvk_pool_num_bos(&cmdbuf->desc_pool) + + panvk_pool_num_bos(&cmdbuf->varying_pool) + + panvk_pool_num_bos(&cmdbuf->tls_pool) + + (batch->fb.info ? batch->fb.info->attachment_count : 0) + + (batch->blit.src ? 1 : 0) + + (batch->blit.dst ? 1 : 0) + + (batch->scoreboard.first_tiler ? 1 : 0) + 1; + unsigned bo_idx = 0; + uint32_t bos[nr_bos]; - panvk_pool_get_bo_handles(&cmdbuf->varying_pool, &bos[bo_idx]); - bo_idx += panvk_pool_num_bos(&cmdbuf->varying_pool); + panvk_pool_get_bo_handles(&cmdbuf->desc_pool, &bos[bo_idx]); + bo_idx += panvk_pool_num_bos(&cmdbuf->desc_pool); - panvk_pool_get_bo_handles(&cmdbuf->tls_pool, &bos[bo_idx]); - bo_idx += panvk_pool_num_bos(&cmdbuf->tls_pool); + panvk_pool_get_bo_handles(&cmdbuf->varying_pool, &bos[bo_idx]); + bo_idx += panvk_pool_num_bos(&cmdbuf->varying_pool); - if (batch->fb.info) { - for (unsigned i = 0; i < batch->fb.info->attachment_count; i++) { - bos[bo_idx++] = batch->fb.info->attachments[i].iview->pview.image->data.bo->gem_handle; - } + panvk_pool_get_bo_handles(&cmdbuf->tls_pool, &bos[bo_idx]); + bo_idx += panvk_pool_num_bos(&cmdbuf->tls_pool); + + if (batch->fb.info) { + for (unsigned i = 0; i < batch->fb.info->attachment_count; i++) { + bos[bo_idx++] = batch->fb.info->attachments[i].iview->pview.image->data.bo->gem_handle; } - - if (batch->blit.src) - bos[bo_idx++] = batch->blit.src->gem_handle; - - if (batch->blit.dst) - bos[bo_idx++] = batch->blit.dst->gem_handle; - - if (batch->scoreboard.first_tiler) - bos[bo_idx++] = pdev->tiler_heap->gem_handle; - - bos[bo_idx++] = pdev->sample_positions->gem_handle; - assert(bo_idx == nr_bos); - - /* Merge identical BO entries. */ - for (unsigned x = 0; x < nr_bos; x++) { - for (unsigned y = x + 1; y < nr_bos; ) { - if (bos[x] == bos[y]) - bos[y] = bos[--nr_bos]; - else - y++; - } - } - - unsigned nr_in_fences = 0; - unsigned max_wait_event_syncobjs = - util_dynarray_num_elements(&batch->event_ops, - struct panvk_event_op); - uint32_t in_fences[nr_semaphores + max_wait_event_syncobjs]; - memcpy(in_fences, semaphores, nr_semaphores * sizeof(*in_fences)); - nr_in_fences += nr_semaphores; - - panvk_add_wait_event_syncobjs(batch, in_fences, &nr_in_fences); - - panvk_queue_submit_batch(queue, batch, bos, nr_bos, in_fences, nr_in_fences); - - panvk_signal_event_syncobjs(queue, batch); } - } - /* Transfer the out fence to signal semaphores */ - for (unsigned i = 0; i < submit->signalSemaphoreCount; i++) { - VK_FROM_HANDLE(panvk_semaphore, sem, submit->pSignalSemaphores[i]); - panvk_queue_transfer_sync(queue, sem->syncobj.temporary ? : sem->syncobj.permanent); + if (batch->blit.src) + bos[bo_idx++] = batch->blit.src->gem_handle; + + if (batch->blit.dst) + bos[bo_idx++] = batch->blit.dst->gem_handle; + + if (batch->scoreboard.first_tiler) + bos[bo_idx++] = pdev->tiler_heap->gem_handle; + + bos[bo_idx++] = pdev->sample_positions->gem_handle; + assert(bo_idx == nr_bos); + + /* Merge identical BO entries. */ + for (unsigned x = 0; x < nr_bos; x++) { + for (unsigned y = x + 1; y < nr_bos; ) { + if (bos[x] == bos[y]) + bos[y] = bos[--nr_bos]; + else + y++; + } + } + + unsigned nr_in_fences = 0; + unsigned max_wait_event_syncobjs = + util_dynarray_num_elements(&batch->event_ops, + struct panvk_event_op); + uint32_t in_fences[nr_semaphores + max_wait_event_syncobjs]; + memcpy(in_fences, semaphores, nr_semaphores * sizeof(*in_fences)); + nr_in_fences += nr_semaphores; + + panvk_add_wait_event_syncobjs(batch, in_fences, &nr_in_fences); + + panvk_queue_submit_batch(queue, batch, bos, nr_bos, in_fences, nr_in_fences); + + panvk_signal_event_syncobjs(queue, batch); } } - if (fence) { - /* Transfer the last out fence to the fence object */ - panvk_queue_transfer_sync(queue, fence->syncobj.temporary ? : fence->syncobj.permanent); + /* Transfer the out fence to signal semaphores */ + for (unsigned i = 0; i < submit->signal_count; i++) { + assert(vk_sync_type_is_drm_syncobj(submit->signals[i].sync->type)); + struct vk_drm_syncobj *syncobj = + vk_sync_as_drm_syncobj(submit->signals[i].sync); + + panvk_queue_transfer_sync(queue, syncobj->syncobj); } return VK_SUCCESS; diff --git a/src/panfrost/vulkan/panvk_vX_device.h b/src/panfrost/vulkan/panvk_vX_device.h new file mode 100644 index 00000000000..5a780944b94 --- /dev/null +++ b/src/panfrost/vulkan/panvk_vX_device.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2022 Collabora Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef PANVK_PRIVATE_H +#error "Must be included from panvk_private.h" +#endif + +#ifndef PAN_ARCH +#error "no arch" +#endif + +VkResult +panvk_per_arch(queue_submit)(struct vk_queue *queue, + struct vk_queue_submit *submit); diff --git a/src/panfrost/vulkan/panvk_wsi.c b/src/panfrost/vulkan/panvk_wsi.c index b3accd7a7e6..2af6f85ccc1 100644 --- a/src/panfrost/vulkan/panvk_wsi.c +++ b/src/panfrost/vulkan/panvk_wsi.c @@ -27,6 +27,9 @@ #include "panvk_private.h" +#include "vk_fence.h" +#include "vk_semaphore.h" +#include "vk_sync_dummy.h" #include "vk_util.h" #include "wsi_common.h" @@ -72,8 +75,8 @@ panvk_AcquireNextImage2KHR(VkDevice _device, uint32_t *pImageIndex) { VK_FROM_HANDLE(panvk_device, device, _device); - VK_FROM_HANDLE(panvk_fence, fence, pAcquireInfo->fence); - VK_FROM_HANDLE(panvk_semaphore, sem, pAcquireInfo->semaphore); + VK_FROM_HANDLE(vk_fence, fence, pAcquireInfo->fence); + VK_FROM_HANDLE(vk_semaphore, sem, pAcquireInfo->semaphore); struct panvk_physical_device *pdevice = device->physical_device; VkResult result = @@ -82,8 +85,24 @@ panvk_AcquireNextImage2KHR(VkDevice _device, /* signal fence/semaphore - image is available immediately */ if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) { - panvk_signal_syncobjs(device, fence ? &fence->syncobj : NULL, - sem ? &sem->syncobj : NULL); + VkResult sync_res; + if (fence) { + vk_fence_reset_temporary(&device->vk, fence); + sync_res = vk_sync_create(&device->vk, &vk_sync_dummy_type, + 0 /* flags */, 0 /* initial_value */, + &fence->temporary); + if (sync_res != VK_SUCCESS) + return sync_res; + } + + if (sem) { + vk_semaphore_reset_temporary(&device->vk, sem); + sync_res = vk_sync_create(&device->vk, &vk_sync_dummy_type, + 0 /* flags */, 0 /* initial_value */, + &sem->temporary); + if (sync_res != VK_SUCCESS) + return sync_res; + } } return result;