diff --git a/src/asahi/lib/agx_device.c b/src/asahi/lib/agx_device.c index a6283302f4d..b2703aac2ae 100644 --- a/src/asahi/lib/agx_device.c +++ b/src/asahi/lib/agx_device.c @@ -382,7 +382,7 @@ agx_get_params(struct agx_device *dev, void *buf, size_t size) static int agx_submit(struct agx_device *dev, struct drm_asahi_submit *submit, - uint32_t vbo_res_id) + struct agx_submit_virt *virt) { return drmIoctl(dev->fd, DRM_IOCTL_ASAHI_SUBMIT, submit); } diff --git a/src/asahi/lib/agx_device.h b/src/asahi/lib/agx_device.h index 37232147d22..bc5f9ff7d11 100644 --- a/src/asahi/lib/agx_device.h +++ b/src/asahi/lib/agx_device.h @@ -17,6 +17,11 @@ #include "layout.h" #include "unstable_asahi_drm.h" +#include "vdrm.h" +#include "virglrenderer_hw.h" + +#include "asahi_proto.h" + // TODO: this is a lie right now static const uint64_t AGX_SUPPORTED_INCOMPAT_FEATURES = DRM_ASAHI_FEAT_MANDATORY_ZS_COMPRESSION; @@ -61,6 +66,12 @@ struct nir_shader; #define BARRIER_RENDER (1 << DRM_ASAHI_SUBQUEUE_RENDER) #define BARRIER_COMPUTE (1 << DRM_ASAHI_SUBQUEUE_COMPUTE) +struct agx_submit_virt { + uint32_t vbo_res_id; + uint32_t extres_count; + struct asahi_ccmd_submit_res *extres; +}; + typedef struct { struct agx_bo *(*bo_alloc)(struct agx_device *dev, size_t size, size_t align, enum agx_bo_flags flags); @@ -70,7 +81,7 @@ typedef struct { void (*bo_mmap)(struct agx_device *dev, struct agx_bo *bo); ssize_t (*get_params)(struct agx_device *dev, void *buf, size_t size); int (*submit)(struct agx_device *dev, struct drm_asahi_submit *submit, - uint32_t vbo_res_id); + struct agx_submit_virt *virt); } agx_device_ops_t; struct agx_device { diff --git a/src/asahi/lib/agx_device_virtio.c b/src/asahi/lib/agx_device_virtio.c index 7ab3fb04cd7..83ce8d7fedf 100644 --- a/src/asahi/lib/agx_device_virtio.c +++ b/src/asahi/lib/agx_device_virtio.c @@ -194,7 +194,7 @@ out: static int agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit, - uint32_t vbo_res_id) + struct agx_submit_virt *virt) { struct drm_asahi_command *commands = (struct drm_asahi_command *)submit->commands; @@ -226,12 +226,17 @@ agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit, } } + size_t extres_size = + sizeof(struct asahi_ccmd_submit_res) * virt->extres_count; + req_len += extres_size; + struct asahi_ccmd_submit_req *req = (struct asahi_ccmd_submit_req *)calloc(1, req_len); req->queue_id = submit->queue_id; - req->result_res_id = vbo_res_id; + req->result_res_id = virt->vbo_res_id; req->command_count = submit->command_count; + req->extres_count = virt->extres_count; char *ptr = (char *)&req->payload; @@ -252,6 +257,9 @@ agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit, } } + memcpy(ptr, virt->extres, extres_size); + ptr += extres_size; + req->hdr.cmd = ASAHI_CCMD_SUBMIT; req->hdr.len = req_len; diff --git a/src/asahi/lib/asahi_proto.h b/src/asahi/lib/asahi_proto.h index 8820b46a5e7..577f701395e 100644 --- a/src/asahi/lib/asahi_proto.h +++ b/src/asahi/lib/asahi_proto.h @@ -120,11 +120,20 @@ struct asahi_ccmd_gem_bind_rsp { int32_t ret; }; +#define ASAHI_EXTRES_READ 0x01 +#define ASAHI_EXTRES_WRITE 0x02 + +struct asahi_ccmd_submit_res { + uint32_t res_id; + uint32_t flags; +}; + struct asahi_ccmd_submit_req { struct vdrm_ccmd_req hdr; uint32_t queue_id; uint32_t result_res_id; uint32_t command_count; + uint32_t extres_count; uint8_t payload[]; }; diff --git a/src/asahi/vulkan/hk_queue.c b/src/asahi/vulkan/hk_queue.c index 7eb20b6d277..4c1efc4eedf 100644 --- a/src/asahi/vulkan/hk_queue.c +++ b/src/asahi/vulkan/hk_queue.c @@ -299,7 +299,13 @@ union drm_asahi_cmd { static VkResult queue_submit_single(struct agx_device *dev, struct drm_asahi_submit *submit) { - int ret = dev->ops.submit(dev, submit, 0); + /* Currently we don't use the result buffer or implicit sync */ + struct agx_submit_virt virt = { + .vbo_res_id = 0, + .extres_count = 0, + }; + + int ret = dev->ops.submit(dev, submit, &virt); /* XXX: don't trap */ if (ret) { diff --git a/src/gallium/drivers/asahi/agx_batch.c b/src/gallium/drivers/asahi/agx_batch.c index 455b0f1c16a..a5999532a12 100644 --- a/src/gallium/drivers/asahi/agx_batch.c +++ b/src/gallium/drivers/asahi/agx_batch.c @@ -764,6 +764,10 @@ agx_batch_submit(struct agx_context *ctx, struct agx_batch *batch, uint64_t wait_seqid = p_atomic_read(&screen->flush_wait_seqid); + struct agx_submit_virt virt = { + .vbo_res_id = ctx->result_buf->vbo_res_id, + }; + /* Elide syncing against our own queue */ if (wait_seqid && wait_seqid == ctx->flush_my_seqid) { batch_debug(batch, @@ -859,6 +863,8 @@ agx_batch_submit(struct agx_context *ctx, struct agx_batch *batch, /* And keep track of the BO for cloning the out_sync */ shared_bos[shared_bo_count++] = bo; + if (dev->is_virtio) + virt.extres_count++; } else { /* Deal with BOs which are not externally shared, but which have been * written from another context within the same screen. We also need to @@ -878,6 +884,20 @@ agx_batch_submit(struct agx_context *ctx, struct agx_batch *batch, } } + if (dev->is_virtio && virt.extres_count) { + struct agx_bo **p = shared_bos; + virt.extres = + malloc(virt.extres_count * sizeof(struct asahi_ccmd_submit_res)); + + for (unsigned i = 0; i < virt.extres_count; i++) { + while (!*p) + p++; // Skip inter-context slots which are not recorded here + virt.extres[i].res_id = (*p)->vbo_res_id; + virt.extres[i].flags = ASAHI_EXTRES_READ | ASAHI_EXTRES_WRITE; + p++; + } + } + if (dev->debug & AGX_DBG_SCRATCH) { if (compute) agx_scratch_debug_pre(&ctx->scratch_cs); @@ -944,7 +964,7 @@ agx_batch_submit(struct agx_context *ctx, struct agx_batch *batch, .commands = (uint64_t)(uintptr_t)(&commands[0]), }; - int ret = dev->ops.submit(dev, &submit, ctx->result_buf->vbo_res_id); + int ret = dev->ops.submit(dev, &submit, &virt); u_rwlock_rdunlock(&screen->destroy_lock); @@ -1054,6 +1074,9 @@ agx_batch_submit(struct agx_context *ctx, struct agx_batch *batch, agx_batch_mark_submitted(batch); + if (virt.extres) + free(virt.extres); + /* Record the last syncobj for fence creation */ ctx->syncobj = batch->syncobj;