From f402f871a7afe5b91d6f1d3bd6e4ab1914371797 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 29 Jul 2025 15:50:39 -0400 Subject: [PATCH] asahi: enable virtgpu support this updates our virtgpu support to match the upstream protocol, and enables. it is marked for backport since the older Mesa releases already had virtgpu support, just gated off to allow for breaking wire protocol changes (of which there was 1 at the last moment). Upstream virglrenderer MR assigned to marge: https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1541 Backport-to: 25.1 Signed-off-by: Alyssa Rosenzweig Part-of: (cherry picked from commit 20dab5f819f7016b8d7f4e88927855a0e5ff7a61) --- .pick_status.json | 2 +- src/asahi/lib/agx_device.c | 5 +---- src/asahi/lib/agx_device.h | 1 + src/asahi/lib/agx_device_virtio.c | 15 +++++---------- src/asahi/vulkan/hk_queue.c | 21 +++++++++++++-------- src/asahi/vulkan/hk_queue.h | 3 +++ src/gallium/drivers/asahi/agx_batch.c | 2 +- src/gallium/drivers/asahi/agx_pipe.c | 1 + src/gallium/drivers/asahi/agx_state.h | 2 +- 9 files changed, 27 insertions(+), 25 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index a64fb4bb960..0122631c7db 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -3884,7 +3884,7 @@ "description": "asahi: enable virtgpu support", "nominated": true, "nomination_type": 4, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/asahi/lib/agx_device.c b/src/asahi/lib/agx_device.c index 745685c0e8d..88ac6c10cd2 100644 --- a/src/asahi/lib/agx_device.c +++ b/src/asahi/lib/agx_device.c @@ -83,7 +83,7 @@ static const struct debug_named_value agx_debug_options[] = { void agx_bo_free(struct agx_device *dev, struct agx_bo *bo) { - const uint64_t handle = bo->uapi_handle; + const uint64_t handle = bo->handle; if (bo->_map) munmap(bo->_map, bo->size); @@ -505,9 +505,6 @@ agx_open_device(void *memctx, struct agx_device *dev) dev->is_virtio = false; dev->ops = agx_device_drm_ops; } else if (!strcmp(version->name, "virtio_gpu")) { - /* TODO: virtio wire protocol is not stable yet */ - return false; - dev->is_virtio = true; if (!agx_virtio_open_device(dev)) { fprintf( diff --git a/src/asahi/lib/agx_device.h b/src/asahi/lib/agx_device.h index aabebec93ff..bb286c90cfc 100644 --- a/src/asahi/lib/agx_device.h +++ b/src/asahi/lib/agx_device.h @@ -67,6 +67,7 @@ struct nir_shader; struct agx_submit_virt { uint32_t extres_count; struct asahi_ccmd_submit_res *extres; + uint32_t ring_idx; }; typedef struct { diff --git a/src/asahi/lib/agx_device_virtio.c b/src/asahi/lib/agx_device_virtio.c index 347faa4e26c..148f7b0a1e5 100644 --- a/src/asahi/lib/agx_device_virtio.c +++ b/src/asahi/lib/agx_device_virtio.c @@ -124,7 +124,7 @@ agx_virtio_bo_bind(struct agx_device *dev, struct drm_asahi_gem_bind_op *ops, *req = (struct asahi_ccmd_vm_bind_req){ .hdr.cmd = ASAHI_CCMD_VM_BIND, - .hdr.len = sizeof(struct asahi_ccmd_vm_bind_req), + .hdr.len = req_len, .vm_id = dev->vm_id, .stride = sizeof(*ops), .count = count, @@ -215,12 +215,8 @@ agx_virtio_get_params(struct agx_device *dev, void *buf, size_t size) sizeof(struct asahi_ccmd_get_params_rsp) + size); int ret = vdrm_send_req(vdrm, &req.hdr, true); - if (!ret) - return ret; - - ret = rsp->ret; - if (ret) - return ret; + if (ret || rsp->ret) + return ret ? ret : rsp->ret; memcpy(buf, &rsp->payload, size); return size; @@ -265,8 +261,7 @@ agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit, } struct vdrm_execbuf_params p = { - /* Signal the host we want to wait for the command to complete */ - .ring_idx = 1, + .ring_idx = virt->ring_idx, .req = &req->hdr, .num_in_syncobjs = submit->in_sync_count, .in_syncobjs = vdrm_syncs, @@ -296,7 +291,7 @@ agx_virtio_open_device(struct agx_device *dev) { struct vdrm_device *vdrm; - vdrm = vdrm_device_connect(dev->fd, 2); + vdrm = vdrm_device_connect(dev->fd, 4); if (!vdrm) { fprintf(stderr, "could not connect vdrm\n"); return false; diff --git a/src/asahi/vulkan/hk_queue.c b/src/asahi/vulkan/hk_queue.c index 36ee2b2a2e8..6fc88f4f439 100644 --- a/src/asahi/vulkan/hk_queue.c +++ b/src/asahi/vulkan/hk_queue.c @@ -250,9 +250,10 @@ max_commands_per_submit(struct hk_device *dev) } static VkResult -queue_submit_single(struct hk_device *dev, struct drm_asahi_submit *submit) +queue_submit_single(struct hk_device *dev, struct drm_asahi_submit *submit, + unsigned ring_idx) { - struct agx_submit_virt virt = {0}; + struct agx_submit_virt virt = {.ring_idx = ring_idx}; if (dev->dev.is_virtio) { u_rwlock_rdlock(&dev->external_bos.lock); @@ -283,7 +284,7 @@ queue_submit_single(struct hk_device *dev, struct drm_asahi_submit *submit) */ static VkResult queue_submit_looped(struct hk_device *dev, struct drm_asahi_submit *submit, - unsigned command_count) + unsigned command_count, unsigned ring_idx) { uint8_t *cmdbuf = (uint8_t *)(uintptr_t)submit->cmdbuf; uint32_t offs = 0; @@ -356,7 +357,7 @@ queue_submit_looped(struct hk_device *dev, struct drm_asahi_submit *submit, .out_sync_count = has_out_syncs ? submit->out_sync_count : 0, }; - VkResult result = queue_submit_single(dev, &submit_ioctl); + VkResult result = queue_submit_single(dev, &submit_ioctl, ring_idx); if (result != VK_SUCCESS) return result; @@ -871,10 +872,13 @@ queue_submit(struct hk_device *dev, struct hk_queue *queue, }; VkResult result; - if (command_count <= max_commands_per_submit(dev)) - result = queue_submit_single(dev, &submit_ioctl); - else - result = queue_submit_looped(dev, &submit_ioctl, command_count); + if (command_count <= max_commands_per_submit(dev)) { + result = + queue_submit_single(dev, &submit_ioctl, queue->drm.virt_ring_idx); + } else { + result = queue_submit_looped(dev, &submit_ioctl, command_count, + queue->drm.virt_ring_idx); + } util_dynarray_fini(&payload); return result; @@ -964,6 +968,7 @@ hk_queue_init(struct hk_device *dev, struct hk_queue *queue, queue->vk.driver_submit = hk_queue_submit; queue->drm.id = agx_create_command_queue(&dev->dev, drm_priority); + queue->drm.virt_ring_idx = drm_priority + 1; if (drmSyncobjCreate(dev->dev.fd, 0, &queue->drm.syncobj)) { mesa_loge("drmSyncobjCreate() failed %d\n", errno); diff --git a/src/asahi/vulkan/hk_queue.h b/src/asahi/vulkan/hk_queue.h index b1073a03f3d..f45c8ed92e0 100644 --- a/src/asahi/vulkan/hk_queue.h +++ b/src/asahi/vulkan/hk_queue.h @@ -22,6 +22,9 @@ struct hk_queue { /* Timeline syncobj backing the queue */ uint32_t syncobj; + /* Ring-idx used with virtgpu, equal to priority + 1 */ + uint32_t virt_ring_idx; + /* Current maximum timeline value for the queue's syncobj. If the * syncobj's value equals timeline_value, then all work is complete. */ diff --git a/src/gallium/drivers/asahi/agx_batch.c b/src/gallium/drivers/asahi/agx_batch.c index 6d61c85470d..666944cf2a6 100644 --- a/src/gallium/drivers/asahi/agx_batch.c +++ b/src/gallium/drivers/asahi/agx_batch.c @@ -659,7 +659,7 @@ 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 = {0}; + struct agx_submit_virt virt = {.ring_idx = ctx->virt_ring_idx}; /* Elide syncing against our own queue */ if (wait_seqid && wait_seqid == ctx->flush_my_seqid) { diff --git a/src/gallium/drivers/asahi/agx_pipe.c b/src/gallium/drivers/asahi/agx_pipe.c index 76d0c9f79ba..e7ad683581b 100644 --- a/src/gallium/drivers/asahi/agx_pipe.c +++ b/src/gallium/drivers/asahi/agx_pipe.c @@ -1762,6 +1762,7 @@ agx_create_context(struct pipe_screen *screen, void *priv, unsigned flags) */ ctx->queue_id = agx_create_command_queue(agx_device(screen), priority); + ctx->virt_ring_idx = priority + 1; pctx->destroy = agx_destroy_context; pctx->flush = agx_flush; diff --git a/src/gallium/drivers/asahi/agx_state.h b/src/gallium/drivers/asahi/agx_state.h index e6dd33aaf27..da39a02141a 100644 --- a/src/gallium/drivers/asahi/agx_state.h +++ b/src/gallium/drivers/asahi/agx_state.h @@ -642,7 +642,7 @@ struct agx_context { } batches; /* Queue handle */ - uint32_t queue_id; + uint32_t queue_id, virt_ring_idx; struct agx_batch *batch; struct agx_bo *timestamps;