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 <lina@asahilina.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32081>
This commit is contained in:
Asahi Lina 2024-11-09 01:04:43 +09:00 committed by Marge Bot
parent 1a621a6967
commit da1601a4ec
4 changed files with 109 additions and 4 deletions

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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);
}