From da1601a4ecb87c9b7266b79fccb5766654f51b11 Mon Sep 17 00:00:00 2001 From: Asahi Lina Date: Sat, 9 Nov 2024 01:04:43 +0900 Subject: [PATCH] hk: Add virtio implicit sync support Since we can't know what BOs are written easily, just sync against all external BOs. This should go away once we have proper fence passing support so we can do implicit sync passing in muvm-x11bridge. Signed-off-by: Asahi Lina Part-of: --- src/asahi/vulkan/hk_device.c | 8 +++ src/asahi/vulkan/hk_device.h | 8 +++ src/asahi/vulkan/hk_device_memory.c | 79 +++++++++++++++++++++++++++++ src/asahi/vulkan/hk_queue.c | 18 +++++-- 4 files changed, 109 insertions(+), 4 deletions(-) diff --git a/src/asahi/vulkan/hk_device.c b/src/asahi/vulkan/hk_device.c index 5478e673c08..e904f80eaa9 100644 --- a/src/asahi/vulkan/hk_device.c +++ b/src/asahi/vulkan/hk_device.c @@ -452,6 +452,10 @@ hk_CreateDevice(VkPhysicalDevice physicalDevice, agx_scratch_init(&dev->dev, &dev->scratch.fs); agx_scratch_init(&dev->dev, &dev->scratch.cs); + u_rwlock_init(&dev->external_bos.lock); + util_dynarray_init(&dev->external_bos.counts, NULL); + util_dynarray_init(&dev->external_bos.list, NULL); + return VK_SUCCESS; fail_mem_cache: @@ -491,6 +495,10 @@ hk_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator) if (!dev) return; + util_dynarray_fini(&dev->external_bos.counts); + util_dynarray_fini(&dev->external_bos.list); + u_rwlock_destroy(&dev->external_bos.lock); + hk_device_finish_meta(dev); hk_destroy_internal_shaders(dev, &dev->kernels, false); hk_destroy_internal_shaders(dev, &dev->prolog_epilog, true); diff --git a/src/asahi/vulkan/hk_device.h b/src/asahi/vulkan/hk_device.h index cf05b26173c..08545826d09 100644 --- a/src/asahi/vulkan/hk_device.h +++ b/src/asahi/vulkan/hk_device.h @@ -8,7 +8,9 @@ #pragma once #include "asahi/lib/agx_device.h" +#include "util/rwlock.h" #include "util/simple_mtx.h" +#include "util/u_dynarray.h" #include "agx_bg_eot.h" #include "agx_pack.h" #include "agx_scratch.h" @@ -107,6 +109,12 @@ struct hk_device { } scratch; uint32_t perftest; + + struct { + struct u_rwlock lock; + struct util_dynarray list; + struct util_dynarray counts; + } external_bos; }; VK_DEFINE_HANDLE_CASTS(hk_device, vk.base, VkDevice, VK_OBJECT_TYPE_DEVICE) diff --git a/src/asahi/vulkan/hk_device_memory.c b/src/asahi/vulkan/hk_device_memory.c index a0922e80176..326ced5067e 100644 --- a/src/asahi/vulkan/hk_device_memory.c +++ b/src/asahi/vulkan/hk_device_memory.c @@ -49,6 +49,79 @@ hk_memory_type_flags(const VkMemoryType *type, return flags; } +static void +hk_add_ext_bo_locked(struct hk_device *dev, struct agx_bo *bo) +{ + uint32_t id = bo->vbo_res_id; + + unsigned count = util_dynarray_num_elements(&dev->external_bos.list, + struct asahi_ccmd_submit_res); + + for (unsigned i = 0; i < count; i++) { + struct asahi_ccmd_submit_res *p = util_dynarray_element( + &dev->external_bos.list, struct asahi_ccmd_submit_res, i); + + if (p->res_id == id) { + ++*util_dynarray_element(&dev->external_bos.counts, unsigned, i); + return; + } + } + + struct asahi_ccmd_submit_res res = { + .res_id = id, + .flags = ASAHI_EXTRES_READ | ASAHI_EXTRES_WRITE, + }; + util_dynarray_append(&dev->external_bos.list, struct asahi_ccmd_submit_res, + res); + util_dynarray_append(&dev->external_bos.counts, unsigned, 1); +} + +static void +hk_add_ext_bo(struct hk_device *dev, struct agx_bo *bo) +{ + if (dev->dev.is_virtio) { + u_rwlock_wrlock(&dev->external_bos.lock); + hk_add_ext_bo_locked(dev, bo); + u_rwlock_wrunlock(&dev->external_bos.lock); + } +} + +static void +hk_remove_ext_bo_locked(struct hk_device *dev, struct agx_bo *bo) +{ + uint32_t id = bo->vbo_res_id; + unsigned count = util_dynarray_num_elements(&dev->external_bos.list, + struct asahi_ccmd_submit_res); + + for (unsigned i = 0; i < count; i++) { + struct asahi_ccmd_submit_res *p = util_dynarray_element( + &dev->external_bos.list, struct asahi_ccmd_submit_res, i); + + if (p->res_id == id) { + unsigned *ctr = + util_dynarray_element(&dev->external_bos.counts, unsigned, i); + if (!--*ctr) { + *ctr = util_dynarray_pop(&dev->external_bos.counts, unsigned); + *p = util_dynarray_pop(&dev->external_bos.list, + struct asahi_ccmd_submit_res); + } + return; + } + } + + unreachable("BO not found"); +} + +static void +hk_remove_ext_bo(struct hk_device *dev, struct agx_bo *bo) +{ + if (dev->dev.is_virtio) { + u_rwlock_wrlock(&dev->external_bos.lock); + hk_remove_ext_bo_locked(dev, bo); + u_rwlock_wrunlock(&dev->external_bos.lock); + } +} + VKAPI_ATTR VkResult VKAPI_CALL hk_GetMemoryFdPropertiesKHR(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, @@ -146,6 +219,9 @@ hk_AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, } } + if (mem->bo->flags & (AGX_BO_SHAREABLE | AGX_BO_SHARED)) + hk_add_ext_bo(dev, mem->bo); + if (fd_info && fd_info->handleType) { /* From the Vulkan spec: * @@ -190,6 +266,9 @@ hk_FreeMemory(VkDevice device, VkDeviceMemory _mem, struct hk_memory_heap *heap = &pdev->mem_heaps[type->heapIndex]; p_atomic_add(&heap->used, -((int64_t)mem->bo->size)); + if (mem->bo->flags & (AGX_BO_SHAREABLE | AGX_BO_SHARED)) + hk_remove_ext_bo(dev, mem->bo); + agx_bo_unreference(&dev->dev, mem->bo); vk_device_memory_destroy(&dev->vk, pAllocator, &mem->vk); diff --git a/src/asahi/vulkan/hk_queue.c b/src/asahi/vulkan/hk_queue.c index 6a991c877e1..d34d855a732 100644 --- a/src/asahi/vulkan/hk_queue.c +++ b/src/asahi/vulkan/hk_queue.c @@ -272,7 +272,7 @@ max_commands_per_submit(struct hk_device *dev) } static VkResult -queue_submit_single(struct agx_device *dev, struct drm_asahi_submit *submit) +queue_submit_single(struct hk_device *dev, struct drm_asahi_submit *submit) { /* Currently we don't use the result buffer or implicit sync */ struct agx_submit_virt virt = { @@ -280,7 +280,17 @@ queue_submit_single(struct agx_device *dev, struct drm_asahi_submit *submit) .extres_count = 0, }; - int ret = dev->ops.submit(dev, submit, &virt); + if (dev->dev.is_virtio) { + u_rwlock_rdlock(&dev->external_bos.lock); + virt.extres_count = util_dynarray_num_elements( + &dev->external_bos.list, struct asahi_ccmd_submit_res); + virt.extres = util_dynarray_begin(&dev->external_bos.list); + } + + int ret = dev->dev.ops.submit(&dev->dev, submit, &virt); + + if (dev->dev.is_virtio) + u_rwlock_rdunlock(&dev->external_bos.lock); /* XXX: don't trap */ if (ret) { @@ -348,7 +358,7 @@ queue_submit_looped(struct hk_device *dev, struct drm_asahi_submit *submit) .out_sync_count = last ? submit->out_sync_count : 0, }; - VkResult result = queue_submit_single(&dev->dev, &submit_ioctl); + VkResult result = queue_submit_single(dev, &submit_ioctl); if (result != VK_SUCCESS) return result; @@ -520,7 +530,7 @@ queue_submit(struct hk_device *dev, struct hk_queue *queue, }; if (command_count <= max_commands_per_submit(dev)) - return queue_submit_single(&dev->dev, &submit_ioctl); + return queue_submit_single(dev, &submit_ioctl); else return queue_submit_looped(dev, &submit_ioctl); }