From 986b5fc57b07c06b5e0b3a3694d06898ebc80163 Mon Sep 17 00:00:00 2001 From: Maximilian Hofmann Date: Thu, 26 Feb 2026 23:28:58 +0100 Subject: [PATCH 01/42] fix: build with glibc 2.43 Several glibc functions now return a const pointer if the input is a const pointer and a non-const pointer if the input is non-const, causing a build failure. Fix this by declaring the output pointers as const if they are never modified, and for the lone failure where the output is modified, instead make the input non-const. Signed-off-by: Maximilian Hofmann Part-of: --- src/gallium/auxiliary/tgsi/tgsi_text.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gallium/auxiliary/tgsi/tgsi_text.c b/src/gallium/auxiliary/tgsi/tgsi_text.c index db7d7b95..7e37bf79 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_text.c +++ b/src/gallium/auxiliary/tgsi/tgsi_text.c @@ -84,7 +84,7 @@ streq_nocase_uprcase(const char *str1, static inline bool skip_n_chars(const char **pcur, int n) { - char* str = memchr(*pcur, '\0', n); + const char* str = memchr(*pcur, '\0', n); if (unlikely(str)) { *pcur = str; return false; From d37dc806d51038140bbddce84fdfd8ede5ab8014 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 11 Mar 2026 17:08:48 -0700 Subject: [PATCH 02/42] vkr: add a gbm allocation path without assuming minigbm Part-of: --- src/venus/vkr_device_memory.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/venus/vkr_device_memory.c b/src/venus/vkr_device_memory.c index ffe621bc..200a3774 100644 --- a/src/venus/vkr_device_memory.c +++ b/src/venus/vkr_device_memory.c @@ -5,6 +5,8 @@ #include "vkr_device_memory.h" +#include + #include "venus-protocol/vn_protocol_renderer_transport.h" #include "vkr_device_memory_gen.h" @@ -161,7 +163,7 @@ vkr_gbm_get_fd_info_from_allocation_info(struct vkr_physical_device *physical_de void **out_gbm_bo, VkImportMemoryFdInfoKHR *out_fd_info) { - const uint32_t gbm_bo_use_flags = + const uint32_t flags = GBM_BO_USE_LINEAR | GBM_BO_USE_SW_READ_RARELY | GBM_BO_USE_SW_WRITE_RARELY; struct gbm_bo *gbm_bo; int fd = -1; @@ -175,10 +177,24 @@ vkr_gbm_get_fd_info_from_allocation_info(struct vkr_physical_device *physical_de if (alloc_info->allocationSize > UINT32_MAX) return VK_ERROR_OUT_OF_DEVICE_MEMORY; - /* 4K alignment is used on all implementations we support. */ - gbm_bo = gbm_bo_create(physical_dev->gbm_device, - align(alloc_info->allocationSize, getpagesize()), 1, - GBM_FORMAT_R8, gbm_bo_use_flags); + /* Page alignment is used on all implementations we support. */ + const uint32_t alloc_size = align(alloc_info->allocationSize, getpagesize()); +#ifdef MINIGBM + const uint32_t format = GBM_FORMAT_R8; + const uint32_t width = alloc_size; + const uint32_t height = 1; +#else + /* Mesa gbm has texture size limitations, so we can't rely on R8 here. Instead, we + * allocate a large enough linear rgba8 buffer. + */ + const uint32_t format = GBM_FORMAT_ABGR8888; + const uint8_t pixel_bytes = 4; + const uint32_t width = + (uint32_t)ceil(sqrt((alloc_size + pixel_bytes - 1) / pixel_bytes)); + const uint32_t height = width; +#endif /* MINIGBM */ + + gbm_bo = gbm_bo_create(physical_dev->gbm_device, width, height, format, flags); if (!gbm_bo) return VK_ERROR_OUT_OF_DEVICE_MEMORY; From efeb2074128efa3a456e652866048735f0f82b7e Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 11 Mar 2026 15:00:31 -0700 Subject: [PATCH 03/42] vkr: add a debug option to force GBM import The UDMABUF option takes precedence over the GBM option. Part-of: --- src/venus/vkr_common.c | 1 + src/venus/vkr_common.h | 1 + src/venus/vkr_device_memory.c | 3 ++- src/venus/vkr_physical_device.c | 17 ++++++++++++----- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/venus/vkr_common.c b/src/venus/vkr_common.c index e7660920..8ff62c77 100644 --- a/src/venus/vkr_common.c +++ b/src/venus/vkr_common.c @@ -216,6 +216,7 @@ static const struct vn_info_extension_table vkr_extension_table = { static const struct debug_named_value vkr_debug_options[] = { { "validate", VKR_DEBUG_VALIDATE, "Force enabling the validation layer" }, { "udmabuf", VKR_DEBUG_UDMABUF, "Force udmabuf for host visible memory" }, + { "gbm", VKR_DEBUG_GBM, "Force gbm for host visible memory" }, DEBUG_NAMED_VALUE_END }; diff --git a/src/venus/vkr_common.h b/src/venus/vkr_common.h index e24a16fb..7a0df1d1 100644 --- a/src/venus/vkr_common.h +++ b/src/venus/vkr_common.h @@ -116,6 +116,7 @@ typedef uint64_t vkr_object_id; enum vkr_debug_flags { VKR_DEBUG_VALIDATE = 1 << 0, VKR_DEBUG_UDMABUF = 1 << 1, + VKR_DEBUG_GBM = 1 << 2, }; /* base class for all objects */ diff --git a/src/venus/vkr_device_memory.c b/src/venus/vkr_device_memory.c index 200a3774..d0f29419 100644 --- a/src/venus/vkr_device_memory.c +++ b/src/venus/vkr_device_memory.c @@ -306,8 +306,9 @@ vkr_dispatch_vkAllocateMemory(struct vn_dispatch_context *dispatch, const bool no_dma_buf_export = !export_info || !(export_info->handleTypes & VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); + const bool force_gbm_import = !!physical_dev->gbm_device; const bool force_udmabuf_import = physical_dev->udmabuf_dev_fd >= 0; - if (!force_udmabuf_import && + if (!(force_gbm_import || force_udmabuf_import) && (physical_dev->is_dma_buf_fd_export_supported || (physical_dev->is_opaque_fd_export_supported && no_dma_buf_export))) { const VkExternalMemoryHandleTypeFlagBits handle_type = diff --git a/src/venus/vkr_physical_device.c b/src/venus/vkr_physical_device.c index da41c9b1..043d5845 100644 --- a/src/venus/vkr_physical_device.c +++ b/src/venus/vkr_physical_device.c @@ -48,21 +48,23 @@ vkr_physical_device_get_udmabuf_dev_fd(void) #ifdef MINIGBM #include #else -#define minigbm_create_default_device(out_fd) NULL +#include "../vrend/vrend_winsys_gbm.h" #endif /* MINIGBM */ -/* TODO remove minigbm allocation fallback after requiring exporting from raw mappable - * device memory via a new Vulkan extension - */ static struct gbm_device *vkr_gbm_dev; static void vkr_gbm_device_init_once(void) { +#ifdef MINIGBM UNUSED int gbm_fd; vkr_gbm_dev = minigbm_create_default_device(&gbm_fd); +#else + struct virgl_gbm *gbm = virgl_gbm_init(-1); + vkr_gbm_dev = gbm->device; +#endif /* MINIGBM */ if (!vkr_gbm_dev) { - vkr_log("minigbm_create_default_device failed"); + vkr_log("vkr_gbm_device_init_once failed"); exit(-1); } } @@ -239,6 +241,11 @@ vkr_physical_device_init_memory_properties(struct vkr_physical_device *physical_ physical_dev->udmabuf_dev_fd = vkr_physical_device_get_udmabuf_dev_fd(); else vkr_log("missing VK_EXT_external_memory_dma_buf for udmabuf import!"); + } else if (VKR_DEBUG(GBM)) { + if (physical_dev->EXT_external_memory_dma_buf) + physical_dev->gbm_device = vkr_physical_device_get_gbm_device(); + else + vkr_log("missing VK_EXT_external_memory_dma_buf for gbm import!"); } } From d1e17bc95c2cd1190f8c2cbb100c81e66ec342ba Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Tue, 10 Mar 2026 21:11:14 -0700 Subject: [PATCH 04/42] proxy/server: SOCK_CLOEXEC and MSG_CMSG_CLOEXEC are optional Using SOCK_CLOEXEC and MSG_CMSG_CLOEXEC are good practice for socket communication, but venus client/server model doesn't involve any racy exec on parallel threads. Meanwhile, the ad-hoc server forked from the proxy client is after socket pair, and we manually close up corresponding fds on both client and server side. As for passing resource fds via socket, there's no requirement to set FD_CLOEXEC both internally and towards the virgl resource side. Just to ease MacOS adoption. Part-of: --- server/render_socket.c | 9 +++++++++ src/proxy/proxy_socket.c | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/server/render_socket.c b/server/render_socket.c index 58edcf46..9891010a 100644 --- a/server/render_socket.c +++ b/server/render_socket.c @@ -10,6 +10,15 @@ #include #include +#ifdef __APPLE__ +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif /* SOCK_CLOEXEC */ +#ifndef MSG_CMSG_CLOEXEC +#define MSG_CMSG_CLOEXEC 0 +#endif /* MSG_CMSG_CLOEXEC */ +#endif /* __APPLE__ */ + #define RENDER_SOCKET_MAX_FD_COUNT 8 /* The socket pair between the server process and the client process is set up diff --git a/src/proxy/proxy_socket.c b/src/proxy/proxy_socket.c index 51223c6c..146f0650 100644 --- a/src/proxy/proxy_socket.c +++ b/src/proxy/proxy_socket.c @@ -13,6 +13,12 @@ #define PROXY_SOCKET_MAX_FD_COUNT 8 +#ifdef __APPLE__ +#ifndef MSG_CMSG_CLOEXEC +#define MSG_CMSG_CLOEXEC 0 +#endif /* MSG_CMSG_CLOEXEC */ +#endif /* __APPLE__ */ + /* this is only used when the render server is started on demand */ bool proxy_socket_pair(int out_fds[static 2]) From 21cf02ca953b5f3bd2cc9729a5b806b3e42d862b Mon Sep 17 00:00:00 2001 From: Sergi Blanch Torne Date: Tue, 3 Mar 2026 10:04:32 +0100 Subject: [PATCH 05/42] ci: Update trace checksums The same issue happened in Mesa https://gitlab.freedesktop.org/mesa/mesa/-/commit/9f1a4461074f117ed124b1d6086624ac4da0e6a1 Signed-off-by: Sergi Blanch Torne Part-of: --- .gitlab-ci/expectations/virt/traces-virgl.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci/expectations/virt/traces-virgl.yml b/.gitlab-ci/expectations/virt/traces-virgl.yml index 3675b26b..c50de53a 100644 --- a/.gitlab-ci/expectations/virt/traces-virgl.yml +++ b/.gitlab-ci/expectations/virt/traces-virgl.yml @@ -9,7 +9,7 @@ traces: checksum: f8eba0fec6e3e0af9cb09844bc73bdc8 gputest/furmark-v2.trace: gl-virgl: - checksum: 8b34d61f34f9c98201a8f5947ab4a667 + checksum: 9fc8c1c66d1ab89f5c91101daaf5573d gputest/triangle-v2.trace: gl-virgl: checksum: b1a1224b949c3ea133e7d2a06b8d294f From 6edfc8b6b5e48bc20bf51ea1f851c58513ffc45c Mon Sep 17 00:00:00 2001 From: Collabora's Gfx CI Team Date: Wed, 25 Feb 2026 00:04:29 +0000 Subject: [PATCH 06/42] Uprev Mesa to 7fc6af99ea4ef86e96b098dcd29a52d33fdd915f https://gitlab.freedesktop.org/mesa/mesa/-/compare/2fa85edd75a4dac145ca9fee78dbe56207aa6870...7fc6af99ea4ef86e96b098dcd29a52d33fdd915f Part-of: --- .gitlab-ci.yml | 4 ++-- .gitlab-ci/expectations/virt/venus-fails.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2b378927..bc4e69b0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,7 +17,7 @@ variables: # # Pick a pipeline on https://gitlab.freedesktop.org/mesa/mesa/-/pipelines/ # - MESA_PIPELINE_ID: 1610924 + MESA_PIPELINE_ID: 1622883 MESA_PROJECT_PATH: mesa/mesa S3_JWT_FILE: /s3_jwt @@ -59,7 +59,7 @@ include: # IMPORTANT: Use a recent Mesa Git revision # The commit ref must be in sync with the pipeline picked above # It can be found on the pipeline page below the commit message - ref: 2fa85edd75a4dac145ca9fee78dbe56207aa6870 + ref: 7fc6af99ea4ef86e96b098dcd29a52d33fdd915f file: - '/.gitlab-ci/image-tags.yml' diff --git a/.gitlab-ci/expectations/virt/venus-fails.txt b/.gitlab-ci/expectations/virt/venus-fails.txt index e32d0e76..04bf7297 100644 --- a/.gitlab-ci/expectations/virt/venus-fails.txt +++ b/.gitlab-ci/expectations/virt/venus-fails.txt @@ -11,4 +11,5 @@ dEQP-VK.draw.dynamic_rendering.partial_secondary_cmd_buff.multiple_interpolation # uprev Mesa in Virglrenderer dEQP-VK.sparse_resources.image_block_shapes.2d.g8b8g8r8_422_unorm.samples_1,Fail +dEQP-VK.wsi.direct_drm.swapchain.private_data.image_usage,Crash From cbdff5fb9c6cf597d5f41c241c4a2900bb5b60d6 Mon Sep 17 00:00:00 2001 From: osy Date: Fri, 28 Nov 2025 16:34:26 -0800 Subject: [PATCH 07/42] server: add support for building on macOS We do not have signalfd() in macOS so we use kqueue() to listen for SIGCHLD. Also do not include when we do not have ENABLE_RENDER_SERVER_WORKER_THREAD. Part-of: --- server/render_worker.c | 78 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/server/render_worker.c b/server/render_worker.c index 24d2c363..a26d88e6 100644 --- a/server/render_worker.c +++ b/server/render_worker.c @@ -3,6 +3,12 @@ * SPDX-License-Identifier: MIT */ +#ifndef __APPLE__ +#include +#else +#include +#undef LIST_ENTRY +#endif #include "render_worker.h" /* One and only one of ENABLE_RENDER_SERVER_WORKER_* must be set. @@ -24,10 +30,11 @@ #include #include #include -#include #include #include +#ifdef ENABLE_RENDER_SERVER_WORKER_THREAD #include +#endif #include struct minijail; @@ -161,6 +168,48 @@ fork_minijail(const struct minijail *template) #ifndef ENABLE_RENDER_SERVER_WORKER_THREAD +#ifdef __APPLE__ +static int +create_sigchld_fd(void) +{ + /* On macOS, use kqueue to monitor SIGCHLD */ + int kq = kqueue(); + if (kq == -1) { + render_log("failed to create kqueue"); + return -1; + } + + /* Set up kqueue to monitor SIGCHLD signal */ + struct kevent kev; + EV_SET(&kev, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); + + if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) { + render_log("failed to add SIGCHLD to kqueue"); + close(kq); + return -1; + } + + /* Block SIGCHLD so it's only handled through kqueue */ + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { + render_log("failed to block SIGCHLD"); + close(kq); + return -1; + } + + /* Set kqueue to non-blocking mode */ + int flags = fcntl(kq, F_GETFL); + if (flags == -1 || fcntl(kq, F_SETFL, flags | O_NONBLOCK) == -1) { + render_log("failed to set kqueue non-blocking"); + close(kq); + return -1; + } + + return kq; +} +#else static int create_sigchld_fd(void) { @@ -196,6 +245,7 @@ create_sigchld_fd(void) return fd; } +#endif /* __APPLE__ */ #endif /* !ENABLE_RENDER_SERVER_WORKER_THREAD */ @@ -321,6 +371,31 @@ render_worker_jail_drain_sigchld_fd(struct render_worker_jail *jail) if (jail->sigchld_fd < 0) return true; +#ifdef __APPLE__ + /* On macOS, drain kqueue events */ + do { + struct kevent events[8]; + struct timespec timeout = {0, 0}; /* non-blocking */ + int nevents = kevent(jail->sigchld_fd, NULL, 0, events, 8, &timeout); + + if (nevents == -1) { + if (errno == EINTR) + continue; + render_log("failed to read kqueue events"); + return false; + } + + if (nevents == 0) + break; /* no more events */ + + /* Process SIGCHLD events - we don't need to do anything special + * as the signal count is in events[i].data, but we just need to drain */ + if (nevents < 8) + break; /* got fewer events than requested, so we're done */ + + } while (true); +#else + /* On Linux, drain signalfd */ do { struct signalfd_siginfo siginfos[8]; const ssize_t r = read(jail->sigchld_fd, siginfos, sizeof(siginfos)); @@ -332,6 +407,7 @@ render_worker_jail_drain_sigchld_fd(struct render_worker_jail *jail) render_log("failed to read signalfd"); return false; } while (true); +#endif return true; } From f9788a084a53963204822cf606dd75134094cbcd Mon Sep 17 00:00:00 2001 From: osy Date: Fri, 28 Nov 2025 16:43:25 -0800 Subject: [PATCH 08/42] vkr: use nanosleep() on macOS macOS does not have clock_nanosleep() Co-authored-by: Lucas Amaral Part-of: --- src/venus/vkr_ring.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/venus/vkr_ring.c b/src/venus/vkr_ring.c index 0e46df87..775ec280 100644 --- a/src/venus/vkr_ring.c +++ b/src/venus/vkr_ring.c @@ -204,7 +204,12 @@ vkr_ring_relax(uint32_t *iter) .tv_sec = us / 1000000, .tv_nsec = (us % 1000000) * 1000, }; +#ifdef __APPLE__ + /* macOS does not implement clock_nanosleep; a unified path is TBD */ + nanosleep(&ts, NULL); +#else clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL); +#endif } static bool From ce062a0809e5582c43e663329d0019296936ec2c Mon Sep 17 00:00:00 2001 From: osy Date: Sat, 20 Dec 2025 05:35:06 -0800 Subject: [PATCH 09/42] proxy: support SOCK_STREAM sockets macOS does not support SOCK_SEQPACKET so we have to make use of SOCK_STREAM. That means we have to take care of framing. Thankfully, the SCM_RIGHTS buffer will always be complete and ordered so we send that with a header indicating the number of bytes for the packet followed by the packet. Co-authored-by: Lucas Amaral Part-of: --- server/render_protocol.h | 13 ++++ server/render_server.c | 6 +- server/render_socket.c | 138 ++++++++++++++++++++++++++++++++++++++- src/proxy/proxy_client.c | 2 + src/proxy/proxy_server.c | 2 + src/proxy/proxy_socket.c | 134 ++++++++++++++++++++++++++++++++++++- 6 files changed, 292 insertions(+), 3 deletions(-) diff --git a/server/render_protocol.h b/server/render_protocol.h index 7e38ac0c..cae94a05 100644 --- a/server/render_protocol.h +++ b/server/render_protocol.h @@ -219,4 +219,17 @@ union render_context_op_request { struct render_context_op_submit_fence_request submit_fence; }; +#ifdef __APPLE__ +/** + * When we do not have SOCK_SEQPACKET support, we need to manage framing. + * This will be sent as the header of each packet when necessary. + */ +struct render_context_socket_header { + union { + uint32_t length; + uint8_t b[sizeof(uint32_t)]; + }; +}; +#endif /* __APPLE__ */ + #endif /* RENDER_PROTOCOL_H */ diff --git a/server/render_server.c b/server/render_server.c index 6b129e4f..ec2f4a37 100644 --- a/server/render_server.c +++ b/server/render_server.c @@ -148,7 +148,11 @@ render_server_parse_options(struct render_server *srv, int argc, char **argv) return false; } - if (srv->client_fd < 0 || !render_socket_is_seqpacket(srv->client_fd)) { + if (srv->client_fd < 0 +#ifndef __APPLE__ + || !render_socket_is_seqpacket(srv->client_fd) +#endif + ) { render_log("no valid client fd specified"); return false; } diff --git a/server/render_socket.c b/server/render_socket.c index 9891010a..e801cd8f 100644 --- a/server/render_socket.c +++ b/server/render_socket.c @@ -37,7 +37,11 @@ bool render_socket_pair(int out_fds[static 2]) { - int ret = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, out_fds); + int type = SOCK_SEQPACKET; +#ifdef __APPLE__ + type = SOCK_STREAM; +#endif + int ret = socketpair(AF_UNIX, type | SOCK_CLOEXEC, 0, out_fds); if (ret) { render_log("failed to create socket pair"); return false; @@ -85,9 +89,86 @@ get_received_fds(const struct msghdr *msg, int *out_count) return (const int *)CMSG_DATA(cmsg); } +#ifdef __APPLE__ +enum socket_state { + SOCKET_STATE_FIRST_MSG, + SOCKET_STATE_HEADER, + SOCKET_STATE_DATA, +}; +#endif + static bool render_socket_recvmsg(struct render_socket *socket, struct msghdr *msg, size_t *out_size) { +#ifdef __APPLE__ + enum socket_state state = SOCKET_STATE_FIRST_MSG; + struct render_context_socket_header hdr = {0}; + ssize_t want = sizeof(hdr); + struct msghdr _msg = { + .msg_iov = + &(struct iovec){ + .iov_base = &hdr, + .iov_len = want, + }, + .msg_iovlen = 1, + .msg_control = msg->msg_control, + .msg_controllen = msg->msg_controllen, + }; + socklen_t _msg_controllen; + + assert(msg->msg_iovlen == 1); + + *out_size = 0; + do { + const ssize_t s = recvmsg(socket->fd, &_msg, MSG_CMSG_CLOEXEC); + if (unlikely(s < 0)) { + if (errno == EAGAIN || errno == EINTR) + continue; + + render_log("failed to receive message: %s", strerror(errno)); + return false; + } + + if (state == SOCKET_STATE_FIRST_MSG) { + _msg_controllen = _msg.msg_controllen; + state = SOCKET_STATE_HEADER; + } else { + /* retain the cmsg from first message */ + assert(_msg.msg_controllen == 0); + } + + if (unlikely(_msg.msg_flags & MSG_CTRUNC)) { + render_log("failed to receive message: truncated"); + + int fd_count; + const int *fds = get_received_fds(&_msg, &fd_count); + for (int i = 0; i < fd_count; i++) + close(fds[i]); + + return false; + } + + if (s <= want) { + _msg.msg_iov[0].iov_base = (char *)_msg.msg_iov[0].iov_base + s; + _msg.msg_iov[0].iov_len -= s; + want -= s; + } + + if (state == SOCKET_STATE_DATA) { + *out_size += s; + } + + if (!want && state == SOCKET_STATE_HEADER) { + want = ntohl(hdr.length); + _msg.msg_iov[0].iov_base = msg->msg_iov[0].iov_base; + _msg.msg_iov[0].iov_len = want; + state = SOCKET_STATE_DATA; + } else if (!want && state == SOCKET_STATE_DATA) { + msg->msg_controllen = _msg_controllen; + break; + } + } while (true); +#else do { const ssize_t s = recvmsg(socket->fd, msg, MSG_CMSG_CLOEXEC); if (unlikely(s <= 0)) { @@ -115,6 +196,9 @@ render_socket_recvmsg(struct render_socket *socket, struct msghdr *msg, size_t * *out_size = s; return true; } while (true); +#endif + + return true; } static bool @@ -205,6 +289,57 @@ render_socket_receive_data(struct render_socket *socket, void *data, size_t size static bool render_socket_sendmsg(struct render_socket *socket, const struct msghdr *msg) { +#ifdef __APPLE__ + enum socket_state state = SOCKET_STATE_FIRST_MSG; + struct render_context_socket_header hdr = { + .length = htonl(msg->msg_iov[0].iov_len), + }; + ssize_t want = sizeof(hdr); + struct msghdr _msg = { + .msg_iov = + &(struct iovec){ + .iov_base = &hdr, + .iov_len = want, + }, + .msg_iovlen = 1, + .msg_control = msg->msg_control, + .msg_controllen = msg->msg_controllen, + }; + + assert(msg->msg_iovlen == 1); + + do { + const ssize_t s = sendmsg(socket->fd, &_msg, MSG_NOSIGNAL); + if (unlikely(s < 0)) { + if (errno == EAGAIN || errno == EINTR) + continue; + + render_log("failed to send message: %s", strerror(errno)); + return false; + } + + if (state == SOCKET_STATE_FIRST_MSG) { + _msg.msg_controllen = 0; + _msg.msg_control = NULL; + state = SOCKET_STATE_HEADER; + } + + if (s <= want) { + _msg.msg_iov[0].iov_base = (char *)_msg.msg_iov[0].iov_base + s; + _msg.msg_iov[0].iov_len -= s; + want -= s; + } + + if (!want && state == SOCKET_STATE_HEADER) { + want = ntohl(hdr.length); + _msg.msg_iov[0].iov_base = msg->msg_iov[0].iov_base; + _msg.msg_iov[0].iov_len = want; + state = SOCKET_STATE_DATA; + } else if (!want && state == SOCKET_STATE_DATA) { + return true; + } + } while (true); +#else do { const ssize_t s = sendmsg(socket->fd, msg, MSG_NOSIGNAL); if (unlikely(s < 0)) { @@ -219,6 +354,7 @@ render_socket_sendmsg(struct render_socket *socket, const struct msghdr *msg) assert(msg->msg_iovlen == 1 && msg->msg_iov[0].iov_len == (size_t)s); return true; } while (true); +#endif } static inline bool diff --git a/src/proxy/proxy_client.c b/src/proxy/proxy_client.c index 97e025fd..7a7ba539 100644 --- a/src/proxy/proxy_client.c +++ b/src/proxy/proxy_client.c @@ -55,10 +55,12 @@ proxy_client_create_context(struct proxy_client *client, return false; } +#ifndef __APPLE__ if (!proxy_socket_is_seqpacket(ctx_fd)) { close(ctx_fd); return false; } +#endif *out_ctx_fd = ctx_fd; return true; diff --git a/src/proxy/proxy_server.c b/src/proxy/proxy_server.c index c9ea27e1..7ccddb9c 100644 --- a/src/proxy/proxy_server.c +++ b/src/proxy/proxy_server.c @@ -114,12 +114,14 @@ proxy_server_create(void) } } +#ifndef __APPLE__ if (!proxy_socket_is_seqpacket(srv->client_fd)) { proxy_log("invalid client fd type"); close(srv->client_fd); free(srv); return NULL; } +#endif proxy_log("proxy server with pid %d", srv->pid); diff --git a/src/proxy/proxy_socket.c b/src/proxy/proxy_socket.c index 146f0650..d3f4906c 100644 --- a/src/proxy/proxy_socket.c +++ b/src/proxy/proxy_socket.c @@ -4,6 +4,7 @@ */ #include "proxy_socket.h" +#include "server/render_protocol.h" #include #include @@ -23,7 +24,11 @@ bool proxy_socket_pair(int out_fds[static 2]) { - int ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, out_fds); + int type = SOCK_SEQPACKET; +#ifdef __APPLE__ + type = SOCK_STREAM; +#endif + int ret = socketpair(AF_UNIX, type, 0, out_fds); if (ret) { proxy_log("failed to create socket pair"); return false; @@ -102,9 +107,81 @@ get_received_fds(const struct msghdr *msg, int *out_count) return (const int *)CMSG_DATA(cmsg); } +#ifdef __APPLE__ +enum socket_state { + SOCKET_STATE_FIRST_MSG, + SOCKET_STATE_HEADER, + SOCKET_STATE_DATA, +}; +#endif + static bool proxy_socket_recvmsg(struct proxy_socket *socket, struct msghdr *msg) { +#ifdef __APPLE__ + enum socket_state state = SOCKET_STATE_FIRST_MSG; + struct render_context_socket_header hdr = {0}; + ssize_t want = sizeof(hdr); + struct msghdr _msg = { + .msg_iov = + &(struct iovec){ + .iov_base = &hdr, + .iov_len = want, + }, + .msg_iovlen = 1, + .msg_control = msg->msg_control, + .msg_controllen = msg->msg_controllen, + }; + socklen_t _msg_controllen; + + assert(msg->msg_iovlen == 1); + + do { + const ssize_t s = recvmsg(socket->fd, &_msg, MSG_CMSG_CLOEXEC); + if (unlikely(s < 0)) { + if (errno == EAGAIN || errno == EINTR) + continue; + + proxy_log("failed to receive message: %s", strerror(errno)); + return false; + } + + if (state == SOCKET_STATE_FIRST_MSG) { + _msg_controllen = _msg.msg_controllen; + state = SOCKET_STATE_HEADER; + } else { + /* retain the cmsg from first message */ + assert(_msg.msg_controllen == 0); + } + + if (unlikely(_msg.msg_flags & MSG_CTRUNC)) { + proxy_log("failed to receive message: truncated"); + + int fd_count; + const int *fds = get_received_fds(&_msg, &fd_count); + for (int i = 0; i < fd_count; i++) + close(fds[i]); + + return false; + } + + if (s <= want) { + _msg.msg_iov[0].iov_base = (char *)_msg.msg_iov[0].iov_base + s; + _msg.msg_iov[0].iov_len -= s; + want -= s; + } + + if (!want && state == SOCKET_STATE_HEADER) { + want = ntohl(hdr.length); + _msg.msg_iov[0].iov_base = msg->msg_iov[0].iov_base; + _msg.msg_iov[0].iov_len = want; + state = SOCKET_STATE_DATA; + } else if (!want && state == SOCKET_STATE_DATA) { + msg->msg_controllen = _msg_controllen; + break; + } + } while (true); +#else do { const ssize_t s = recvmsg(socket->fd, msg, MSG_CMSG_CLOEXEC); if (unlikely(s < 0)) { @@ -130,6 +207,9 @@ proxy_socket_recvmsg(struct proxy_socket *socket, struct msghdr *msg) return true; } while (true); +#endif + + return true; } static bool @@ -198,6 +278,57 @@ proxy_socket_receive_reply_with_fds(struct proxy_socket *socket, static bool proxy_socket_sendmsg(struct proxy_socket *socket, const struct msghdr *msg) { +#ifdef __APPLE__ + enum socket_state state = SOCKET_STATE_FIRST_MSG; + struct render_context_socket_header hdr = { + .length = htonl(msg->msg_iov[0].iov_len), + }; + ssize_t want = sizeof(hdr); + struct msghdr _msg = { + .msg_iov = + &(struct iovec){ + .iov_base = &hdr, + .iov_len = want, + }, + .msg_iovlen = 1, + .msg_control = msg->msg_control, + .msg_controllen = msg->msg_controllen, + }; + + assert(msg->msg_iovlen == 1); + + do { + const ssize_t s = sendmsg(socket->fd, &_msg, MSG_NOSIGNAL); + if (unlikely(s < 0)) { + if (errno == EAGAIN || errno == EINTR) + continue; + + proxy_log("failed to send message: %s", strerror(errno)); + return false; + } + + if (state == SOCKET_STATE_FIRST_MSG) { + _msg.msg_controllen = 0; + _msg.msg_control = NULL; + state = SOCKET_STATE_HEADER; + } + + if (s <= want) { + _msg.msg_iov[0].iov_base = (char *)_msg.msg_iov[0].iov_base + s; + _msg.msg_iov[0].iov_len -= s; + want -= s; + } + + if (!want && state == SOCKET_STATE_HEADER) { + want = ntohl(hdr.length); + _msg.msg_iov[0].iov_base = msg->msg_iov[0].iov_base; + _msg.msg_iov[0].iov_len = want; + state = SOCKET_STATE_DATA; + } else if (!want && state == SOCKET_STATE_DATA) { + return true; + } + } while (true); +#else do { const ssize_t s = sendmsg(socket->fd, msg, MSG_NOSIGNAL); if (unlikely(s < 0)) { @@ -212,6 +343,7 @@ proxy_socket_sendmsg(struct proxy_socket *socket, const struct msghdr *msg) assert(msg->msg_iovlen == 1 && msg->msg_iov[0].iov_len == (size_t)s); return true; } while (true); +#endif } static bool From 96bc0cfc6c8a161ea6c6a8a02e51d1fec5580795 Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Sun, 8 Mar 2026 23:36:57 -0300 Subject: [PATCH 10/42] proxy: detect socket disconnect on SOCK_STREAM When the peer closes the socket (e.g. QEMU dies abnormally), recvmsg() returns 0 on SOCK_STREAM. The existing loop only checked for s < 0, so a zero return caused want -= 0 (a no-op) and the loop spun at 100% CPU forever. Add s == 0 checks in both recvmsg and sendmsg paths of render_socket and proxy_socket, returning false to signal disconnection. This lets the render server exit cleanly when QEMU terminates without calling proxy_server_destroy(). Signed-off-by: Lucas Amaral Part-of: --- server/render_socket.c | 9 +++++++++ src/proxy/proxy_socket.c | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/server/render_socket.c b/server/render_socket.c index e801cd8f..24b565e7 100644 --- a/server/render_socket.c +++ b/server/render_socket.c @@ -128,6 +128,11 @@ render_socket_recvmsg(struct render_socket *socket, struct msghdr *msg, size_t * render_log("failed to receive message: %s", strerror(errno)); return false; } + if (unlikely(s == 0)) { + /* Peer closed the socket. */ + render_log("socket disconnected"); + return false; + } if (state == SOCKET_STATE_FIRST_MSG) { _msg_controllen = _msg.msg_controllen; @@ -317,6 +322,10 @@ render_socket_sendmsg(struct render_socket *socket, const struct msghdr *msg) render_log("failed to send message: %s", strerror(errno)); return false; } + if (unlikely(s == 0)) { + render_log("failed to send message: socket disconnected"); + return false; + } if (state == SOCKET_STATE_FIRST_MSG) { _msg.msg_controllen = 0; diff --git a/src/proxy/proxy_socket.c b/src/proxy/proxy_socket.c index d3f4906c..625de051 100644 --- a/src/proxy/proxy_socket.c +++ b/src/proxy/proxy_socket.c @@ -145,6 +145,10 @@ proxy_socket_recvmsg(struct proxy_socket *socket, struct msghdr *msg) proxy_log("failed to receive message: %s", strerror(errno)); return false; } + if (unlikely(s == 0)) { + proxy_log("socket disconnected"); + return false; + } if (state == SOCKET_STATE_FIRST_MSG) { _msg_controllen = _msg.msg_controllen; @@ -306,6 +310,10 @@ proxy_socket_sendmsg(struct proxy_socket *socket, const struct msghdr *msg) proxy_log("failed to send message: %s", strerror(errno)); return false; } + if (unlikely(s == 0)) { + proxy_log("failed to send message: socket disconnected"); + return false; + } if (state == SOCKET_STATE_FIRST_MSG) { _msg.msg_controllen = 0; From 04ed113106ef7094b00ee5170bee27b4c0eeea0e Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Sat, 7 Mar 2026 10:37:18 -0300 Subject: [PATCH 11/42] server: fix kqueue non-blocking mode on macOS kqueue file descriptors do not support fcntl(F_SETFL, O_NONBLOCK) on macOS. The kqueue code added in "server: add support for building on macOS" attempted to set O_NONBLOCK this way, which failed silently. Remove the broken fcntl call. Non-blocking behavior is already achieved in render_worker_jail_drain_sigchld_fd() via kevent() with a zero timeout, which is the correct approach for kqueue. Fixes: eb2b98b4 ("server: add support for building on macOS") Signed-off-by: Lucas Amaral Part-of: --- server/render_worker.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/server/render_worker.c b/server/render_worker.c index a26d88e6..01621cff 100644 --- a/server/render_worker.c +++ b/server/render_worker.c @@ -199,14 +199,6 @@ create_sigchld_fd(void) return -1; } - /* Set kqueue to non-blocking mode */ - int flags = fcntl(kq, F_GETFL); - if (flags == -1 || fcntl(kq, F_SETFL, flags | O_NONBLOCK) == -1) { - render_log("failed to set kqueue non-blocking"); - close(kq); - return -1; - } - return kq; } #else From 5d4ba455c7b53c0b8f86869d3d3ee2ae02641d3b Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Tue, 17 Mar 2026 11:18:54 -0300 Subject: [PATCH 12/42] proxy/server: rename is_seqpacket to is_valid with platform checks Rename proxy_socket_is_seqpacket and render_socket_is_seqpacket to proxy_socket_is_valid and render_socket_is_valid. The functions now validate the expected socket type per platform: SOCK_STREAM on macOS, SOCK_SEQPACKET elsewhere. This removes the #ifndef __APPLE__ guards at every call site. Part-of: --- server/render_server.c | 6 +----- server/render_socket.c | 6 +++++- server/render_socket.h | 2 +- src/proxy/proxy_client.c | 4 +--- src/proxy/proxy_server.c | 4 +--- src/proxy/proxy_socket.c | 6 +++++- src/proxy/proxy_socket.h | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/server/render_server.c b/server/render_server.c index ec2f4a37..0563bc54 100644 --- a/server/render_server.c +++ b/server/render_server.c @@ -148,11 +148,7 @@ render_server_parse_options(struct render_server *srv, int argc, char **argv) return false; } - if (srv->client_fd < 0 -#ifndef __APPLE__ - || !render_socket_is_seqpacket(srv->client_fd) -#endif - ) { + if (srv->client_fd < 0 || !render_socket_is_valid(srv->client_fd)) { render_log("no valid client fd specified"); return false; } diff --git a/server/render_socket.c b/server/render_socket.c index 24b565e7..464b24f6 100644 --- a/server/render_socket.c +++ b/server/render_socket.c @@ -51,13 +51,17 @@ render_socket_pair(int out_fds[static 2]) } bool -render_socket_is_seqpacket(int fd) +render_socket_is_valid(int fd) { int type; socklen_t len = sizeof(type); if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len)) return false; +#ifdef __APPLE__ + return type == SOCK_STREAM; +#else return type == SOCK_SEQPACKET; +#endif } void diff --git a/server/render_socket.h b/server/render_socket.h index ead1f8cc..1f4ae431 100644 --- a/server/render_socket.h +++ b/server/render_socket.h @@ -16,7 +16,7 @@ bool render_socket_pair(int out_fds[static 2]); bool -render_socket_is_seqpacket(int fd); +render_socket_is_valid(int fd); void render_socket_init(struct render_socket *socket, int fd); diff --git a/src/proxy/proxy_client.c b/src/proxy/proxy_client.c index 7a7ba539..ad79be95 100644 --- a/src/proxy/proxy_client.c +++ b/src/proxy/proxy_client.c @@ -55,12 +55,10 @@ proxy_client_create_context(struct proxy_client *client, return false; } -#ifndef __APPLE__ - if (!proxy_socket_is_seqpacket(ctx_fd)) { + if (!proxy_socket_is_valid(ctx_fd)) { close(ctx_fd); return false; } -#endif *out_ctx_fd = ctx_fd; return true; diff --git a/src/proxy/proxy_server.c b/src/proxy/proxy_server.c index 7ccddb9c..c643f74d 100644 --- a/src/proxy/proxy_server.c +++ b/src/proxy/proxy_server.c @@ -114,14 +114,12 @@ proxy_server_create(void) } } -#ifndef __APPLE__ - if (!proxy_socket_is_seqpacket(srv->client_fd)) { + if (!proxy_socket_is_valid(srv->client_fd)) { proxy_log("invalid client fd type"); close(srv->client_fd); free(srv); return NULL; } -#endif proxy_log("proxy server with pid %d", srv->pid); diff --git a/src/proxy/proxy_socket.c b/src/proxy/proxy_socket.c index 625de051..dd30b112 100644 --- a/src/proxy/proxy_socket.c +++ b/src/proxy/proxy_socket.c @@ -38,7 +38,7 @@ proxy_socket_pair(int out_fds[static 2]) } bool -proxy_socket_is_seqpacket(int fd) +proxy_socket_is_valid(int fd) { int type; socklen_t len = sizeof(type); @@ -46,7 +46,11 @@ proxy_socket_is_seqpacket(int fd) proxy_log("fd %d err %s", fd, strerror(errno)); return false; } +#ifdef __APPLE__ + return type == SOCK_STREAM; +#else return type == SOCK_SEQPACKET; +#endif } void diff --git a/src/proxy/proxy_socket.h b/src/proxy/proxy_socket.h index 04e2f543..1e313cc8 100644 --- a/src/proxy/proxy_socket.h +++ b/src/proxy/proxy_socket.h @@ -16,7 +16,7 @@ bool proxy_socket_pair(int out_fds[static 2]); bool -proxy_socket_is_seqpacket(int fd); +proxy_socket_is_valid(int fd); void proxy_socket_init(struct proxy_socket *socket, int fd); From a09222f6855e5ff7577a3f463c6a84bfffdd3bb7 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 19 Mar 2026 13:10:48 -0700 Subject: [PATCH 13/42] server: udpate docs for main for Linux specifics Part-of: --- server/main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/main.c b/server/main.c index 90c6c624..83f22bc7 100644 --- a/server/main.c +++ b/server/main.c @@ -16,13 +16,13 @@ * up a socket pair, with one end owned by the worker and the other end sent * to and owned by the client process. * - * A worker can be a subprocess forked from the server process, or a thread - * created by the server process. When a worker is a subprocess, the - * subprocess returns from render_server_main and enters render_context_main. - * * When a worker is a thread, the thread enters render_context_main directly * from its start function. In this case, render_context_main must be * thread-safe. + * + * When a worker is a process, + * - On Linux, it's a subprocess forked from the server process. It returns + * from render_server_main and enters render_context_main. */ int main(int argc, char **argv) From bbe178bbe433ab9ca798b0769733eadc3d25abe0 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 19 Mar 2026 15:52:38 -0700 Subject: [PATCH 14/42] server: supports parsing worker context args This is to prepare for clean process spawn on non-Linux platforms e.g. MacOS and Windows. Also close the fds before ownership transfer. Inspired from https://gitlab.freedesktop.org/virgl/virglrenderer/-/merge_requests/1601 Part-of: --- server/render_server.c | 53 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/server/render_server.c b/server/render_server.c index 0563bc54..b9589bfb 100644 --- a/server/render_server.c +++ b/server/render_server.c @@ -11,6 +11,7 @@ #include #include "render_client.h" +#include "render_context.h" #include "render_worker.h" #define RENDER_SERVER_MAX_WORKER_COUNT 256 @@ -105,6 +106,10 @@ render_server_parse_options(struct render_server *srv, int argc, char **argv) OPT_WORKER_SECCOMP_BPF, OPT_WORKER_SECCOMP_MINIJAIL_POLICY, OPT_WORKER_SECCOMP_MINIJAIL_LOG, + OPT_WORKER_CONTEXT_INIT_FLAGS, + OPT_WORKER_CONTEXT_ID, + OPT_WORKER_CONTEXT_NAME, + OPT_WORKER_CONTEXT_FD, OPT_COUNT, }; static const struct option options[] = { @@ -114,6 +119,11 @@ render_server_parse_options(struct render_server *srv, int argc, char **argv) OPT_WORKER_SECCOMP_MINIJAIL_POLICY }, { "worker-seccomp-minijail-log", no_argument, NULL, OPT_WORKER_SECCOMP_MINIJAIL_LOG }, + { "worker-context-init-flags", required_argument, NULL, + OPT_WORKER_CONTEXT_INIT_FLAGS }, + { "worker-context-id", required_argument, NULL, OPT_WORKER_CONTEXT_ID }, + { "worker-context-name", required_argument, NULL, OPT_WORKER_CONTEXT_NAME }, + { "worker-context-fd", required_argument, NULL, OPT_WORKER_CONTEXT_FD }, { NULL, 0, NULL, 0 } }; static_assert(OPT_COUNT <= 'z', ""); @@ -136,6 +146,19 @@ render_server_parse_options(struct render_server *srv, int argc, char **argv) case OPT_WORKER_SECCOMP_MINIJAIL_LOG: srv->worker_seccomp_minijail_log = true; break; + case OPT_WORKER_CONTEXT_INIT_FLAGS: + srv->context_args->init_flags = atoi(optarg); + break; + case OPT_WORKER_CONTEXT_ID: + srv->context_args->ctx_id = atoi(optarg); + break; + case OPT_WORKER_CONTEXT_NAME: + snprintf(srv->context_args->ctx_name, sizeof(srv->context_args->ctx_name), "%s", + optarg); + break; + case OPT_WORKER_CONTEXT_FD: + srv->context_args->ctx_fd = atoi(optarg); + break; default: render_log("unknown option specified"); return false; @@ -148,12 +171,35 @@ render_server_parse_options(struct render_server *srv, int argc, char **argv) return false; } - if (srv->client_fd < 0 || !render_socket_is_valid(srv->client_fd)) { - render_log("no valid client fd specified"); + if (srv->client_fd < 0 && srv->context_args->ctx_fd < 0) { + render_log("no socket fd specified"); return false; } + if (srv->client_fd >= 0 && srv->context_args->ctx_fd >= 0) { + render_log("multiple socket fds specified"); + goto fail; + } + + if (srv->client_fd >= 0 && !render_socket_is_valid(srv->client_fd)) { + render_log("client fd is invalid"); + goto fail; + } + + if (srv->context_args->ctx_fd >= 0 && + !render_socket_is_valid(srv->context_args->ctx_fd)) { + render_log("context fd is invalid"); + goto fail; + } + return true; + +fail: + if (srv->client_fd >= 0) + close(srv->client_fd); + if (srv->context_args->ctx_fd >= 0) + close(srv->context_args->ctx_fd); + return false; } static bool @@ -162,6 +208,9 @@ render_server_init(struct render_server *srv, char **argv, struct render_context_args *ctx_args) { + memset(ctx_args, 0, sizeof(*ctx_args)); + ctx_args->ctx_fd = -1; + memset(srv, 0, sizeof(*srv)); srv->state = RENDER_SERVER_STATE_RUN; srv->context_args = ctx_args; From 2bef09b9efb1867916a06cc463d6bf84837b0fb6 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 19 Mar 2026 17:09:57 -0700 Subject: [PATCH 15/42] server: allow cleanly spawn subprocess This helps skip: - render_worker_jail_create - render_server_run Part-of: --- server/render_server.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/server/render_server.c b/server/render_server.c index b9589bfb..efa73133 100644 --- a/server/render_server.c +++ b/server/render_server.c @@ -62,6 +62,9 @@ render_server_poll(UNUSED struct render_server *srv, static bool render_server_run(struct render_server *srv) { + if (srv->state == RENDER_SERVER_STATE_SUBPROCESS) + return true; + struct render_client *client = srv->client; struct pollfd poll_fds[RENDER_SERVER_POLL_COUNT]; @@ -219,6 +222,13 @@ render_server_init(struct render_server *srv, if (!render_server_parse_options(srv, argc, argv)) return false; + if (srv->context_args->ctx_fd >= 0) { + assert(srv->client_fd < 0); + srv->context_args->valid = true; + srv->state = RENDER_SERVER_STATE_SUBPROCESS; + return true; + } + enum render_worker_jail_seccomp_filter seccomp_filter = RENDER_WORKER_JAIL_SECCOMP_NONE; const char *seccomp_path = NULL; From 7a6d61a6409083a33bdbb4bddf6dd10912050640 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Fri, 20 Mar 2026 12:19:33 -0700 Subject: [PATCH 16/42] vkr: roll metal vulkan header Part-of: --- meson.build | 6 + src/venus/venus-protocol/vulkan_metal.h | 244 ++++++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 src/venus/venus-protocol/vulkan_metal.h diff --git a/meson.build b/meson.build index 69c1bb82..8e1c0767 100644 --- a/meson.build +++ b/meson.build @@ -365,6 +365,12 @@ if with_venus epoll_dep = [] endif + if with_host_darwin + venus_dep += declare_dependency( + compile_args : ['-DVK_USE_PLATFORM_METAL_EXT'], + ) + endif + conf_data.set('ENABLE_VENUS', 1) conf_data.set('ENABLE_RENDER_SERVER', 1) conf_data.set('RENDER_SERVER_EXEC_PATH', diff --git a/src/venus/venus-protocol/vulkan_metal.h b/src/venus/venus-protocol/vulkan_metal.h new file mode 100644 index 00000000..501c3638 --- /dev/null +++ b/src/venus/venus-protocol/vulkan_metal.h @@ -0,0 +1,244 @@ +#ifndef VULKAN_METAL_H_ +#define VULKAN_METAL_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_EXT_metal_surface is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_metal_surface 1 +#ifdef __OBJC__ +@class CAMetalLayer; +#else +typedef void CAMetalLayer; +#endif + +#define VK_EXT_METAL_SURFACE_SPEC_VERSION 1 +#define VK_EXT_METAL_SURFACE_EXTENSION_NAME "VK_EXT_metal_surface" +typedef VkFlags VkMetalSurfaceCreateFlagsEXT; +typedef struct VkMetalSurfaceCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkMetalSurfaceCreateFlagsEXT flags; + const CAMetalLayer* pLayer; +} VkMetalSurfaceCreateInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateMetalSurfaceEXT)(VkInstance instance, const VkMetalSurfaceCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateMetalSurfaceEXT( + VkInstance instance, + const VkMetalSurfaceCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkSurfaceKHR* pSurface); +#endif +#endif + + +// VK_EXT_metal_objects is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_metal_objects 1 +#ifdef __OBJC__ +@protocol MTLDevice; +typedef __unsafe_unretained id MTLDevice_id; +#else +typedef void* MTLDevice_id; +#endif + +#ifdef __OBJC__ +@protocol MTLCommandQueue; +typedef __unsafe_unretained id MTLCommandQueue_id; +#else +typedef void* MTLCommandQueue_id; +#endif + +#ifdef __OBJC__ +@protocol MTLBuffer; +typedef __unsafe_unretained id MTLBuffer_id; +#else +typedef void* MTLBuffer_id; +#endif + +#ifdef __OBJC__ +@protocol MTLTexture; +typedef __unsafe_unretained id MTLTexture_id; +#else +typedef void* MTLTexture_id; +#endif + +typedef struct __IOSurface* IOSurfaceRef; +#ifdef __OBJC__ +@protocol MTLSharedEvent; +typedef __unsafe_unretained id MTLSharedEvent_id; +#else +typedef void* MTLSharedEvent_id; +#endif + +#define VK_EXT_METAL_OBJECTS_SPEC_VERSION 2 +#define VK_EXT_METAL_OBJECTS_EXTENSION_NAME "VK_EXT_metal_objects" + +typedef enum VkExportMetalObjectTypeFlagBitsEXT { + VK_EXPORT_METAL_OBJECT_TYPE_METAL_DEVICE_BIT_EXT = 0x00000001, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_COMMAND_QUEUE_BIT_EXT = 0x00000002, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT = 0x00000004, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_TEXTURE_BIT_EXT = 0x00000008, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT = 0x00000010, + VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT = 0x00000020, + VK_EXPORT_METAL_OBJECT_TYPE_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF +} VkExportMetalObjectTypeFlagBitsEXT; +typedef VkFlags VkExportMetalObjectTypeFlagsEXT; +typedef struct VkExportMetalObjectCreateInfoEXT { + VkStructureType sType; + const void* pNext; + VkExportMetalObjectTypeFlagBitsEXT exportObjectType; +} VkExportMetalObjectCreateInfoEXT; + +typedef struct VkExportMetalObjectsInfoEXT { + VkStructureType sType; + const void* pNext; +} VkExportMetalObjectsInfoEXT; + +typedef struct VkExportMetalDeviceInfoEXT { + VkStructureType sType; + const void* pNext; + MTLDevice_id mtlDevice; +} VkExportMetalDeviceInfoEXT; + +typedef struct VkExportMetalCommandQueueInfoEXT { + VkStructureType sType; + const void* pNext; + VkQueue queue; + MTLCommandQueue_id mtlCommandQueue; +} VkExportMetalCommandQueueInfoEXT; + +typedef struct VkExportMetalBufferInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + MTLBuffer_id mtlBuffer; +} VkExportMetalBufferInfoEXT; + +typedef struct VkImportMetalBufferInfoEXT { + VkStructureType sType; + const void* pNext; + MTLBuffer_id mtlBuffer; +} VkImportMetalBufferInfoEXT; + +typedef struct VkExportMetalTextureInfoEXT { + VkStructureType sType; + const void* pNext; + VkImage image; + VkImageView imageView; + VkBufferView bufferView; + VkImageAspectFlagBits plane; + MTLTexture_id mtlTexture; +} VkExportMetalTextureInfoEXT; + +typedef struct VkImportMetalTextureInfoEXT { + VkStructureType sType; + const void* pNext; + VkImageAspectFlagBits plane; + MTLTexture_id mtlTexture; +} VkImportMetalTextureInfoEXT; + +typedef struct VkExportMetalIOSurfaceInfoEXT { + VkStructureType sType; + const void* pNext; + VkImage image; + IOSurfaceRef ioSurface; +} VkExportMetalIOSurfaceInfoEXT; + +typedef struct VkImportMetalIOSurfaceInfoEXT { + VkStructureType sType; + const void* pNext; + IOSurfaceRef ioSurface; +} VkImportMetalIOSurfaceInfoEXT; + +typedef struct VkExportMetalSharedEventInfoEXT { + VkStructureType sType; + const void* pNext; + VkSemaphore semaphore; + VkEvent event; + MTLSharedEvent_id mtlSharedEvent; +} VkExportMetalSharedEventInfoEXT; + +typedef struct VkImportMetalSharedEventInfoEXT { + VkStructureType sType; + const void* pNext; + MTLSharedEvent_id mtlSharedEvent; +} VkImportMetalSharedEventInfoEXT; + +typedef void (VKAPI_PTR *PFN_vkExportMetalObjectsEXT)(VkDevice device, VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkExportMetalObjectsEXT( + VkDevice device, + VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); +#endif +#endif + + +// VK_EXT_external_memory_metal is a preprocessor guard. Do not pass it to API calls. +#define VK_EXT_external_memory_metal 1 +#define VK_EXT_EXTERNAL_MEMORY_METAL_SPEC_VERSION 1 +#define VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME "VK_EXT_external_memory_metal" +typedef struct VkImportMemoryMetalHandleInfoEXT { + VkStructureType sType; + const void* pNext; + VkExternalMemoryHandleTypeFlagBits handleType; + void* handle; +} VkImportMemoryMetalHandleInfoEXT; + +typedef struct VkMemoryMetalHandlePropertiesEXT { + VkStructureType sType; + void* pNext; + uint32_t memoryTypeBits; +} VkMemoryMetalHandlePropertiesEXT; + +typedef struct VkMemoryGetMetalHandleInfoEXT { + VkStructureType sType; + const void* pNext; + VkDeviceMemory memory; + VkExternalMemoryHandleTypeFlagBits handleType; +} VkMemoryGetMetalHandleInfoEXT; + +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryMetalHandleEXT)(VkDevice device, const VkMemoryGetMetalHandleInfoEXT* pGetMetalHandleInfo, void** pHandle); +typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryMetalHandlePropertiesEXT)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, const void* pHandle, VkMemoryMetalHandlePropertiesEXT* pMemoryMetalHandleProperties); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryMetalHandleEXT( + VkDevice device, + const VkMemoryGetMetalHandleInfoEXT* pGetMetalHandleInfo, + void** pHandle); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryMetalHandlePropertiesEXT( + VkDevice device, + VkExternalMemoryHandleTypeFlagBits handleType, + const void* pHandle, + VkMemoryMetalHandlePropertiesEXT* pMemoryMetalHandleProperties); +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif From 0c3fa5b2bed2b1bfd6479b91ef7699a7eace9367 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 25 Mar 2026 20:45:54 -0700 Subject: [PATCH 17/42] vtest: avoid leaking workers on threadpool fini Part-of: --- vtest/threadpool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vtest/threadpool.c b/vtest/threadpool.c index dbe3baa8..412a3c42 100644 --- a/vtest/threadpool.c +++ b/vtest/threadpool.c @@ -123,7 +123,7 @@ threadpool_fini(struct threadpool *tp) { mtx_lock(&tp->lock); - while (!list_is_empty(&tp->idle_workers) && + while (!list_is_empty(&tp->idle_workers) || !list_is_empty(&tp->busy_workers)) { struct threadpool_worker *w; int ret; From cdcfb72cb92480049faa394e7ecca8eb7270335a Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 25 Mar 2026 20:44:33 -0700 Subject: [PATCH 18/42] vtest: threadpool to robustly handle spurious wakeups Part-of: --- vtest/threadpool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vtest/threadpool.c b/vtest/threadpool.c index 412a3c42..87c23a08 100644 --- a/vtest/threadpool.c +++ b/vtest/threadpool.c @@ -37,7 +37,7 @@ worker_main(void *arg) mtx_lock(&w->tp->lock); do { - if (!w->work) + while (!w->work) cnd_wait(&w->cnd, &w->tp->lock); if (w->work == exit_work) @@ -129,7 +129,7 @@ threadpool_fini(struct threadpool *tp) int ret; /* Wait for an idle worker: */ - if (list_is_empty(&tp->idle_workers)) + while (list_is_empty(&tp->idle_workers)) cnd_wait(&tp->cnd, &tp->lock); /* Kick exit job to notify the worker to shut down: */ From 485c0182421618b5b0f7defa0e80b92dbd3b9e15 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 25 Mar 2026 20:52:29 -0700 Subject: [PATCH 19/42] vkr: handle spurious wakeups in ring notify cnd_wait This ensures we don't unexpectedly unset VK_RING_STATUS_IDLE_BIT_MESA when the ring is still idle when spurious wakeups occur. The bug pattern would be driver side stuck in ring seqno progression. This change also properly handles cnd_wait errors. Part-of: --- src/venus/vkr_ring.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/venus/vkr_ring.c b/src/venus/vkr_ring.c index 775ec280..dc6b5789 100644 --- a/src/venus/vkr_ring.c +++ b/src/venus/vkr_ring.c @@ -281,8 +281,14 @@ vkr_ring_thread(void *arg) TRACE_SCOPE("ring idle"); mtx_lock(&ring->mutex); - if (ring->started && !ring->pending_notify) - cnd_wait(&ring->cond, &ring->mutex); + while (ring->started && !ring->pending_notify) { + ret = cnd_wait(&ring->cond, &ring->mutex); + if (ret != thrd_success) { + vkr_log("%s: ring idle cnd_wait has failed(%d)", __func__, ret); + ret = -EINVAL; + goto out; + } + } vkr_ring_unset_status_bits(ring, VK_RING_STATUS_IDLE_BIT_MESA); mtx_unlock(&ring->mutex); @@ -333,6 +339,7 @@ vkr_ring_thread(void *arg) } } +out: if (ret < 0) { vkr_ring_set_status_bits(ring, VK_RING_STATUS_FATAL_BIT_MESA); vkr_context_on_ring_fatal(ctx); From be2b86c32aaf32a44ca625caf1b268915f0b5da9 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Thu, 26 Mar 2026 08:54:08 -0700 Subject: [PATCH 20/42] vkr: handle spurious wakeups in ring monitor thread The absolute wait target should be update only when real timeout occurs but not spurious wakeups. The bug pattern would be driver side unable to detect heartbeat, ending up with a false-positive ring alive status expiration. The chance to hit this is really low though. Part-of: --- src/venus/vkr_context.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/venus/vkr_context.c b/src/venus/vkr_context.c index 7c82e7c7..2704bfd8 100644 --- a/src/venus/vkr_context.c +++ b/src/venus/vkr_context.c @@ -528,7 +528,7 @@ vkr_context_ring_monitor_thread(void *arg) snprintf(thread_name, ARRAY_SIZE(thread_name), "vkr-ringmon-%d", ctx->ctx_id); u_thread_setname(thread_name); - struct timespec ts; + struct timespec abs_ts; int ret = thrd_busy; assert(ctx->ring_monitor.started); while (ctx->ring_monitor.started) { @@ -540,20 +540,23 @@ vkr_context_ring_monitor_thread(void *arg) vkr_ring_set_status_bits(ring, VK_RING_STATUS_ALIVE_BIT_MESA); } mtx_unlock(&ctx->ring_mutex); - ret = 0; + + ret = clock_gettime(CLOCK_REALTIME, &abs_ts); + if (ret) + break; + + const uint32_t period_us = ctx->ring_monitor.report_period_us; + const struct timespec rel_ts = { + .tv_sec = period_us / 1000000, + .tv_nsec = (period_us % 1000000) * 1000, + }; + abs_ts = timespec_add(abs_ts, rel_ts); } else if (ret) break; + /* abs_ts is immutable for spurious wakeups */ mtx_lock(&ctx->ring_monitor.mutex); - if ((ret = clock_gettime(CLOCK_REALTIME, &ts))) { - mtx_unlock(&ctx->ring_monitor.mutex); - break; - } - - const uint32_t period_us = ctx->ring_monitor.report_period_us; - ts = timespec_add( - ts, (struct timespec){ period_us / 1000000, (period_us % 1000000) * 1000 }); - ret = cnd_timedwait(&ctx->ring_monitor.cond, &ctx->ring_monitor.mutex, &ts); + ret = cnd_timedwait(&ctx->ring_monitor.cond, &ctx->ring_monitor.mutex, &abs_ts); mtx_unlock(&ctx->ring_monitor.mutex); } From 79ed6bbd43ffbe1b653496e3e41647100b51e694 Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Sat, 7 Mar 2026 10:40:08 -0300 Subject: [PATCH 21/42] server: posix_spawn worker process for macOS Metal On macOS, Metal shader compilation uses XPC (Mach port-based IPC). Pure fork() without exec() inherits stale XPC connections from the parent process, causing Metal to fail silently in worker subprocesses. Use posix_spawn() to create worker processes on macOS. posix_spawn() atomically creates a fresh process image without an intermediate forked state, ensuring valid XPC connections for Metal. POSIX_SPAWN_CLOEXEC_DEFAULT closes all file descriptors by default; only the context fd is explicitly inherited via addinherit_np(). The spawned worker receives its context via command-line arguments (--ctx-fd, --ctx-id, --init-flags, --ctx-name) and enters render_context_main() directly, bypassing the server socket loop. Signed-off-by: Lucas Amaral Part-of: --- server/main.c | 3 ++ server/render_client.c | 3 +- server/render_worker.c | 86 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/server/main.c b/server/main.c index 83f22bc7..3ef5a937 100644 --- a/server/main.c +++ b/server/main.c @@ -23,6 +23,9 @@ * When a worker is a process, * - On Linux, it's a subprocess forked from the server process. It returns * from render_server_main and enters render_context_main. + * - On macOS, the worker is posix_spawn'd with --worker-context-* args. + * render_server_main parses these, skips the server loop, and returns + * with ctx_args.valid set for render_context_main. */ int main(int argc, char **argv) diff --git a/server/render_client.c b/server/render_client.c index 87bab87e..dbb6e0f7 100644 --- a/server/render_client.c +++ b/server/render_client.c @@ -131,7 +131,8 @@ render_client_create_context(struct render_client *client, if (rec->worker) ctx_fd = -1; /* ownership transferred */ #else - rec->worker = render_worker_create(srv->worker_jail, NULL, NULL, 0); + rec->worker = render_worker_create(srv->worker_jail, NULL, + &ctx_args, sizeof(ctx_args)); #endif if (!rec->worker) { render_log("failed to create a context worker"); diff --git a/server/render_worker.c b/server/render_worker.c index 01621cff..b8df351d 100644 --- a/server/render_worker.c +++ b/server/render_worker.c @@ -432,6 +432,83 @@ render_worker_jail_detach_workers(struct render_worker_jail *jail) render_worker_jail_remove_worker(jail, worker); } +#if defined(ENABLE_RENDER_SERVER_WORKER_PROCESS) && defined(__APPLE__) + +#include +#include +#include +#include +#include + +#include "render_context.h" + +/* On macOS, fork() without exec() inherits stale XPC connections + * (Mach port based), breaking Metal shader compilation in worker + * subprocesses. posix_spawn() atomically creates a fresh process + * image without an intermediate forked state. + * + * POSIX_SPAWN_CLOEXEC_DEFAULT closes all fds by default in the child; + * only ctx_fd is explicitly inherited via addinherit_np. + */ + +static pid_t +render_worker_spawn(const struct render_context_args *ctx_args) +{ + /* for devenv without installing server */ + char *const server_path = getenv("RENDER_SERVER_EXEC_PATH"); + const char *exec_path = server_path ? server_path : RENDER_SERVER_EXEC_PATH; + + char fd_str[16]; + char id_str[16]; + char flags_str[16]; + snprintf(fd_str, sizeof(fd_str), "%d", ctx_args->ctx_fd); + snprintf(id_str, sizeof(id_str), "%u", ctx_args->ctx_id); + snprintf(flags_str, sizeof(flags_str), "%u", ctx_args->init_flags); + + char *const argv[] = { + (char *)exec_path, + "--worker-context-fd", + fd_str, + "--worker-context-id", + id_str, + "--worker-context-init-flags", + flags_str, + "--worker-context-name", + (char *)ctx_args->ctx_name, + NULL, + }; + + posix_spawnattr_t attr; + if (posix_spawnattr_init(&attr) != 0) + return -1; + posix_spawnattr_setflags(&attr, POSIX_SPAWN_CLOEXEC_DEFAULT); + + posix_spawn_file_actions_t file_actions; + if (posix_spawn_file_actions_init(&file_actions) != 0) { + posix_spawnattr_destroy(&attr); + return -1; + } + posix_spawn_file_actions_addinherit_np(&file_actions, STDIN_FILENO); + posix_spawn_file_actions_addinherit_np(&file_actions, STDOUT_FILENO); + posix_spawn_file_actions_addinherit_np(&file_actions, STDERR_FILENO); + posix_spawn_file_actions_addinherit_np(&file_actions, ctx_args->ctx_fd); + + pid_t pid; + int ret = posix_spawn(&pid, exec_path, &file_actions, &attr, argv, *_NSGetEnviron()); + + posix_spawn_file_actions_destroy(&file_actions); + posix_spawnattr_destroy(&attr); + + if (ret != 0) { + render_log("posix_spawn failed: %s", strerror(ret)); + return -1; + } + + return pid; +} + +#endif /* ENABLE_RENDER_SERVER_WORKER_PROCESS && __APPLE__ */ + struct render_worker * render_worker_create(struct render_worker_jail *jail, int (*thread_func)(void *thread_data), @@ -451,8 +528,17 @@ render_worker_create(struct render_worker_jail *jail, bool ok; #if defined(ENABLE_RENDER_SERVER_WORKER_PROCESS) +#ifdef __APPLE__ + { + const struct render_context_args *ctx_args = + (const struct render_context_args *)worker->thread_data; + worker->pid = render_worker_spawn(ctx_args); + ok = worker->pid >= 0; + } +#else worker->pid = fork(); ok = worker->pid >= 0; +#endif (void)thread_func; #elif defined(ENABLE_RENDER_SERVER_WORKER_THREAD) ok = thrd_create(&worker->thread, thread_func, worker->thread_data) == thrd_success; From be2ace73dcdfd5be3c884f71ae3d87b199d800f1 Mon Sep 17 00:00:00 2001 From: Sergi Blanch Torne Date: Mon, 23 Mar 2026 16:04:26 +0100 Subject: [PATCH 22/42] ci: Update trace checksums The same issue happened in Mesa https://gitlab.freedesktop.org/mesa/mesa/-/commit/0b51ed736d220be926b39bf76b3f4663cc68de78 Signed-off-by: Sergi Blanch Torne Part-of: --- .gitlab-ci/expectations/virt/traces-virgl.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci/expectations/virt/traces-virgl.yml b/.gitlab-ci/expectations/virt/traces-virgl.yml index c50de53a..7ce54d5a 100644 --- a/.gitlab-ci/expectations/virt/traces-virgl.yml +++ b/.gitlab-ci/expectations/virt/traces-virgl.yml @@ -18,7 +18,7 @@ traces: checksum: 7691e87a06e5c8baf9e0c0ca6381775b 0ad/0ad-v2.trace: gl-virgl: - checksum: 6379222413b517861b70e2550337795e + checksum: 9c91dc2a05e140f8233e7f5f3a4b4f11 gputest/gimark-v2.trace: gl-virgl: label: [crash] @@ -30,7 +30,7 @@ traces: checksum: 837b834310e2e6bd784e3202c6c0bed7 gputest/pixmark-volplosion-v2.trace: gl-virgl: - checksum: d006b8b713db2dc0a968d95dd4ff10b7 + checksum: bcaa3938ca6cdc3a6ac0f4da518ff9a9 gputest/plot3d-v2.trace: gl-virgl: checksum: c4a35b0635bbe3fd6693c33814ff5059 @@ -45,7 +45,7 @@ traces: checksum: fd4fadc9c537e0f10f82c767fc95ff5e humus/DynamicBranching3-v2.trace: gl-virgl: - checksum: b96191174fc9487a8b399fad734cd2e7 + checksum: 401178849862615598c7962f0d497e20 humus/HDR-v2.trace: gl-virgl: checksum: a81ae5282a5d2612f05fc4da2c84e7a0 @@ -81,10 +81,10 @@ traces: checksum: 67161dca3527e5769bc02d84bb9a7bce supertuxkart/supertuxkart-mansion-egl-gles-v2.trace: gl-virgl: - checksum: 1f3b873a320587256d7392ddc8162ae2 + checksum: 0809d2721da25b08f71ab361dac75a7d xonotic/xonotic-keybench-high-v2.trace: gl-virgl: - checksum: 2d2f319615062eb7cc10dfa8d7a66333 + checksum: dc84733cd92584b50dcb7f6b9e57ccce valve/counterstrike-v2.trace: gl-virgl: checksum: 0d32696d18e2cea024a11c252e059002 @@ -94,10 +94,10 @@ traces: label: [skip, flakes] valve/half-life-2-v2.trace: gl-virgl: - checksum: 4299337c370be2523421d17cab387778 + checksum: f88af44c333473dd37661a3da0708226 valve/portal-2-v2.trace: gl-virgl: - checksum: 8974f30da49259a3e5f9ff268e366787 + checksum: 6a793fde53b7d43e28805cfbd48996fa supertuxkart/supertuxkart-antediluvian-abyss.rdc: gl-virgl: label: [crash] @@ -109,7 +109,7 @@ traces: label: [crash] godot/Material Testers.x86_64_2020.04.08_13.38_frame799.rdc: gl-virgl: - checksum: 9855a7ccdab2cd66a59964aba43bf7df + checksum: 7ba4f0c52a719d94b805653d31ce22d7 ror/ror-default.trace: gl-virgl: label: [crash] From 5cfd01b27e24678c01edadfe1239598b0745a3f9 Mon Sep 17 00:00:00 2001 From: Collabora's Gfx CI Team Date: Mon, 23 Mar 2026 14:54:44 +0000 Subject: [PATCH 23/42] Uprev Mesa to cc4492204894c0488e96a93f51b546345ae32f88 https://gitlab.freedesktop.org/mesa/mesa/-/compare/7fc6af99ea4ef86e96b098dcd29a52d33fdd915f...cc4492204894c0488e96a93f51b546345ae32f88 Part-of: --- .gitlab-ci.yml | 4 +- .../expectations/host/virgl-gl-fails.txt | 127 ++++++++++++++++++ .../expectations/host/virgl-gles-fails.txt | 39 +++++- .../expectations/virt/virgl-gl-fails.txt | 38 ++++++ .../expectations/virt/virgl-gles-fails.txt | 40 ++++++ 5 files changed, 245 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bc4e69b0..11ec47ca 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -17,7 +17,7 @@ variables: # # Pick a pipeline on https://gitlab.freedesktop.org/mesa/mesa/-/pipelines/ # - MESA_PIPELINE_ID: 1622883 + MESA_PIPELINE_ID: 1646089 MESA_PROJECT_PATH: mesa/mesa S3_JWT_FILE: /s3_jwt @@ -59,7 +59,7 @@ include: # IMPORTANT: Use a recent Mesa Git revision # The commit ref must be in sync with the pipeline picked above # It can be found on the pipeline page below the commit message - ref: 7fc6af99ea4ef86e96b098dcd29a52d33fdd915f + ref: cc4492204894c0488e96a93f51b546345ae32f88 file: - '/.gitlab-ci/image-tags.yml' diff --git a/.gitlab-ci/expectations/host/virgl-gl-fails.txt b/.gitlab-ci/expectations/host/virgl-gl-fails.txt index 90baf527..a8c6d995 100644 --- a/.gitlab-ci/expectations/host/virgl-gl-fails.txt +++ b/.gitlab-ci/expectations/host/virgl-gl-fails.txt @@ -549,3 +549,130 @@ spec@ext_texture_array@copyteximage 2d_array samples=8,Fail spec@glsl-1.50@execution@variable-indexing@vs-output-array-vec3-index-wr-before-gs,Crash spec@glsl-1.50@execution@variable-indexing@vs-output-array-vec4-index-wr-before-gs,Crash +# uprev Mesa in Virglrenderer +KHR-GL43.gpu_shader_fp64.fp64.named_uniform_blocks,Crash +KHR-GL43.shading_language_420pack.const_dynamic_value,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_double_t2_int,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_double_t2_uint,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_float_t2_float,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_float_t2_int,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_float_t2_uint,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_mat2_t2_mat2,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_mat2x3_t2_mat2x3,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_mat2x4_t2_mat2x4,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec2_t2_ivec2,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec2_t2_uvec2,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec2_t2_vec2,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec3_t2_ivec3,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec3_t2_uvec3,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec3_t2_vec3,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec4_t2_ivec4,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec4_t2_uvec4,Crash +KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec4_t2_vec4,Crash +KHR-GL43.shading_language_420pack.initializer_list_initializer_vector_cols_1_rows_2,Crash +KHR-GL43.shading_language_420pack.initializer_list_initializer_vector_cols_1_rows_3,Crash +KHR-GL43.shading_language_420pack.length_of_vector_and_matrix_type_float_cols_1_rows_3,Crash +KHR-GL43.shading_language_420pack.length_of_vector_and_matrix_type_float_cols_4_rows_2,Crash +KHR-GL43.shading_language_420pack.length_of_vector_and_matrix_type_float_cols_4_rows_3,Crash +KHR-GL43.shading_language_420pack.length_of_vector_and_matrix_type_float_cols_4_rows_4,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_part_string_without_null_termination_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_part_string_without_null_termination_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_part_string_without_null_termination_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_part_string_without_null_termination_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_source_string_without_null_termination_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_source_string_without_null_termination_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_source_string_without_null_termination_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_source_string_without_null_termination_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_between_preprocessor_token_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_between_preprocessor_token_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_between_preprocessor_token_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_between_preprocessor_token_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_comment_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_comment_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_comment_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_comment_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_function_name_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_function_name_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_function_name_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_function_name_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_preprocessor_token_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_preprocessor_token_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_preprocessor_token_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_preprocessor_token_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_type_name_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_type_name_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_type_name_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_type_name_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_variable_name_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_variable_name_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_variable_name_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_variable_name_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_vector_variable_initializer_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_vector_variable_initializer_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_vector_variable_initializer_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_inside_vector_variable_initializer_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_after_assignment_operator_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_after_assignment_operator_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_after_assignment_operator_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_after_assignment_operator_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_assignment_operator_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_assignment_operator_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_assignment_operator_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_assignment_operator_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_of_source_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_of_source_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_of_source_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_of_source_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_string_without_null_termination_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_string_without_null_termination_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_string_without_null_termination_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_string_without_null_termination_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_part_of_source_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_part_of_source_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_part_of_source_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_part_of_source_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_source_repetition_multiple_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_source_repetition_multiple_ending_unix,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_source_repetition_single_ending_dos,Crash +KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_source_repetition_single_ending_unix,Crash +KHR-GL43.shading_language_420pack.qualifier_override_layout,Crash +KHR-GL43.shading_language_420pack.scalar_swizzlers,Crash +spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-max3-float-float-float,Crash +spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-min3-float-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-clamp-float-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec2-vec2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec3-vec3,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-max-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-min-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec2-vec2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec3-vec3,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat3x4-mat3x4-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4,Crash +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-float-index-rd,Crash +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec2-index-rd,Crash +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec3-index-rd,Crash +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec2-index-wr-before-tcs,Crash +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec3-index-wr-before-tcs,Crash +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec4-index-wr-before-tcs,Crash + diff --git a/.gitlab-ci/expectations/host/virgl-gles-fails.txt b/.gitlab-ci/expectations/host/virgl-gles-fails.txt index 9d4b378c..2a07bc18 100644 --- a/.gitlab-ci/expectations/host/virgl-gles-fails.txt +++ b/.gitlab-ci/expectations/host/virgl-gles-fails.txt @@ -3055,7 +3055,6 @@ spec@arb_texture_float@texwrap formats bordercolor-swizzled@GL_RGB16F- swizzled- spec@arb_texture_float@texwrap formats bordercolor@GL_RGB32F- border color only,Fail spec@arb_texture_float@texwrap formats bordercolor@GL_LUMINANCE_ALPHA16F_ARB- border color only,Fail - # uprev Mesa in Virglrenderer spec@!opengl 1.1@depthstencil-default_fb-blit samples=2,Fail spec@!opengl 1.1@depthstencil-default_fb-blit samples=4,Fail @@ -3093,6 +3092,8 @@ spec@!opengl 1.1@depthstencil-default_fb-readpixels-float-and-ushort samples=2,F spec@!opengl 1.1@depthstencil-default_fb-readpixels-float-and-ushort samples=4,Fail spec@!opengl 1.1@depthstencil-default_fb-readpixels-float-and-ushort samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-readpixels-float-and-ushort samples=8,Fail +spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-max3-float-float-float,Crash +spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-min3-float-float-float,Crash spec@arb_copy_image@arb_copy_image-formats --samples=2,Fail spec@arb_copy_image@arb_copy_image-formats --samples=2@Source: GL_ALPHA/Destination: GL_ALPHA,Fail spec@arb_copy_image@arb_copy_image-formats --samples=4,Fail @@ -3136,6 +3137,42 @@ spec@arb_sample_shading@samplemask 8@noms mask_in_one,Fail spec@arb_sample_shading@samplemask 8@noms partition,Fail spec@arb_sample_shading@samplemask 8@sample mask_in_one,Fail spec@arb_spirv_extensions@execution@storage_buffer_storage_class@unsized-array,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-clamp-float-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec2-vec2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec3-vec3,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-max-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-min-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec2-vec2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec3-vec3,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat3x4-mat3x4-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4-using-if,Crash +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4,Crash +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-float-index-rd,Crash +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec2-index-rd,Crash +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec3-index-rd,Crash +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec2-index-wr-before-tcs,Crash +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec3-index-wr-before-tcs,Crash +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec4-index-wr-before-tcs,Crash spec@arb_texture_cube_map@copyteximage cube samples=2,Fail spec@arb_texture_cube_map@copyteximage cube samples=4,Fail spec@arb_texture_cube_map@copyteximage cube samples=6,Fail diff --git a/.gitlab-ci/expectations/virt/virgl-gl-fails.txt b/.gitlab-ci/expectations/virt/virgl-gl-fails.txt index b9ac5d00..70bad6b2 100644 --- a/.gitlab-ci/expectations/virt/virgl-gl-fails.txt +++ b/.gitlab-ci/expectations/virt/virgl-gl-fails.txt @@ -530,12 +530,50 @@ spec@!opengl 1.1@depthstencil-default_fb-drawpixels-24_8 samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-24_8 samples=8,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-32f_24_8_rev samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-32f_24_8_rev samples=8,Fail +spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-max3-float-float-float,Fail +spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-min3-float-float-float,Fail spec@arb_framebuffer_object@execution@msaa-alpha-to-coverage_alpha-to-one_write-z,Fail spec@arb_shader_image_load_store@max-size@image2DMS max size test/8x16384x8x1,Fail spec@arb_shader_image_load_store@max-size@image2DMS max size test/8x8x16384x1,Fail spec@arb_shader_image_load_store@max-size@image2DMSArray max size test/8x8x8x2048,Fail spec@arb_spirv_extensions@execution@storage_buffer_storage_class@unsized-array,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-clamp-float-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec2-vec2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec3-vec3,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-max-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-min-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec2-vec2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec3-vec3,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat3x4-mat3x4-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4,Fail spec@arb_tessellation_shader@execution@tcs-output-unmatched,Fail +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-float-index-rd,Fail +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec2-index-rd,Fail +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec3-index-rd,Fail +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec2-index-wr-before-tcs,Fail +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec3-index-wr-before-tcs,Fail +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec4-index-wr-before-tcs,Fail spec@arb_texture_rectangle@copyteximage rect samples=6,Fail spec@arb_texture_rectangle@copyteximage rect samples=8,Fail spec@egl_ext_device_query_name@conformance,Fail diff --git a/.gitlab-ci/expectations/virt/virgl-gles-fails.txt b/.gitlab-ci/expectations/virt/virgl-gles-fails.txt index 791ccde6..3670f8cd 100644 --- a/.gitlab-ci/expectations/virt/virgl-gles-fails.txt +++ b/.gitlab-ci/expectations/virt/virgl-gles-fails.txt @@ -3097,6 +3097,8 @@ KHR-GL30.framebuffer_blit.framebuffer_blit_functionality_multisampled_to_singles KHR-GL30.texture_lod_bias.texture_lod_bias_all,Fail KHR-GL31.framebuffer_blit.framebuffer_blit_functionality_multisampled_to_singlesampled_blit,Fail KHR-GL32.framebuffer_blit.framebuffer_blit_functionality_multisampled_to_singlesampled_blit,Fail +KHR-GL32.packed_depth_stencil.blit.depth24_stencil8,Fail +KHR-GL32.packed_depth_stencil.blit.depth32f_stencil8,Fail KHR-GL32.texture_lod_bias.texture_lod_bias_all,Fail spec@!opengl 1.1@depthstencil-default_fb-blit samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-blit samples=8,Fail @@ -3108,6 +3110,8 @@ spec@!opengl 1.1@depthstencil-default_fb-drawpixels-32f_24_8_rev samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-32f_24_8_rev samples=8,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-float-and-ushort samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-float-and-ushort samples=8,Fail +spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-max3-float-float-float,Fail +spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-min3-float-float-float,Fail spec@arb_copy_image@arb_copy_image-formats --samples=8,Fail spec@arb_copy_image@arb_copy_image-formats --samples=8@Source: GL_ALPHA/Destination: GL_ALPHA,Fail spec@arb_framebuffer_no_attachments@arb_framebuffer_no_attachments-query@MS8,Fail @@ -3144,6 +3148,42 @@ spec@arb_sample_shading@samplemask 8@noms mask_in_one,Fail spec@arb_sample_shading@samplemask 8@noms partition,Fail spec@arb_sample_shading@samplemask 8@sample mask_in_one,Fail spec@arb_spirv_extensions@execution@storage_buffer_storage_class@unsized-array,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-clamp-float-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec2-vec2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec3-vec3,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-max-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-min-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec2-vec2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec3-vec3,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat3x4-mat3x4-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4-using-if,Fail +spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4,Fail +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-float-index-rd,Fail +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec2-index-rd,Fail +spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec3-index-rd,Fail +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec2-index-wr-before-tcs,Fail +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec3-index-wr-before-tcs,Fail +spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec4-index-wr-before-tcs,Fail spec@egl_ext_device_query_name@conformance,Fail spec@ext_framebuffer_multisample@alpha-to-one-dual-src-blend 6,Fail spec@ext_framebuffer_multisample@alpha-to-one-dual-src-blend 8,Fail From 4e19e9992bc2fe8686fe844666626e03d8ec6e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benno=20F=C3=BCnfst=C3=BCck?= Date: Tue, 14 Apr 2026 12:29:30 +0200 Subject: [PATCH 24/42] renderer: fix cases of wrong cursor orientation If Y_0_TOP is not set, we should not flip the cursor data. Downstream consumers like QEMU expect the returned buffer to be the cursor in a format where y=0 is bottom. This fixes a bug where QEMU renders an inverted mouse cursor if using a gl-accelerated display with certain wayland compositors (for example wl-roots based) in the guest. Part-of: --- src/vrend/vrend_renderer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vrend/vrend_renderer.c b/src/vrend/vrend_renderer.c index 4bf88e09..3a9607a3 100644 --- a/src/vrend/vrend_renderer.c +++ b/src/vrend/vrend_renderer.c @@ -12967,7 +12967,8 @@ void *vrend_renderer_get_cursor_contents(struct pipe_resource *pres, } for (h = 0; h < res->base.height0; h++) { - uint32_t doff = (res->base.height0 - h - 1) * res->base.width0 * blsize; + uint32_t dh = res->y_0_top ? (res->base.height0 - h - 1) : (h); + uint32_t doff = dh * res->base.width0 * blsize; uint32_t soff = h * res->base.width0 * blsize; memcpy(data2 + doff, data + soff, res->base.width0 * blsize); From 23d4e31c9108051f7d5b09250f5959f795216730 Mon Sep 17 00:00:00 2001 From: Julia Zhang Date: Fri, 17 Apr 2026 18:01:22 +0800 Subject: [PATCH 25/42] vrend: free sync thread before fences on init failure When vrend_renderer_init() hits cleanup_and_fail, it calls vrend_renderer_fini(), which in turn calls vrend_free_fences(). vrend_free_fences() asserts that the sync thread has already been freed: qemu-system-i386: ../src/vrend/vrend_renderer.c:7268: vrend_free_fences: Assertion `!vrend_state.sync_thread' failed. This tear sync thread down to avoid above misleading error log. Signed-off-by: Julia Zhang Part-of: --- src/vrend/vrend_renderer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/vrend/vrend_renderer.c b/src/vrend/vrend_renderer.c index 3a9607a3..e3a10e55 100644 --- a/src/vrend/vrend_renderer.c +++ b/src/vrend/vrend_renderer.c @@ -7770,6 +7770,9 @@ int vrend_renderer_init(const struct vrend_if_cbs *cbs, uint32_t flags) return 0; cleanup_and_fail: + if (flags & VREND_USE_THREAD_SYNC) + vrend_free_sync_thread(); + vrend_renderer_fini(); fail: return EINVAL; From d4ffc44e3334884d77aef4123ff6ce6cf5591540 Mon Sep 17 00:00:00 2001 From: Adam Ford Date: Tue, 21 Apr 2026 10:25:53 -0500 Subject: [PATCH 26/42] virglrenderer: check for NULL resource before dereferencing it virgl_renderer_resource_map_fixed() was reading res->fd_type and res->fd into local variables before checking whether virgl_resource_lookup() had returned NULL, so a stale or invalid res_handle from a guest would crash the renderer before the -EINVAL early-return could fire. Move the initialisations below the NULL check so the lookup failure returns cleanly. Signed-off-by: Adam Ford Part-of: --- src/virglrenderer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/virglrenderer.c b/src/virglrenderer.c index 79717fcc..2e64d82e 100644 --- a/src/virglrenderer.c +++ b/src/virglrenderer.c @@ -1298,13 +1298,14 @@ int virgl_renderer_resource_map_fixed(uint32_t res_handle, void *addr) void *map = NULL; struct virgl_context *ctx = NULL; struct virgl_resource *res = virgl_resource_lookup(res_handle); - enum virgl_resource_fd_type fd_type = res->fd_type; - enum virgl_resource_fd_type export_fd_type = res->fd_type; - int fd = res->fd; if (!res) return -EINVAL; + enum virgl_resource_fd_type fd_type = res->fd_type; + enum virgl_resource_fd_type export_fd_type = res->fd_type; + int fd = res->fd; + if (fd_type == VIRGL_RESOURCE_OPAQUE_HANDLE) { ctx = virgl_context_lookup(res->opaque_handle_context_id); if (!ctx) From 85dd6cb2e3fb5db027d71d2ef6db4eb78d161a87 Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Sat, 7 Mar 2026 10:43:25 -0300 Subject: [PATCH 27/42] vkr: add macOS Vulkan library loading Add macOS-specific dynamic library names for Vulkan loading. Try libvulkan.1.dylib and libvulkan.dylib first (Vulkan SDK loader), then fall back to libMoltenVK.dylib (direct MoltenVK usage). Signed-off-by: Lucas Amaral Part-of: --- src/venus/vkr_library.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/venus/vkr_library.c b/src/venus/vkr_library.c index 5cd39962..67d38a56 100644 --- a/src/venus/vkr_library.c +++ b/src/venus/vkr_library.c @@ -4,10 +4,11 @@ */ #include "vkr_common.h" -#include "vkr_library.h" #include +#include "vkr_library.h" + void vkr_library_preload_icd(void) { @@ -41,9 +42,17 @@ vkr_library_load(struct vulkan_library *lib) if (lib->handle) return true; +#ifdef __APPLE__ + lib->handle = dlopen("libvulkan.dylib", RTLD_NOW | RTLD_LOCAL); + if (lib->handle == NULL) + lib->handle = dlopen("libvulkan.1.dylib", RTLD_NOW | RTLD_LOCAL); + if (lib->handle == NULL) + lib->handle = dlopen("libMoltenVK.dylib", RTLD_NOW | RTLD_LOCAL); +#else lib->handle = dlopen("libvulkan.so.1", RTLD_NOW | RTLD_LOCAL); if (lib->handle == NULL) lib->handle = dlopen("libvulkan.so", RTLD_NOW | RTLD_LOCAL); +#endif if (lib->handle == NULL) { vkr_log("failed to open libvulkan: %s", dlerror()); return false; From 161e9fd7fc5e2c9532df8d34b716b2297be9499f Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Sat, 7 Mar 2026 10:45:08 -0300 Subject: [PATCH 28/42] build: add Objective-C, Metal framework, and helper wrappers for macOS Enable Objective-C compilation and link Metal.framework and Foundation.framework on macOS. These are required for the Metal helper wrappers that implement cross-process GPU memory sharing via MTLBuffer. Add vkr_metal_helpers.h/.m with: - vkr_metal_get_device(): retrieve the MTLDevice backing a VkDevice via vkExportMetalObjectsEXT (correct for multi-GPU systems) - vkr_mtl_shm_alloc()/free(): allocate and release Metal shared memory (SHM file + mmap + MTLBuffer) Move the with_host_darwin detection before compiler warning flags so Objective-C arguments can be set alongside C arguments. Signed-off-by: Lucas Amaral Part-of: --- meson.build | 21 ++++++-- src/meson.build | 4 ++ src/venus/vkr_metal_helpers.h | 72 +++++++++++++++++++++++++ src/venus/vkr_metal_helpers.m | 99 +++++++++++++++++++++++++++++++++++ 4 files changed, 193 insertions(+), 3 deletions(-) create mode 100644 src/venus/vkr_metal_helpers.h create mode 100644 src/venus/vkr_metal_helpers.m diff --git a/meson.build b/meson.build index 8e1c0767..5c1ad164 100644 --- a/meson.build +++ b/meson.build @@ -54,6 +54,9 @@ if cc.get_id() == 'gcc' and cc.version().version_compare('< 4.1') error('When using GCC, version 4.1 or later is required.') endif +with_host_windows = host_machine.system() == 'windows' +with_host_darwin = host_machine.system() == 'darwin' + warnings = [ '-Werror=enum-int-mismatch', '-Werror=implicit-function-declaration', @@ -79,9 +82,6 @@ add_project_arguments(cc.get_supported_arguments(flags), language : 'c') prog_python = import('python').find_installation('python3') -with_host_windows = host_machine.system() == 'windows' -with_host_darwin = host_machine.system() == 'darwin' - not_found = dependency('', required: false) gbm_dep = not_found thread_dep = dependency('threads') @@ -349,6 +349,13 @@ with_venus = get_option('venus') with_render_server = with_venus with_render_server_worker = get_option('render-server-worker') render_server_install_dir = get_option('prefix') / get_option('libexecdir') +if with_venus and with_host_darwin + add_languages('objc', required: true) + objcc = meson.get_compiler('objc') + add_project_arguments(objcc.get_supported_arguments(warnings), language : 'objc') + add_project_arguments(objcc.get_supported_arguments(flags), language : 'objc') +endif + if with_venus venus_dep = [] if get_option('vulkan-dload') @@ -368,6 +375,10 @@ if with_venus if with_host_darwin venus_dep += declare_dependency( compile_args : ['-DVK_USE_PLATFORM_METAL_EXT'], + dependencies : [ + dependency('appleframeworks', modules: ['Metal'], required: true), + dependency('appleframeworks', modules: ['Foundation'], required: true), + ], ) endif @@ -424,6 +435,10 @@ configure_file(input : 'config.h.meson', add_project_arguments('-imacros', meson.current_build_dir() / 'config.h', language : 'c') add_project_arguments('-DHAVE_CONFIG_H=1', language : 'c') +if with_venus and with_host_darwin + add_project_arguments('-imacros', meson.current_build_dir() / 'config.h', language : 'objc') + add_project_arguments('-DHAVE_CONFIG_H=1', language : 'objc') +endif inc_configuration = include_directories(['.', 'src']) diff --git a/src/meson.build b/src/meson.build index ed677f38..83eb6173 100644 --- a/src/meson.build +++ b/src/meson.build @@ -200,6 +200,9 @@ if with_venus virgl_sources += venus_sources virgl_sources += venus_codegen virgl_depends += [venus_dep] + if with_host_darwin + virgl_sources += ['venus/vkr_metal_helpers.m'] + endif endif if with_drm_renderers @@ -245,6 +248,7 @@ libvirgl = static_library( virgl_sources, include_directories: [inc_gallium, inc_configuration, 'venus', 'drm'], dependencies : [virgl_depends, drm_uapi_dep], + objc_args : ['-fno-objc-arc'], ) libvirgl_inc = [ diff --git a/src/venus/vkr_metal_helpers.h b/src/venus/vkr_metal_helpers.h new file mode 100644 index 00000000..4f5208bd --- /dev/null +++ b/src/venus/vkr_metal_helpers.h @@ -0,0 +1,72 @@ +/* + * Copyright 2026 Lucas Amaral + * SPDX-License-Identifier: MIT + */ + +#ifndef VKR_METAL_HELPERS_H +#define VKR_METAL_HELPERS_H + +#include + +/* + * Metal shared memory (opaque, allocated/freed in vkr_metal_helpers.m) + */ +struct vkr_mtl_shm { + int shm_fd; + void *shm_ptr; + size_t shm_size; + void *mtl_buffer; +}; + +#ifdef __APPLE__ + +#include + +/* + * Metal helper functions (implemented in vkr_metal_helpers.m) + */ + +/* Return the MTLDevice backing a VkDevice. + * Uses vkExportMetalObjectsEXT to query the device, or NULL on failure. + */ +void * +vkr_metal_get_device(VkDevice vk_device, PFN_vkGetDeviceProcAddr GetDeviceProcAddr); + +/* Allocate Metal shared memory: create anonymous SHM file, mmap it, + * wrap as MTLBuffer. Returns a populated vkr_mtl_shm, or NULL on failure. + * Caller must free with vkr_mtl_shm_free(). + */ +struct vkr_mtl_shm * +vkr_mtl_shm_alloc(void *mtl_device, uint64_t size); + +/* Release all resources held by a vkr_mtl_shm and free the struct. */ +void +vkr_mtl_shm_free(struct vkr_mtl_shm *shm); + +#else /* !__APPLE__ */ + +static inline void * +vkr_metal_get_device(VkDevice vk_device, PFN_vkGetDeviceProcAddr GetDeviceProcAddr) +{ + (void)vk_device; + (void)GetDeviceProcAddr; + return NULL; +} + +static inline struct vkr_mtl_shm * +vkr_mtl_shm_alloc(void *mtl_device, uint64_t size) +{ + (void)mtl_device; + (void)size; + return NULL; +} + +static inline void +vkr_mtl_shm_free(struct vkr_mtl_shm *shm) +{ + (void)shm; +} + +#endif /* __APPLE__ */ + +#endif /* VKR_METAL_HELPERS_H */ diff --git a/src/venus/vkr_metal_helpers.m b/src/venus/vkr_metal_helpers.m new file mode 100644 index 00000000..f0373ed1 --- /dev/null +++ b/src/venus/vkr_metal_helpers.m @@ -0,0 +1,99 @@ +/* + * Copyright 2026 Lucas Amaral + * SPDX-License-Identifier: MIT + */ + +#ifdef __APPLE__ + +#include "vkr_common.h" + +#import +#include +#include +#include + +#include "util/anon_file.h" +#include "venus-protocol/vulkan_metal.h" + +#include "vkr_metal_helpers.h" + +void * +vkr_metal_get_device(VkDevice vk_device, PFN_vkGetDeviceProcAddr GetDeviceProcAddr) +{ + PFN_vkExportMetalObjectsEXT pfn = (PFN_vkExportMetalObjectsEXT)GetDeviceProcAddr( + vk_device, "vkExportMetalObjectsEXT"); + if (!pfn) + return NULL; + + VkExportMetalDeviceInfoEXT device_info = { + .sType = VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT, + }; + VkExportMetalObjectsInfoEXT export_info = { + .sType = VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECTS_INFO_EXT, + .pNext = &device_info, + }; + pfn(vk_device, &export_info); + return (void *)device_info.mtlDevice; +} + +struct vkr_mtl_shm * +vkr_mtl_shm_alloc(void *mtl_device, uint64_t size) +{ + if (!mtl_device) + return NULL; + + const size_t page_size = getpagesize(); + const size_t aligned_size = (size + page_size - 1) & ~(page_size - 1); + + int shm_fd = os_create_anonymous_file(aligned_size, "vkr-metal-mem"); + if (shm_fd < 0) + return NULL; + + void *shm_ptr = + mmap(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + if (shm_ptr == MAP_FAILED) { + close(shm_fd); + return NULL; + } + + id device = (id)mtl_device; + id buffer = [device newBufferWithBytesNoCopy:shm_ptr + length:aligned_size + options:MTLResourceStorageModeShared + deallocator:nil]; + if (!buffer) { + munmap(shm_ptr, aligned_size); + close(shm_fd); + return NULL; + } + + struct vkr_mtl_shm *shm = calloc(1, sizeof(*shm)); + if (!shm) { + CFRelease(buffer); + munmap(shm_ptr, aligned_size); + close(shm_fd); + return NULL; + } + + shm->shm_fd = shm_fd; + shm->shm_ptr = shm_ptr; + shm->shm_size = aligned_size; + shm->mtl_buffer = (void *)buffer; + return shm; +} + +void +vkr_mtl_shm_free(struct vkr_mtl_shm *shm) +{ + if (!shm) + return; + if (shm->mtl_buffer) + CFRelease(shm->mtl_buffer); + if (shm->shm_ptr) + munmap(shm->shm_ptr, shm->shm_size); + if (shm->shm_fd >= 0) + close(shm->shm_fd); + free(shm); +} + +#endif /* __APPLE__ */ From 7812c372fae79cf9b30f879f359916192bcfaf9b Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Tue, 7 Apr 2026 21:36:57 -0300 Subject: [PATCH 29/42] vkr: detect and inject Metal extensions on macOS Detect VK_EXT_external_memory_metal and VK_EXT_metal_objects from MoltenVK's physical device extension list. Skip opaque fd export probing when Metal external memory is available, since MoltenVK does not support opaque fd handles. Inject VK_KHR_external_memory_fd into the guest's view of the physical device extension list so the Mesa Venus driver accepts the device. MoltenVK does not natively support KHR_external_memory_fd; virglrenderer emulates it via Metal buffers backed by POSIX SHM. The injection sets the extension as advertised but does NOT mark physical_dev->KHR_external_memory_fd = true. That flag tracks native host support and is intentionally left false: it gates the host-side vkCreateDevice call, which must not forward KHR_external_memory_fd to MoltenVK (rejected with VK_ERROR_EXTENSION_NOT_PRESENT). Signed-off-by: Lucas Amaral Part-of: --- src/venus/vkr_device.c | 17 +++++++++++++---- src/venus/vkr_physical_device.c | 33 +++++++++++++++++++++++++++++++++ src/venus/vkr_physical_device.h | 3 +++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/venus/vkr_device.c b/src/venus/vkr_device.c index 91441804..79d75b26 100644 --- a/src/venus/vkr_device.c +++ b/src/venus/vkr_device.c @@ -130,6 +130,8 @@ vkr_dispatch_vkCreateDevice(struct vn_dispatch_context *dispatch, /* append extensions for our own use */ const char **exts = NULL; uint32_t ext_count = args->pCreateInfo->enabledExtensionCount; + ext_count += physical_dev->EXT_external_memory_metal; + ext_count += physical_dev->EXT_metal_objects; ext_count += physical_dev->KHR_external_memory_fd; ext_count += physical_dev->EXT_external_memory_dma_buf; ext_count += physical_dev->KHR_external_fence_fd; @@ -139,12 +141,19 @@ vkr_dispatch_vkCreateDevice(struct vn_dispatch_context *dispatch, args->ret = VK_ERROR_OUT_OF_HOST_MEMORY; return; } - for (uint32_t i = 0; i < args->pCreateInfo->enabledExtensionCount; i++) - exts[i] = args->pCreateInfo->ppEnabledExtensionNames[i]; - ext_count = args->pCreateInfo->enabledExtensionCount; + ext_count = 0; + for (uint32_t i = 0; i < args->pCreateInfo->enabledExtensionCount; i++) + exts[ext_count++] = args->pCreateInfo->ppEnabledExtensionNames[i]; + +#ifdef __APPLE__ + if (physical_dev->EXT_external_memory_metal) + exts[ext_count++] = VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME; + if (physical_dev->EXT_metal_objects) + exts[ext_count++] = VK_EXT_METAL_OBJECTS_EXTENSION_NAME; +#endif if (physical_dev->KHR_external_memory_fd) - exts[ext_count++] = "VK_KHR_external_memory_fd"; + exts[ext_count++] = VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME; if (physical_dev->EXT_external_memory_dma_buf) exts[ext_count++] = "VK_EXT_external_memory_dma_buf"; if (physical_dev->KHR_external_fence_fd) diff --git a/src/venus/vkr_physical_device.c b/src/venus/vkr_physical_device.c index 043d5845..40c10968 100644 --- a/src/venus/vkr_physical_device.c +++ b/src/venus/vkr_physical_device.c @@ -282,6 +282,10 @@ vkr_physical_device_init_extensions(struct vkr_physical_device *physical_dev) physical_dev->EXT_external_memory_dma_buf = true; else if (!strcmp(props->extensionName, "VK_KHR_external_fence_fd")) physical_dev->KHR_external_fence_fd = true; + else if (!strcmp(props->extensionName, "VK_EXT_external_memory_metal")) + physical_dev->EXT_external_memory_metal = true; + else if (!strcmp(props->extensionName, "VK_EXT_metal_objects")) + physical_dev->EXT_metal_objects = true; const uint32_t spec_ver = vkr_extension_get_spec_version(props->extensionName); if (spec_ver) { @@ -305,6 +309,35 @@ vkr_physical_device_init_extensions(struct vkr_physical_device *physical_dev) physical_dev->KHR_external_fence_fd = false; } + /* On macOS, VK_KHR_external_memory_fd is emulated via Metal shared memory. + * MoltenVK doesn't natively support it, but virglrenderer implements + * fd-based memory export using Metal buffers backed by POSIX SHM. + * + * Inject it into the advertised list so the guest Venus driver accepts + * the physical device (it's a hard requirement in vn_physical_device.c). + * The guest never enables it in vkCreateDevice — Mesa's Venus driver + * uses the advertised flag for capability detection only. + * + * Do NOT mark physical_dev->KHR_external_memory_fd = true here — that + * flag tracks native MoltenVK support and gates the host-side + * vkCreateDevice extension list (MoltenVK rejects it with -7). + * + * TODO: Remove after mesa!40478 has had sufficient distro uptake. + */ + if (physical_dev->EXT_external_memory_metal && !physical_dev->KHR_external_memory_fd) { + VkExtensionProperties *new_exts = + realloc(exts, sizeof(*exts) * (advertised_count + 1)); + if (new_exts) { + exts = new_exts; + strcpy(new_exts[advertised_count].extensionName, + VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME); + new_exts[advertised_count].specVersion = 0; + advertised_count++; + } else { + vkr_log("failed to inject VK_KHR_external_memory_fd"); + } + } + physical_dev->extensions = realloc(exts, sizeof(*exts) * advertised_count); physical_dev->extension_count = advertised_count; } diff --git a/src/venus/vkr_physical_device.h b/src/venus/vkr_physical_device.h index b0b66918..ca77595b 100644 --- a/src/venus/vkr_physical_device.h +++ b/src/venus/vkr_physical_device.h @@ -27,6 +27,9 @@ struct vkr_physical_device { bool KHR_external_fence_fd; bool KHR_external_semaphore_fd; + bool EXT_external_memory_metal; + bool EXT_metal_objects; + VkPhysicalDeviceMemoryProperties memory_properties; VkPhysicalDeviceIDProperties id_properties; bool is_dma_buf_fd_export_supported; From 15f1669cf0ab368623ee68894b87306ce5cb2e09 Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Mon, 9 Mar 2026 11:08:51 -0300 Subject: [PATCH 30/42] proxy: use fstat for SHM fd size validation lseek() behavior is undefined on POSIX shared memory objects per POSIX.1. On platforms where os_create_anonymous_file() uses shm_open(), lseek() returns -1, breaking the existing size validation. Replace lseek(fd, 0, SEEK_END) with fstat(), which works on all fd types. Also page-align the expected size before comparing, since the server rounds up SHM allocations to page boundaries. Signed-off-by: Lucas Amaral Part-of: --- src/proxy/proxy_context.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/proxy/proxy_context.c b/src/proxy/proxy_context.c index dc23ef58..2780a540 100644 --- a/src/proxy/proxy_context.c +++ b/src/proxy/proxy_context.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "server/render_protocol.h" @@ -310,10 +311,14 @@ validate_resource_fd_shm(int fd, uint64_t expected_size) } #endif - const uint64_t size = lseek(fd, 0, SEEK_END); - if (size != expected_size) { - proxy_log("failed to validate shm size(%" PRIu64 ") expected(%" PRIu64 ")", size, - expected_size); + struct stat st; + if (fstat(fd, &st) < 0) { + proxy_log("failed to fstat shm fd"); + return false; + } + if ((uint64_t)st.st_size < expected_size) { + proxy_log("shm size(%" PRIu64 ") smaller than expected(%" PRIu64 ")", + (uint64_t)st.st_size, expected_size); return false; } From 5488b9c136d9f743ad2542329f408dcc6ad0d42c Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Tue, 7 Apr 2026 21:38:47 -0300 Subject: [PATCH 31/42] anon_file: add macOS shm_open() path macOS lacks memfd_create and SHM_ANON. Add a shm_open() path with random name generation and immediate shm_unlink() to create anonymous shared memory files. Signed-off-by: Lucas Amaral Part-of: --- src/mesa/util/anon_file.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/mesa/util/anon_file.c b/src/mesa/util/anon_file.c index 4f8a5fb1..9963dd00 100644 --- a/src/mesa/util/anon_file.c +++ b/src/mesa/util/anon_file.c @@ -29,12 +29,14 @@ #include "anon_file.h" -#include -#include #include +#include +#include #include +#include -#if defined(HAVE_MEMFD_CREATE) || defined(__FreeBSD__) || defined(__OpenBSD__) +#if defined(HAVE_MEMFD_CREATE) || defined(__FreeBSD__) || \ + defined(__OpenBSD__) || defined(__APPLE__) #include #elif defined(__ANDROID__) #include @@ -43,7 +45,8 @@ #include #endif -#if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || defined(HAVE_MKOSTEMP) || defined(__ANDROID__)) +#if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || \ + defined(HAVE_MKOSTEMP) || defined(__ANDROID__) || defined(__APPLE__)) static int set_cloexec_or_close(int fd) { @@ -67,7 +70,8 @@ set_cloexec_or_close(int fd) } #endif -#if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || defined(__ANDROID__)) +#if !(defined(__FreeBSD__) || defined(HAVE_MEMFD_CREATE) || \ + defined(__ANDROID__) || defined(__APPLE__)) static int create_tmpfile_cloexec(char *tmpname) { @@ -124,6 +128,22 @@ os_create_anonymous_file(off_t size, const char *debug_name) fd = syscall(SYS_memfd_create, debug_name, MFD_CLOEXEC | MFD_ALLOW_SEALING); #elif defined(__FreeBSD__) fd = shm_open(SHM_ANON, O_CREAT | O_RDWR | O_CLOEXEC, 0600); +#elif defined(__APPLE__) + const char *tag = (debug_name && debug_name[0]) ? debug_name : "mesa"; + const unsigned int nonce = arc4random(); + for (unsigned int i = 0; i < 32; i++) { + char shm_name[64]; + snprintf(shm_name, sizeof(shm_name), "/%s-%d-%x-%x", tag, getpid(), nonce, + i); + fd = shm_open(shm_name, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0600); + if (fd >= 0) { + shm_unlink(shm_name); + break; + } + + if (errno != EEXIST) + break; + } #elif defined(__OpenBSD__) char template[] = "/tmp/mesa-XXXXXXXXXX"; fd = shm_mkstemp(template); From e526766d34e0dd7cc0f504f8aa4ad5e88314a15e Mon Sep 17 00:00:00 2001 From: Lucas Amaral Date: Tue, 7 Apr 2026 21:52:52 -0300 Subject: [PATCH 32/42] vkr: implement Metal shared memory allocation on macOS Implement cross-process GPU memory sharing via Metal buffers backed by POSIX shared memory. For HOST_VISIBLE allocations on macOS, allocate a page-aligned SHM file, mmap it, wrap as MTLBuffer using the cached vkr_device->mtl_device, and import into Vulkan via VK_EXT_external_memory_metal. The SHM fd is exported as VIRGL_RESOURCE_FD_SHM for the VMM to map into the guest address space. Cache the MTLDevice in struct vkr_device at vkCreateDevice time via vkExportMetalObjectsEXT, which returns the exact MTLDevice backing the VkPhysicalDevice (correct for multi-GPU systems). Page-align SHM allocation in vkr_context_create_resource_from_shm() for hv_vm_map alignment. Signed-off-by: Lucas Amaral Part-of: --- src/venus/vkr_context.c | 14 ++++++++---- src/venus/vkr_device.c | 5 +++++ src/venus/vkr_device.h | 2 ++ src/venus/vkr_device_memory.c | 41 +++++++++++++++++++++++++++++++++++ src/venus/vkr_device_memory.h | 4 ++++ 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/venus/vkr_context.c b/src/venus/vkr_context.c index 2704bfd8..2ea58988 100644 --- a/src/venus/vkr_context.c +++ b/src/venus/vkr_context.c @@ -282,19 +282,25 @@ vkr_context_create_resource_from_shm(struct vkr_context *ctx, { assert(!vkr_context_get_resource(ctx, res_id)); - int fd = os_create_anonymous_file(blob_size, "vkr-shmem"); + /* Round up to host page size. The VMM maps this resource with + * MAP_FIXED which requires page-aligned sizes. + */ + const size_t page_size = getpagesize(); + const uint64_t alloc_size = (blob_size + page_size - 1) & ~(page_size - 1); + + int fd = os_create_anonymous_file(alloc_size, "vkr-shmem"); if (fd < 0) return false; - void *mmap_ptr = mmap(NULL, blob_size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); + void *mmap_ptr = mmap(NULL, alloc_size, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0); if (mmap_ptr == MAP_FAILED) { close(fd); return false; } - if (!vkr_context_import_resource_internal(ctx, res_id, blob_size, + if (!vkr_context_import_resource_internal(ctx, res_id, alloc_size, VIRGL_RESOURCE_FD_SHM, -1, mmap_ptr)) { - munmap(mmap_ptr, blob_size); + munmap(mmap_ptr, alloc_size); close(fd); return false; } diff --git a/src/venus/vkr_device.c b/src/venus/vkr_device.c index 79d75b26..b17bcbb9 100644 --- a/src/venus/vkr_device.c +++ b/src/venus/vkr_device.c @@ -11,6 +11,7 @@ #include "vkr_context.h" #include "vkr_descriptor_set.h" #include "vkr_device_memory.h" +#include "vkr_metal_helpers.h" #include "vkr_physical_device.h" #include "vkr_queue.h" @@ -186,6 +187,10 @@ vkr_dispatch_vkCreateDevice(struct vn_dispatch_context *dispatch, args->pCreateInfo->ppEnabledExtensionNames, args->pCreateInfo->enabledExtensionCount); + if (physical_dev->EXT_external_memory_metal) + dev->mtl_device = + vkr_metal_get_device(dev->base.handle.device, vk->GetDeviceProcAddr); + free(exts); args->ret = vkr_device_create_queues(ctx, dev, args->pCreateInfo->queueCreateInfoCount, diff --git a/src/venus/vkr_device.h b/src/venus/vkr_device.h index 189df6f5..f7de555c 100644 --- a/src/venus/vkr_device.h +++ b/src/venus/vkr_device.h @@ -26,6 +26,8 @@ struct vkr_device { mtx_t object_mutex; struct list_head objects; + + void *mtl_device; }; VKR_DEFINE_OBJECT_CAST(device, VK_OBJECT_TYPE_DEVICE, VkDevice) diff --git a/src/venus/vkr_device_memory.c b/src/venus/vkr_device_memory.c index d0f29419..9a94d25d 100644 --- a/src/venus/vkr_device_memory.c +++ b/src/venus/vkr_device_memory.c @@ -10,6 +10,7 @@ #include "venus-protocol/vn_protocol_renderer_transport.h" #include "vkr_device_memory_gen.h" +#include "vkr_metal_helpers.h" #include "vkr_physical_device.h" static bool @@ -297,6 +298,33 @@ vkr_dispatch_vkAllocateMemory(struct vn_dispatch_context *dispatch, int udmabuf_fd = -1; void *gbm_bo = NULL; VkExportMemoryAllocateInfo local_export_info; + + /* macOS: use shared memory + Metal buffer for HOST_VISIBLE cross-process sharing. */ + struct vkr_mtl_shm *mtl_shm = NULL; +#ifdef VK_EXT_external_memory_metal + VkImportMemoryMetalHandleInfoEXT local_metal_import = { + .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT, + }; + + if ((property_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && + physical_dev->EXT_external_memory_metal && !res_info) { + assert(!res_info); + mtl_shm = vkr_mtl_shm_alloc(dev->mtl_device, alloc_info->allocationSize); + if (!mtl_shm) { + args->ret = VK_ERROR_OUT_OF_HOST_MEMORY; + return; + } + + /* Chain Metal import into alloc_info */ + local_metal_import.pNext = alloc_info->pNext; + local_metal_import.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_EXT; + local_metal_import.handle = mtl_shm->mtl_buffer; + alloc_info->pNext = &local_metal_import; + alloc_info->allocationSize = mtl_shm->shm_size; + + valid_fd_types = 1 << VIRGL_RESOURCE_FD_SHM; + } else +#endif if ((property_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && !res_info) { /* An implementation can support dma_buf import along with opaque fd export/import. * If the client driver is using external memory and requesting dma_buf, without @@ -388,6 +416,7 @@ vkr_dispatch_vkAllocateMemory(struct vn_dispatch_context *dispatch, close(local_import_info.fd); if (gbm_bo) vkr_gbm_bo_destroy(gbm_bo); + vkr_mtl_shm_free(mtl_shm); return; } @@ -397,6 +426,7 @@ vkr_dispatch_vkAllocateMemory(struct vn_dispatch_context *dispatch, mem->valid_fd_types = valid_fd_types; mem->udmabuf_fd = udmabuf_fd; mem->gbm_bo = gbm_bo; + mem->mtl_shm = mtl_shm; mem->allocation_size = alloc_info->allocationSize; mem->memory_type_index = mem_type_index; } @@ -505,6 +535,7 @@ vkr_context_init_device_memory_dispatch(struct vkr_context *ctx) void vkr_device_memory_release(struct vkr_device_memory *mem) { + vkr_mtl_shm_free(mem->mtl_shm); if (mem->gbm_bo) vkr_gbm_bo_destroy(mem->gbm_bo); if (mem->udmabuf_fd >= 0) @@ -542,6 +573,16 @@ vkr_device_memory_export_blob(struct vkr_device_memory *mem, : VIRGL_RENDERER_MAP_CACHE_WC; } + if (mem->mtl_shm && mem->mtl_shm->shm_fd >= 0) { + mem->exported = true; + *out_blob = (struct virgl_context_blob){ + .type = VIRGL_RESOURCE_FD_SHM, + .u.fd = os_dupfd_cloexec(mem->mtl_shm->shm_fd), + .map_info = map_info, + }; + return out_blob->u.fd >= 0; + } + const bool can_export_dma_buf = mem->valid_fd_types & (1 << VIRGL_RESOURCE_FD_DMABUF); const bool can_export_opaque = mem->valid_fd_types & (1 << VIRGL_RESOURCE_FD_OPAQUE); enum virgl_resource_fd_type fd_type; diff --git a/src/venus/vkr_device_memory.h b/src/venus/vkr_device_memory.h index 6e4e12e7..32599664 100644 --- a/src/venus/vkr_device_memory.h +++ b/src/venus/vkr_device_memory.h @@ -9,6 +9,7 @@ #include "vkr_common.h" struct gbm_bo; +struct vkr_mtl_shm; struct vkr_device_memory { struct vkr_object base; @@ -26,6 +27,9 @@ struct vkr_device_memory { /* udmabuf backing non-external mappable memory */ int udmabuf_fd; + /* Metal buffer backed by POSIX shared memory */ + struct vkr_mtl_shm *mtl_shm; + uint64_t allocation_size; uint32_t memory_type_index; From 8263ab2835a00ecc4d3e538cfb61dcda2a0877c2 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Fri, 24 Apr 2026 09:10:11 -0700 Subject: [PATCH 33/42] vkr: assign vkr_allocator.instance when instance creation succeeds When vkCreateInstance fails, the passed VkInstance handle might become non-NULL, which is allowed by the spec. Passing an invalid non-NULL handle to vkDestroyInstance violates the spec, whereas NULL is allowed. Part-of: --- src/venus/vkr_allocator.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/venus/vkr_allocator.c b/src/venus/vkr_allocator.c index ed250833..d104b892 100644 --- a/src/venus/vkr_allocator.c +++ b/src/venus/vkr_allocator.c @@ -242,12 +242,14 @@ vkr_allocator_init(void) .pApplicationInfo = &app_info, }; + VkInstance inst_handle; vk->CreateInstance = (PFN_vkCreateInstance)get_proc_addr(VK_NULL_HANDLE, "vkCreateInstance"); - res = vk->CreateInstance(&inst_info, NULL, &vkr_allocator.instance); + res = vk->CreateInstance(&inst_info, NULL, &inst_handle); if (res != VK_SUCCESS) goto fail; + vkr_allocator.instance = inst_handle; vkr_allocator_inst_proc_table_init(vkr_allocator.instance, get_proc_addr, vk); vkr_allocator.device_count = VKR_ALLOCATOR_MAX_DEVICE_COUNT; From 05e53389d593e8e5b9cf8f756695d0022389e49e Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Wed, 29 Apr 2026 16:49:01 +0200 Subject: [PATCH 34/42] vrend/shader: Don't emit precise/invariant TCS predefined block outputs The temp variables are all marked precise and assigning to the output is usually a indirect mopve in this case, so we should be good here and it avoids creating broken glsl. Closes: https://gitlab.freedesktop.org/virgl/virglrenderer/-/work_items/650 Signed-off-by: Gert Wollny Part-of: --- src/vrend/vrend_shader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/vrend/vrend_shader.c b/src/vrend/vrend_shader.c index 6a26fdfe..d4e815b6 100644 --- a/src/vrend/vrend_shader.c +++ b/src/vrend/vrend_shader.c @@ -7570,7 +7570,8 @@ static void emit_ios_tcs(const struct dump_ctx *ctx, ctx->separable_program); } else emit_ios_generic(ctx, glsl_strbufs, generic_ios, texcoord_ios, io_out, "", &ctx->outputs[i], "out", "[]"); - } else if (ctx->outputs[i].invariant || ctx->outputs[i].precise) { + } else if ((ctx->outputs[i].invariant || ctx->outputs[i].precise) && + !ctx->outputs[i].glsl_gl_block) { emit_hdrf(glsl_strbufs, "%s%s;\n", ctx->outputs[i].precise ? "precise " : (ctx->outputs[i].invariant ? "invariant " : ""), From b52cbefdd6ec9f583ee6adc60b008a6b2bb73ec1 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Thu, 30 Apr 2026 02:33:09 +0300 Subject: [PATCH 35/42] ci: Update virgl expectations Remove fails that are fixed now. Signed-off-by: Dmitry Osipenko Part-of: --- .../expectations/host/virgl-gl-fails.txt | 127 ------------------ .../expectations/host/virgl-gles-fails.txt | 39 +----- .../expectations/virt/virgl-gl-fails.txt | 38 ------ .../expectations/virt/virgl-gles-fails.txt | 38 ------ 4 files changed, 1 insertion(+), 241 deletions(-) diff --git a/.gitlab-ci/expectations/host/virgl-gl-fails.txt b/.gitlab-ci/expectations/host/virgl-gl-fails.txt index a8c6d995..90baf527 100644 --- a/.gitlab-ci/expectations/host/virgl-gl-fails.txt +++ b/.gitlab-ci/expectations/host/virgl-gl-fails.txt @@ -549,130 +549,3 @@ spec@ext_texture_array@copyteximage 2d_array samples=8,Fail spec@glsl-1.50@execution@variable-indexing@vs-output-array-vec3-index-wr-before-gs,Crash spec@glsl-1.50@execution@variable-indexing@vs-output-array-vec4-index-wr-before-gs,Crash -# uprev Mesa in Virglrenderer -KHR-GL43.gpu_shader_fp64.fp64.named_uniform_blocks,Crash -KHR-GL43.shading_language_420pack.const_dynamic_value,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_double_t2_int,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_double_t2_uint,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_float_t2_float,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_float_t2_int,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_float_t2_uint,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_mat2_t2_mat2,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_mat2x3_t2_mat2x3,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_mat2x4_t2_mat2x4,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec2_t2_ivec2,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec2_t2_uvec2,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec2_t2_vec2,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec3_t2_ivec3,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec3_t2_uvec3,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec3_t2_vec3,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec4_t2_ivec4,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec4_t2_uvec4,Crash -KHR-GL43.shading_language_420pack.implicit_conversions_case_t1_vec4_t2_vec4,Crash -KHR-GL43.shading_language_420pack.initializer_list_initializer_vector_cols_1_rows_2,Crash -KHR-GL43.shading_language_420pack.initializer_list_initializer_vector_cols_1_rows_3,Crash -KHR-GL43.shading_language_420pack.length_of_vector_and_matrix_type_float_cols_1_rows_3,Crash -KHR-GL43.shading_language_420pack.length_of_vector_and_matrix_type_float_cols_4_rows_2,Crash -KHR-GL43.shading_language_420pack.length_of_vector_and_matrix_type_float_cols_4_rows_3,Crash -KHR-GL43.shading_language_420pack.length_of_vector_and_matrix_type_float_cols_4_rows_4,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_part_string_without_null_termination_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_part_string_without_null_termination_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_part_string_without_null_termination_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_part_string_without_null_termination_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_source_string_without_null_termination_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_source_string_without_null_termination_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_source_string_without_null_termination_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_as_last_character_in_source_string_without_null_termination_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_between_preprocessor_token_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_between_preprocessor_token_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_between_preprocessor_token_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_between_preprocessor_token_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_comment_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_comment_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_comment_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_comment_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_function_name_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_function_name_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_function_name_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_function_name_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_preprocessor_token_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_preprocessor_token_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_preprocessor_token_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_preprocessor_token_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_type_name_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_type_name_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_type_name_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_type_name_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_variable_name_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_variable_name_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_variable_name_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_variable_name_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_vector_variable_initializer_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_vector_variable_initializer_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_vector_variable_initializer_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_inside_vector_variable_initializer_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_after_assignment_operator_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_after_assignment_operator_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_after_assignment_operator_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_after_assignment_operator_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_assignment_operator_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_assignment_operator_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_assignment_operator_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_assignment_operator_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_of_source_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_of_source_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_of_source_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_of_source_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_string_without_null_termination_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_string_without_null_termination_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_string_without_null_termination_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_last_character_in_part_string_without_null_termination_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_part_of_source_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_part_of_source_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_part_of_source_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_part_of_source_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_source_repetition_multiple_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_source_repetition_multiple_ending_unix,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_source_repetition_single_ending_dos,Crash -KHR-GL43.shading_language_420pack.line_continuation_case_just_before_null_terminating_source_repetition_single_ending_unix,Crash -KHR-GL43.shading_language_420pack.qualifier_override_layout,Crash -KHR-GL43.shading_language_420pack.scalar_swizzlers,Crash -spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-max3-float-float-float,Crash -spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-min3-float-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-clamp-float-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec2-vec2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec3-vec3,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-max-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-min-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec2-vec2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec3-vec3,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat3x4-mat3x4-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4,Crash -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-float-index-rd,Crash -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec2-index-rd,Crash -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec3-index-rd,Crash -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec2-index-wr-before-tcs,Crash -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec3-index-wr-before-tcs,Crash -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec4-index-wr-before-tcs,Crash - diff --git a/.gitlab-ci/expectations/host/virgl-gles-fails.txt b/.gitlab-ci/expectations/host/virgl-gles-fails.txt index 2a07bc18..9d4b378c 100644 --- a/.gitlab-ci/expectations/host/virgl-gles-fails.txt +++ b/.gitlab-ci/expectations/host/virgl-gles-fails.txt @@ -3055,6 +3055,7 @@ spec@arb_texture_float@texwrap formats bordercolor-swizzled@GL_RGB16F- swizzled- spec@arb_texture_float@texwrap formats bordercolor@GL_RGB32F- border color only,Fail spec@arb_texture_float@texwrap formats bordercolor@GL_LUMINANCE_ALPHA16F_ARB- border color only,Fail + # uprev Mesa in Virglrenderer spec@!opengl 1.1@depthstencil-default_fb-blit samples=2,Fail spec@!opengl 1.1@depthstencil-default_fb-blit samples=4,Fail @@ -3092,8 +3093,6 @@ spec@!opengl 1.1@depthstencil-default_fb-readpixels-float-and-ushort samples=2,F spec@!opengl 1.1@depthstencil-default_fb-readpixels-float-and-ushort samples=4,Fail spec@!opengl 1.1@depthstencil-default_fb-readpixels-float-and-ushort samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-readpixels-float-and-ushort samples=8,Fail -spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-max3-float-float-float,Crash -spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-min3-float-float-float,Crash spec@arb_copy_image@arb_copy_image-formats --samples=2,Fail spec@arb_copy_image@arb_copy_image-formats --samples=2@Source: GL_ALPHA/Destination: GL_ALPHA,Fail spec@arb_copy_image@arb_copy_image-formats --samples=4,Fail @@ -3137,42 +3136,6 @@ spec@arb_sample_shading@samplemask 8@noms mask_in_one,Fail spec@arb_sample_shading@samplemask 8@noms partition,Fail spec@arb_sample_shading@samplemask 8@sample mask_in_one,Fail spec@arb_spirv_extensions@execution@storage_buffer_storage_class@unsized-array,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-clamp-float-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec2-vec2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec3-vec3,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-max-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-min-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec2-vec2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec3-vec3,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat3x4-mat3x4-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4-using-if,Crash -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4,Crash -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-float-index-rd,Crash -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec2-index-rd,Crash -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec3-index-rd,Crash -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec2-index-wr-before-tcs,Crash -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec3-index-wr-before-tcs,Crash -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec4-index-wr-before-tcs,Crash spec@arb_texture_cube_map@copyteximage cube samples=2,Fail spec@arb_texture_cube_map@copyteximage cube samples=4,Fail spec@arb_texture_cube_map@copyteximage cube samples=6,Fail diff --git a/.gitlab-ci/expectations/virt/virgl-gl-fails.txt b/.gitlab-ci/expectations/virt/virgl-gl-fails.txt index 70bad6b2..b9ac5d00 100644 --- a/.gitlab-ci/expectations/virt/virgl-gl-fails.txt +++ b/.gitlab-ci/expectations/virt/virgl-gl-fails.txt @@ -530,50 +530,12 @@ spec@!opengl 1.1@depthstencil-default_fb-drawpixels-24_8 samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-24_8 samples=8,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-32f_24_8_rev samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-32f_24_8_rev samples=8,Fail -spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-max3-float-float-float,Fail -spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-min3-float-float-float,Fail spec@arb_framebuffer_object@execution@msaa-alpha-to-coverage_alpha-to-one_write-z,Fail spec@arb_shader_image_load_store@max-size@image2DMS max size test/8x16384x8x1,Fail spec@arb_shader_image_load_store@max-size@image2DMS max size test/8x8x16384x1,Fail spec@arb_shader_image_load_store@max-size@image2DMSArray max size test/8x8x8x2048,Fail spec@arb_spirv_extensions@execution@storage_buffer_storage_class@unsized-array,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-clamp-float-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec2-vec2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec3-vec3,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-max-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-min-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec2-vec2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec3-vec3,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat3x4-mat3x4-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4,Fail spec@arb_tessellation_shader@execution@tcs-output-unmatched,Fail -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-float-index-rd,Fail -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec2-index-rd,Fail -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec3-index-rd,Fail -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec2-index-wr-before-tcs,Fail -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec3-index-wr-before-tcs,Fail -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec4-index-wr-before-tcs,Fail spec@arb_texture_rectangle@copyteximage rect samples=6,Fail spec@arb_texture_rectangle@copyteximage rect samples=8,Fail spec@egl_ext_device_query_name@conformance,Fail diff --git a/.gitlab-ci/expectations/virt/virgl-gles-fails.txt b/.gitlab-ci/expectations/virt/virgl-gles-fails.txt index 3670f8cd..8bde4b6f 100644 --- a/.gitlab-ci/expectations/virt/virgl-gles-fails.txt +++ b/.gitlab-ci/expectations/virt/virgl-gles-fails.txt @@ -3110,8 +3110,6 @@ spec@!opengl 1.1@depthstencil-default_fb-drawpixels-32f_24_8_rev samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-32f_24_8_rev samples=8,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-float-and-ushort samples=6,Fail spec@!opengl 1.1@depthstencil-default_fb-drawpixels-float-and-ushort samples=8,Fail -spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-max3-float-float-float,Fail -spec@amd_shader_trinary_minmax@execution@built-in-functions@tcs-min3-float-float-float,Fail spec@arb_copy_image@arb_copy_image-formats --samples=8,Fail spec@arb_copy_image@arb_copy_image-formats --samples=8@Source: GL_ALPHA/Destination: GL_ALPHA,Fail spec@arb_framebuffer_no_attachments@arb_framebuffer_no_attachments-query@MS8,Fail @@ -3148,42 +3146,6 @@ spec@arb_sample_shading@samplemask 8@noms mask_in_one,Fail spec@arb_sample_shading@samplemask 8@noms partition,Fail spec@arb_sample_shading@samplemask 8@sample mask_in_one,Fail spec@arb_spirv_extensions@execution@storage_buffer_storage_class@unsized-array,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-clamp-float-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec2-vec2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-equal-vec3-vec3,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-max-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-min-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec2-vec2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-notequal-vec3-vec3,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat2-mat2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-mat3x4-mat3x4-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec2-vec2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec3-vec3,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-eq-vec4-vec4,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-float-float,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat2-mat2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-mat3x4-mat3x4,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec2-vec2,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec3-vec3,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4-using-if,Fail -spec@arb_tessellation_shader@execution@built-in-functions@tcs-op-ne-vec4-vec4,Fail -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-float-index-rd,Fail -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec2-index-rd,Fail -spec@arb_tessellation_shader@execution@variable-indexing@tcs-input-array-vec3-index-rd,Fail -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec2-index-wr-before-tcs,Fail -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec3-index-wr-before-tcs,Fail -spec@arb_tessellation_shader@execution@variable-indexing@vs-output-array-vec4-index-wr-before-tcs,Fail spec@egl_ext_device_query_name@conformance,Fail spec@ext_framebuffer_multisample@alpha-to-one-dual-src-blend 6,Fail spec@ext_framebuffer_multisample@alpha-to-one-dual-src-blend 8,Fail From 1161d2825c3652918a57fe6f89f556bf274b8872 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 27 Apr 2026 12:34:18 -0700 Subject: [PATCH 36/42] venus: use __APPLE__ guard for consistency Part-of: --- src/venus/vkr_device_memory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/venus/vkr_device_memory.c b/src/venus/vkr_device_memory.c index 9a94d25d..97338b63 100644 --- a/src/venus/vkr_device_memory.c +++ b/src/venus/vkr_device_memory.c @@ -301,7 +301,7 @@ vkr_dispatch_vkAllocateMemory(struct vn_dispatch_context *dispatch, /* macOS: use shared memory + Metal buffer for HOST_VISIBLE cross-process sharing. */ struct vkr_mtl_shm *mtl_shm = NULL; -#ifdef VK_EXT_external_memory_metal +#ifdef __APPLE__ VkImportMemoryMetalHandleInfoEXT local_metal_import = { .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_METAL_HANDLE_INFO_EXT, }; @@ -324,7 +324,7 @@ vkr_dispatch_vkAllocateMemory(struct vn_dispatch_context *dispatch, valid_fd_types = 1 << VIRGL_RESOURCE_FD_SHM; } else -#endif +#endif /* __APPLE__ */ if ((property_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) && !res_info) { /* An implementation can support dma_buf import along with opaque fd export/import. * If the client driver is using external memory and requesting dma_buf, without From 3ca4a779e0a83651bf92090bc3db7d5fdb5ce05e Mon Sep 17 00:00:00 2001 From: osy Date: Fri, 28 Nov 2025 18:47:48 -0800 Subject: [PATCH 37/42] vulkan: add vulkan_beta.h header v2 (zzyiwei): roll the exact header used by venus-protocol Part-of: --- meson.build | 2 +- src/venus/venus-protocol/vulkan_beta.h | 375 +++++++++++++++++++++++++ 2 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 src/venus/venus-protocol/vulkan_beta.h diff --git a/meson.build b/meson.build index 5c1ad164..94d19410 100644 --- a/meson.build +++ b/meson.build @@ -374,7 +374,7 @@ if with_venus if with_host_darwin venus_dep += declare_dependency( - compile_args : ['-DVK_USE_PLATFORM_METAL_EXT'], + compile_args : ['-DVK_USE_PLATFORM_METAL_EXT', '-DVK_ENABLE_BETA_EXTENSIONS'], dependencies : [ dependency('appleframeworks', modules: ['Metal'], required: true), dependency('appleframeworks', modules: ['Foundation'], required: true), diff --git a/src/venus/venus-protocol/vulkan_beta.h b/src/venus/venus-protocol/vulkan_beta.h new file mode 100644 index 00000000..147a3f3c --- /dev/null +++ b/src/venus/venus-protocol/vulkan_beta.h @@ -0,0 +1,375 @@ +#ifndef VULKAN_BETA_H_ +#define VULKAN_BETA_H_ 1 + +/* +** Copyright 2015-2026 The Khronos Group Inc. +** +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* +** This header is generated from the Khronos Vulkan XML API Registry. +** +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// VK_KHR_portability_subset is a preprocessor guard. Do not pass it to API calls. +#define VK_KHR_portability_subset 1 +#define VK_KHR_PORTABILITY_SUBSET_SPEC_VERSION 1 +#define VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME "VK_KHR_portability_subset" +typedef struct VkPhysicalDevicePortabilitySubsetFeaturesKHR { + VkStructureType sType; + void* pNext; + VkBool32 constantAlphaColorBlendFactors; + VkBool32 events; + VkBool32 imageViewFormatReinterpretation; + VkBool32 imageViewFormatSwizzle; + VkBool32 imageView2DOn3DImage; + VkBool32 multisampleArrayImage; + VkBool32 mutableComparisonSamplers; + VkBool32 pointPolygons; + VkBool32 samplerMipLodBias; + VkBool32 separateStencilMaskRef; + VkBool32 shaderSampleRateInterpolationFunctions; + VkBool32 tessellationIsolines; + VkBool32 tessellationPointMode; + VkBool32 triangleFans; + VkBool32 vertexAttributeAccessBeyondStride; +} VkPhysicalDevicePortabilitySubsetFeaturesKHR; + +typedef struct VkPhysicalDevicePortabilitySubsetPropertiesKHR { + VkStructureType sType; + void* pNext; + uint32_t minVertexInputBindingStrideAlignment; +} VkPhysicalDevicePortabilitySubsetPropertiesKHR; + + + +// VK_AMDX_shader_enqueue is a preprocessor guard. Do not pass it to API calls. +#define VK_AMDX_shader_enqueue 1 +#define VK_AMDX_SHADER_ENQUEUE_SPEC_VERSION 2 +#define VK_AMDX_SHADER_ENQUEUE_EXTENSION_NAME "VK_AMDX_shader_enqueue" +#define VK_SHADER_INDEX_UNUSED_AMDX (~0U) +typedef struct VkPhysicalDeviceShaderEnqueueFeaturesAMDX { + VkStructureType sType; + void* pNext; + VkBool32 shaderEnqueue; + VkBool32 shaderMeshEnqueue; +} VkPhysicalDeviceShaderEnqueueFeaturesAMDX; + +typedef struct VkPhysicalDeviceShaderEnqueuePropertiesAMDX { + VkStructureType sType; + void* pNext; + uint32_t maxExecutionGraphDepth; + uint32_t maxExecutionGraphShaderOutputNodes; + uint32_t maxExecutionGraphShaderPayloadSize; + uint32_t maxExecutionGraphShaderPayloadCount; + uint32_t executionGraphDispatchAddressAlignment; + uint32_t maxExecutionGraphWorkgroupCount[3]; + uint32_t maxExecutionGraphWorkgroups; +} VkPhysicalDeviceShaderEnqueuePropertiesAMDX; + +typedef struct VkExecutionGraphPipelineScratchSizeAMDX { + VkStructureType sType; + void* pNext; + VkDeviceSize minSize; + VkDeviceSize maxSize; + VkDeviceSize sizeGranularity; +} VkExecutionGraphPipelineScratchSizeAMDX; + +typedef struct VkExecutionGraphPipelineCreateInfoAMDX { + VkStructureType sType; + const void* pNext; + VkPipelineCreateFlags flags; + uint32_t stageCount; + const VkPipelineShaderStageCreateInfo* pStages; + const VkPipelineLibraryCreateInfoKHR* pLibraryInfo; + VkPipelineLayout layout; + VkPipeline basePipelineHandle; + int32_t basePipelineIndex; +} VkExecutionGraphPipelineCreateInfoAMDX; + +typedef union VkDeviceOrHostAddressConstAMDX { + VkDeviceAddress deviceAddress; + const void* hostAddress; +} VkDeviceOrHostAddressConstAMDX; + +typedef struct VkDispatchGraphInfoAMDX { + uint32_t nodeIndex; + uint32_t payloadCount; + VkDeviceOrHostAddressConstAMDX payloads; + uint64_t payloadStride; +} VkDispatchGraphInfoAMDX; + +typedef struct VkDispatchGraphCountInfoAMDX { + uint32_t count; + VkDeviceOrHostAddressConstAMDX infos; + uint64_t stride; +} VkDispatchGraphCountInfoAMDX; + +typedef struct VkPipelineShaderStageNodeCreateInfoAMDX { + VkStructureType sType; + const void* pNext; + const char* pName; + uint32_t index; +} VkPipelineShaderStageNodeCreateInfoAMDX; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateExecutionGraphPipelinesAMDX)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines); +typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineScratchSizeAMDX)(VkDevice device, VkPipeline executionGraph, VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); +typedef VkResult (VKAPI_PTR *PFN_vkGetExecutionGraphPipelineNodeIndexAMDX)(VkDevice device, VkPipeline executionGraph, const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, uint32_t* pNodeIndex); +typedef void (VKAPI_PTR *PFN_vkCmdInitializeGraphScratchMemoryAMDX)(VkCommandBuffer commandBuffer, VkPipeline executionGraph, VkDeviceAddress scratch, VkDeviceSize scratchSize); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, const VkDispatchGraphCountInfoAMDX* pCountInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, const VkDispatchGraphCountInfoAMDX* pCountInfo); +typedef void (VKAPI_PTR *PFN_vkCmdDispatchGraphIndirectCountAMDX)(VkCommandBuffer commandBuffer, VkDeviceAddress scratch, VkDeviceSize scratchSize, VkDeviceAddress countInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateExecutionGraphPipelinesAMDX( + VkDevice device, + VkPipelineCache pipelineCache, + uint32_t createInfoCount, + const VkExecutionGraphPipelineCreateInfoAMDX* pCreateInfos, + const VkAllocationCallbacks* pAllocator, + VkPipeline* pPipelines); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineScratchSizeAMDX( + VkDevice device, + VkPipeline executionGraph, + VkExecutionGraphPipelineScratchSizeAMDX* pSizeInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetExecutionGraphPipelineNodeIndexAMDX( + VkDevice device, + VkPipeline executionGraph, + const VkPipelineShaderStageNodeCreateInfoAMDX* pNodeInfo, + uint32_t* pNodeIndex); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdInitializeGraphScratchMemoryAMDX( + VkCommandBuffer commandBuffer, + VkPipeline executionGraph, + VkDeviceAddress scratch, + VkDeviceSize scratchSize); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceSize scratchSize, + const VkDispatchGraphCountInfoAMDX* pCountInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceSize scratchSize, + const VkDispatchGraphCountInfoAMDX* pCountInfo); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdDispatchGraphIndirectCountAMDX( + VkCommandBuffer commandBuffer, + VkDeviceAddress scratch, + VkDeviceSize scratchSize, + VkDeviceAddress countInfo); +#endif +#endif + + +// VK_NV_cuda_kernel_launch is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_cuda_kernel_launch 1 +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaModuleNV) +VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCudaFunctionNV) +#define VK_NV_CUDA_KERNEL_LAUNCH_SPEC_VERSION 2 +#define VK_NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME "VK_NV_cuda_kernel_launch" +typedef struct VkCudaModuleCreateInfoNV { + VkStructureType sType; + const void* pNext; + size_t dataSize; + const void* pData; +} VkCudaModuleCreateInfoNV; + +typedef struct VkCudaFunctionCreateInfoNV { + VkStructureType sType; + const void* pNext; + VkCudaModuleNV module; + const char* pName; +} VkCudaFunctionCreateInfoNV; + +typedef struct VkCudaLaunchInfoNV { + VkStructureType sType; + const void* pNext; + VkCudaFunctionNV function; + uint32_t gridDimX; + uint32_t gridDimY; + uint32_t gridDimZ; + uint32_t blockDimX; + uint32_t blockDimY; + uint32_t blockDimZ; + uint32_t sharedMemBytes; + size_t paramCount; + const void* const * pParams; + size_t extraCount; + const void* const * pExtras; +} VkCudaLaunchInfoNV; + +typedef struct VkPhysicalDeviceCudaKernelLaunchFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 cudaKernelLaunchFeatures; +} VkPhysicalDeviceCudaKernelLaunchFeaturesNV; + +typedef struct VkPhysicalDeviceCudaKernelLaunchPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t computeCapabilityMinor; + uint32_t computeCapabilityMajor; +} VkPhysicalDeviceCudaKernelLaunchPropertiesNV; + +typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaModuleNV)(VkDevice device, const VkCudaModuleCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaModuleNV* pModule); +typedef VkResult (VKAPI_PTR *PFN_vkGetCudaModuleCacheNV)(VkDevice device, VkCudaModuleNV module, size_t* pCacheSize, void* pCacheData); +typedef VkResult (VKAPI_PTR *PFN_vkCreateCudaFunctionNV)(VkDevice device, const VkCudaFunctionCreateInfoNV* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCudaFunctionNV* pFunction); +typedef void (VKAPI_PTR *PFN_vkDestroyCudaModuleNV)(VkDevice device, VkCudaModuleNV module, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkDestroyCudaFunctionNV)(VkDevice device, VkCudaFunctionNV function, const VkAllocationCallbacks* pAllocator); +typedef void (VKAPI_PTR *PFN_vkCmdCudaLaunchKernelNV)(VkCommandBuffer commandBuffer, const VkCudaLaunchInfoNV* pLaunchInfo); + +#ifndef VK_NO_PROTOTYPES +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaModuleNV( + VkDevice device, + const VkCudaModuleCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCudaModuleNV* pModule); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkGetCudaModuleCacheNV( + VkDevice device, + VkCudaModuleNV module, + size_t* pCacheSize, + void* pCacheData); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR VkResult VKAPI_CALL vkCreateCudaFunctionNV( + VkDevice device, + const VkCudaFunctionCreateInfoNV* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkCudaFunctionNV* pFunction); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyCudaModuleNV( + VkDevice device, + VkCudaModuleNV module, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkDestroyCudaFunctionNV( + VkDevice device, + VkCudaFunctionNV function, + const VkAllocationCallbacks* pAllocator); +#endif + +#ifndef VK_ONLY_EXPORTED_PROTOTYPES +VKAPI_ATTR void VKAPI_CALL vkCmdCudaLaunchKernelNV( + VkCommandBuffer commandBuffer, + const VkCudaLaunchInfoNV* pLaunchInfo); +#endif +#endif + + +// VK_NV_displacement_micromap is a preprocessor guard. Do not pass it to API calls. +#define VK_NV_displacement_micromap 1 +#define VK_NV_DISPLACEMENT_MICROMAP_SPEC_VERSION 2 +#define VK_NV_DISPLACEMENT_MICROMAP_EXTENSION_NAME "VK_NV_displacement_micromap" + +typedef enum VkDisplacementMicromapFormatNV { + VK_DISPLACEMENT_MICROMAP_FORMAT_64_TRIANGLES_64_BYTES_NV = 1, + VK_DISPLACEMENT_MICROMAP_FORMAT_256_TRIANGLES_128_BYTES_NV = 2, + VK_DISPLACEMENT_MICROMAP_FORMAT_1024_TRIANGLES_128_BYTES_NV = 3, + VK_DISPLACEMENT_MICROMAP_FORMAT_MAX_ENUM_NV = 0x7FFFFFFF +} VkDisplacementMicromapFormatNV; +typedef struct VkPhysicalDeviceDisplacementMicromapFeaturesNV { + VkStructureType sType; + void* pNext; + VkBool32 displacementMicromap; +} VkPhysicalDeviceDisplacementMicromapFeaturesNV; + +typedef struct VkPhysicalDeviceDisplacementMicromapPropertiesNV { + VkStructureType sType; + void* pNext; + uint32_t maxDisplacementMicromapSubdivisionLevel; +} VkPhysicalDeviceDisplacementMicromapPropertiesNV; + +typedef struct VkAccelerationStructureTrianglesDisplacementMicromapNV { + VkStructureType sType; + void* pNext; + VkFormat displacementBiasAndScaleFormat; + VkFormat displacementVectorFormat; + VkDeviceOrHostAddressConstKHR displacementBiasAndScaleBuffer; + VkDeviceSize displacementBiasAndScaleStride; + VkDeviceOrHostAddressConstKHR displacementVectorBuffer; + VkDeviceSize displacementVectorStride; + VkDeviceOrHostAddressConstKHR displacedMicromapPrimitiveFlags; + VkDeviceSize displacedMicromapPrimitiveFlagsStride; + VkIndexType indexType; + VkDeviceOrHostAddressConstKHR indexBuffer; + VkDeviceSize indexStride; + uint32_t baseTriangle; + uint32_t usageCountsCount; + const VkMicromapUsageEXT* pUsageCounts; + const VkMicromapUsageEXT* const* ppUsageCounts; + VkMicromapEXT micromap; +} VkAccelerationStructureTrianglesDisplacementMicromapNV; + + + +// VK_AMDX_dense_geometry_format is a preprocessor guard. Do not pass it to API calls. +#define VK_AMDX_dense_geometry_format 1 +#define VK_AMDX_DENSE_GEOMETRY_FORMAT_SPEC_VERSION 1 +#define VK_AMDX_DENSE_GEOMETRY_FORMAT_EXTENSION_NAME "VK_AMDX_dense_geometry_format" +#define VK_COMPRESSED_TRIANGLE_FORMAT_DGF1_BYTE_ALIGNMENT_AMDX 128U +#define VK_COMPRESSED_TRIANGLE_FORMAT_DGF1_BYTE_STRIDE_AMDX 128U + +typedef enum VkCompressedTriangleFormatAMDX { + VK_COMPRESSED_TRIANGLE_FORMAT_DGF1_AMDX = 0, + VK_COMPRESSED_TRIANGLE_FORMAT_MAX_ENUM_AMDX = 0x7FFFFFFF +} VkCompressedTriangleFormatAMDX; +typedef struct VkPhysicalDeviceDenseGeometryFormatFeaturesAMDX { + VkStructureType sType; + void* pNext; + VkBool32 denseGeometryFormat; +} VkPhysicalDeviceDenseGeometryFormatFeaturesAMDX; + +typedef struct VkAccelerationStructureDenseGeometryFormatTrianglesDataAMDX { + VkStructureType sType; + const void* pNext; + VkDeviceOrHostAddressConstKHR compressedData; + VkDeviceSize dataSize; + uint32_t numTriangles; + uint32_t numVertices; + uint32_t maxPrimitiveIndex; + uint32_t maxGeometryIndex; + VkCompressedTriangleFormatAMDX format; +} VkAccelerationStructureDenseGeometryFormatTrianglesDataAMDX; + + +#ifdef __cplusplus +} +#endif + +#endif From a2d0553174522ee6b7cd2653c76122e3740876af Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 29 Apr 2026 15:12:28 -0700 Subject: [PATCH 38/42] vkr: add vkr_allocator_global_proc_table_init helper This also adds vkEnumerateInstanceExtensionProperties support to prepare for portability extension support. Part-of: --- src/venus/vkr_allocator.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/venus/vkr_allocator.c b/src/venus/vkr_allocator.c index d104b892..1e118307 100644 --- a/src/venus/vkr_allocator.c +++ b/src/venus/vkr_allocator.c @@ -46,6 +46,7 @@ #define VKR_ALLOCATOR_MAX_DEVICE_COUNT 4 struct vkr_inst_proc_table { + PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; PFN_vkCreateInstance CreateInstance; PFN_vkDestroyInstance DestroyInstance; PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices; @@ -187,6 +188,17 @@ vkr_allocator_fini(void) vkr_allocator_initialized = false; } +static void +vkr_allocator_global_proc_table_init(PFN_vkGetInstanceProcAddr get_proc_addr, + struct vkr_inst_proc_table *vk) +{ +#define VN_GIPA(cmd) (PFN_##cmd) get_proc_addr(VK_NULL_HANDLE, #cmd) + vk->EnumerateInstanceExtensionProperties = + VN_GIPA(vkEnumerateInstanceExtensionProperties); + vk->CreateInstance = VN_GIPA(vkCreateInstance); +#undef VN_GIPA +} + static void vkr_allocator_inst_proc_table_init(VkInstance inst_handle, PFN_vkGetInstanceProcAddr get_proc_addr, @@ -231,6 +243,7 @@ vkr_allocator_init(void) /* Get vkGetInstanceProcAddr from libvulkan */ PFN_vkGetInstanceProcAddr get_proc_addr = vkr_allocator.vulkan_library.GetInstanceProcAddr; + vkr_allocator_global_proc_table_init(get_proc_addr, vk); VkApplicationInfo app_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, @@ -243,8 +256,6 @@ vkr_allocator_init(void) }; VkInstance inst_handle; - vk->CreateInstance = - (PFN_vkCreateInstance)get_proc_addr(VK_NULL_HANDLE, "vkCreateInstance"); res = vk->CreateInstance(&inst_info, NULL, &inst_handle); if (res != VK_SUCCESS) goto fail; From fbc3fe451b3f5c7d7f98cedbe56a72a8a8b8c6cc Mon Sep 17 00:00:00 2001 From: osy Date: Fri, 28 Nov 2025 17:40:28 -0800 Subject: [PATCH 39/42] vkr: support portability enumeration MoltenVK requires loading with `VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` which means that we will detect and load any library with portability enumeration extension. v2 (zzyiwei): - hide portability enumeration enablement behind __APPLE__ - misc refactors and clang-format Part-of: --- src/venus/vkr_allocator.c | 16 ++++++++++++++++ src/venus/vkr_instance.c | 8 ++++++++ src/venus/vkr_library.c | 33 +++++++++++++++++++++++++++++++++ src/venus/vkr_library.h | 4 ++++ 4 files changed, 61 insertions(+) diff --git a/src/venus/vkr_allocator.c b/src/venus/vkr_allocator.c index 1e118307..3461e6ce 100644 --- a/src/venus/vkr_allocator.c +++ b/src/venus/vkr_allocator.c @@ -245,14 +245,30 @@ vkr_allocator_init(void) PFN_vkGetInstanceProcAddr get_proc_addr = vkr_allocator.vulkan_library.GetInstanceProcAddr; vkr_allocator_global_proc_table_init(get_proc_addr, vk); + const char *inst_ext_names[4]; + uint32_t inst_ext_count = 0; + VkInstanceCreateFlags inst_flags = 0; + +#ifdef __APPLE__ + if (vkr_library_has_portability_enumeration( + vk->EnumerateInstanceExtensionProperties)) { + inst_flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + inst_ext_names[inst_ext_count++] = VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME; + } +#endif /* __APPLE__ */ + VkApplicationInfo app_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .apiVersion = VK_API_VERSION_1_1, }; + assert(inst_ext_count <= ARRAY_SIZE(inst_ext_names)); VkInstanceCreateInfo inst_info = { .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + .flags = inst_flags, .pApplicationInfo = &app_info, + .enabledExtensionCount = inst_ext_count, + .ppEnabledExtensionNames = inst_ext_names, }; VkInstance inst_handle; diff --git a/src/venus/vkr_instance.c b/src/venus/vkr_instance.c index a5002a35..27bf2dca 100644 --- a/src/venus/vkr_instance.c +++ b/src/venus/vkr_instance.c @@ -177,6 +177,14 @@ vkr_dispatch_vkCreateInstance(struct vn_dispatch_context *dispatch, create_info->pNext = &messenger_create_info; } +#ifdef __APPLE__ + if (vkr_library_has_portability_enumeration( + vk->EnumerateInstanceExtensionProperties)) { + create_info->flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; + ext_names[ext_count++] = VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME; + } +#endif /* __APPLE__ */ + assert(layer_count <= ARRAY_SIZE(layer_names)); create_info->enabledLayerCount = layer_count; create_info->ppEnabledLayerNames = layer_names; diff --git a/src/venus/vkr_library.c b/src/venus/vkr_library.c index 67d38a56..dc1f42c4 100644 --- a/src/venus/vkr_library.c +++ b/src/venus/vkr_library.c @@ -98,3 +98,36 @@ vkr_library_unload(struct vulkan_library *lib) } #endif /* ENABLE_VULKAN_DLOAD */ + +bool +vkr_library_has_portability_enumeration( + PFN_vkEnumerateInstanceExtensionProperties enum_inst_ext_props) +{ + uint32_t property_count = 0; + VkExtensionProperties *properties; + bool has_portability_enumeration = false; + + VkResult ret = enum_inst_ext_props(NULL, &property_count, NULL); + if (ret != VK_SUCCESS) + return false; + + properties = calloc(property_count, sizeof(*properties)); + if (!properties) + return false; + + ret = enum_inst_ext_props(NULL, &property_count, properties); + if (ret != VK_SUCCESS) { + free(properties); + return false; + } + + for (uint32_t i = 0; i < property_count; i++) { + if (!strcmp(properties[i].extensionName, + VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) { + has_portability_enumeration = true; + break; + } + } + free(properties); + return has_portability_enumeration; +} diff --git a/src/venus/vkr_library.h b/src/venus/vkr_library.h index 718f8918..48e1e09d 100644 --- a/src/venus/vkr_library.h +++ b/src/venus/vkr_library.h @@ -44,4 +44,8 @@ vkr_library_unload(struct vulkan_library *lib) #endif /* ENABLE_VULKAN_DLOAD */ +bool +vkr_library_has_portability_enumeration( + PFN_vkEnumerateInstanceExtensionProperties enum_inst_ext_props); + #endif /* VKR_LIBRARY_H */ From f8a090357bbdbd93c6aa54f45a29ec04d2f3faca Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Wed, 29 Apr 2026 16:28:33 -0700 Subject: [PATCH 40/42] vkr: refactor to drop __APPLE__ guard for extension enablement using raw string drops the dep on the header Part-of: --- src/venus/vkr_device.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/venus/vkr_device.c b/src/venus/vkr_device.c index b17bcbb9..d67f07fa 100644 --- a/src/venus/vkr_device.c +++ b/src/venus/vkr_device.c @@ -147,14 +147,12 @@ vkr_dispatch_vkCreateDevice(struct vn_dispatch_context *dispatch, for (uint32_t i = 0; i < args->pCreateInfo->enabledExtensionCount; i++) exts[ext_count++] = args->pCreateInfo->ppEnabledExtensionNames[i]; -#ifdef __APPLE__ if (physical_dev->EXT_external_memory_metal) - exts[ext_count++] = VK_EXT_EXTERNAL_MEMORY_METAL_EXTENSION_NAME; + exts[ext_count++] = "VK_EXT_external_memory_metal"; if (physical_dev->EXT_metal_objects) - exts[ext_count++] = VK_EXT_METAL_OBJECTS_EXTENSION_NAME; -#endif + exts[ext_count++] = "VK_EXT_metal_objects"; if (physical_dev->KHR_external_memory_fd) - exts[ext_count++] = VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME; + exts[ext_count++] = "VK_KHR_external_memory_fd"; if (physical_dev->EXT_external_memory_dma_buf) exts[ext_count++] = "VK_EXT_external_memory_dma_buf"; if (physical_dev->KHR_external_fence_fd) From 51b9a7cdcf2f859e4980d87dbff056a70bf281c5 Mon Sep 17 00:00:00 2001 From: osy Date: Fri, 28 Nov 2025 18:53:04 -0800 Subject: [PATCH 41/42] vkr: use portability subset extension if available This is required for MoltenVK to work. v2 (zzyiwei): - no extra guard needed since we have it at instance level - misc refactors Part-of: --- src/venus/vkr_device.c | 3 +++ src/venus/vkr_physical_device.c | 2 ++ src/venus/vkr_physical_device.h | 1 + 3 files changed, 6 insertions(+) diff --git a/src/venus/vkr_device.c b/src/venus/vkr_device.c index d67f07fa..3e943bfd 100644 --- a/src/venus/vkr_device.c +++ b/src/venus/vkr_device.c @@ -133,6 +133,7 @@ vkr_dispatch_vkCreateDevice(struct vn_dispatch_context *dispatch, uint32_t ext_count = args->pCreateInfo->enabledExtensionCount; ext_count += physical_dev->EXT_external_memory_metal; ext_count += physical_dev->EXT_metal_objects; + ext_count += physical_dev->KHR_portability_subset; ext_count += physical_dev->KHR_external_memory_fd; ext_count += physical_dev->EXT_external_memory_dma_buf; ext_count += physical_dev->KHR_external_fence_fd; @@ -151,6 +152,8 @@ vkr_dispatch_vkCreateDevice(struct vn_dispatch_context *dispatch, exts[ext_count++] = "VK_EXT_external_memory_metal"; if (physical_dev->EXT_metal_objects) exts[ext_count++] = "VK_EXT_metal_objects"; + if (physical_dev->KHR_portability_subset) + exts[ext_count++] = "VK_KHR_portability_subset"; if (physical_dev->KHR_external_memory_fd) exts[ext_count++] = "VK_KHR_external_memory_fd"; if (physical_dev->EXT_external_memory_dma_buf) diff --git a/src/venus/vkr_physical_device.c b/src/venus/vkr_physical_device.c index 40c10968..65fdf4c4 100644 --- a/src/venus/vkr_physical_device.c +++ b/src/venus/vkr_physical_device.c @@ -286,6 +286,8 @@ vkr_physical_device_init_extensions(struct vkr_physical_device *physical_dev) physical_dev->EXT_external_memory_metal = true; else if (!strcmp(props->extensionName, "VK_EXT_metal_objects")) physical_dev->EXT_metal_objects = true; + else if (!strcmp(props->extensionName, "VK_KHR_portability_subset")) + physical_dev->KHR_portability_subset = true; const uint32_t spec_ver = vkr_extension_get_spec_version(props->extensionName); if (spec_ver) { diff --git a/src/venus/vkr_physical_device.h b/src/venus/vkr_physical_device.h index ca77595b..139b11ad 100644 --- a/src/venus/vkr_physical_device.h +++ b/src/venus/vkr_physical_device.h @@ -23,6 +23,7 @@ struct vkr_physical_device { bool KHR_external_memory_fd; bool EXT_external_memory_dma_buf; + bool KHR_portability_subset; bool KHR_external_fence_fd; bool KHR_external_semaphore_fd; From 37168812546aba59e79eb032d65e150c38ad3996 Mon Sep 17 00:00:00 2001 From: Aaron Ruby Date: Thu, 30 Apr 2026 13:43:43 -0400 Subject: [PATCH 42/42] vrend: Ensure sampler view and framebuffer attachment swizzle conditions match for imported resources Part-of: --- src/vrend/vrend_renderer.c | 49 ++++++++++++++++++++++---------------- src/vrend/vrend_renderer.h | 1 - 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/vrend/vrend_renderer.c b/src/vrend/vrend_renderer.c index e3a10e55..94c75b10 100644 --- a/src/vrend/vrend_renderer.c +++ b/src/vrend/vrend_renderer.c @@ -982,6 +982,13 @@ bool vrend_format_is_bgra(enum virgl_formats format) { format == VIRGL_FORMAT_B8G8R8A8_SRGB); } +static bool +vrend_resource_resource_is_imported(const struct vrend_resource *res) +{ + return has_bit(res->storage_bits, VREND_STORAGE_EGL_IMAGE) || + has_bit(res->storage_bits, VREND_STORAGE_GL_MEMOBJ); +} + static GLuint vrend_resource_get_internal_format_override(const struct vrend_resource *res) { /* Some shared resources imported to guest mesa as EGL images occupy 24bpp instead of more common 32bpp. @@ -1010,25 +1017,17 @@ static GLuint vrend_resource_get_internal_format_override(const struct vrend_res static bool vrend_resource_supports_view(const struct vrend_resource *res, UNUSED enum virgl_formats view_format) { - /* Texture views on eglimage-backed bgr* resources are not supported and - * lead to unexpected format interpretation since internally allocated - * bgr* resources use GL_RGBA8 internal format, while eglimage-backed - * resources use BGRA8, but GL lacks an equivalent internalformat enum. + /* Texture views on imported bgr* resources are not supported and lead to + * unexpected format interpretation since internally allocated bgr* resources + * use GL_RGBA8 internal format, while imported resources use BGRA8, but GL + * lacks an equivalent internalformat enum. * * For views that don't require colorspace conversion, we can add swizzles * instead. For views that do require colorspace conversion, manual srgb * decode/encode is required. */ return !(vrend_format_is_bgra(res->base.format) && - has_bit(res->storage_bits, VREND_STORAGE_EGL_IMAGE)) && - (vrend_resource_get_internal_format_override(res) == GL_NONE); -} - -static inline bool -vrend_resource_needs_redblue_swizzle(struct vrend_resource *res, - enum virgl_formats view_format) -{ - return !vrend_resource_supports_view(res, view_format) && - vrend_format_is_bgra(res->base.format) ^ vrend_format_is_bgra(view_format); + vrend_resource_resource_is_imported(res)) && + (vrend_resource_get_internal_format_override(res) == GL_NONE); } static inline bool @@ -2752,7 +2751,8 @@ int vrend_create_sampler_view(struct vrend_context *ctx, for (enum pipe_swizzle i = 0; i < 4; ++i) view->gl_swizzle[i] = to_gl_swizzle(swizzle[i]); - if (res->is_imported && vrend_format_is_bgra(view->texture->base.format)) { + if (!vrend_resource_supports_view(view->texture, view->format) && + vrend_format_is_bgra(view->format)) { /* Swap R/B channel for vulkan imported texture. */ GLenum tmp = view->gl_swizzle[0]; view->gl_swizzle[0] = view->gl_swizzle[2]; @@ -3130,7 +3130,8 @@ static void vrend_hw_emit_framebuffer_state(struct vrend_sub_context *sub_ctx) * be necessary, e.g. for rgb* views on bgr* resources. Ensure this * happens by adding a shader swizzle to the final write of such surfaces. */ - if (vrend_resource_needs_redblue_swizzle(surf->texture, surf->format)) + if (!vrend_resource_supports_view(surf->texture, surf->format) && + vrend_format_is_bgra(surf->format)) sub_ctx->swizzle_output_rgb_to_bgr |= 1 << i; /* glTextureView() on eglimage-backed bgr* textures for is not supported. @@ -4706,7 +4707,8 @@ static void vrend_clear_prepare(struct vrend_sub_context *sub_ctx, if (surf && vrend_format_is_emulated_alpha(surf->format)) { glClearColor(colorf[3], 0.0, 0.0, 0.0); } else if (surf && - vrend_resource_needs_redblue_swizzle(surf->texture, surf->format)) { + (!vrend_resource_supports_view(surf->texture, surf->format) && + vrend_format_is_bgra(surf->format))) { VREND_DEBUG(dbg_bgra, sub_ctx->parent, "swizzling glClearColor() since rendering surface is an externally-stored BGR* resource\n"); glClearColor(colorf[2], colorf[1], colorf[0], colorf[3]); } else { @@ -10832,6 +10834,14 @@ static GLuint vrend_make_view(struct vrend_resource *res, enum virgl_formats for return view_id; } +static inline bool +vrend_blit_resource_needs_redblue_swizzle(struct vrend_resource *res, + enum virgl_formats view_format) +{ + return !vrend_resource_supports_view(res, view_format) && + vrend_format_is_bgra(res->base.format) ^ vrend_format_is_bgra(view_format); +} + static bool vrend_blit_needs_redblue_swizzle(struct vrend_resource *src_res, struct vrend_resource *dst_res, const struct pipe_blit_info *info) @@ -10839,8 +10849,8 @@ static bool vrend_blit_needs_redblue_swizzle(struct vrend_resource *src_res, /* EGL-backed bgr* resources are always stored with BGR* internal format, * despite Virgl's use of the GL_RGBA8 internal format, so special care must * be taken when determining the swizzling. */ - bool src_needs_swizzle = vrend_resource_needs_redblue_swizzle(src_res, info->src.format); - bool dst_needs_swizzle = vrend_resource_needs_redblue_swizzle(dst_res, info->dst.format); + bool src_needs_swizzle = vrend_blit_resource_needs_redblue_swizzle(src_res, info->src.format); + bool dst_needs_swizzle = vrend_blit_resource_needs_redblue_swizzle(dst_res, info->dst.format); return src_needs_swizzle ^ dst_needs_swizzle; } @@ -13487,7 +13497,6 @@ vrend_renderer_pipe_resource_set_type(struct vrend_context *ctx, glTexParameteri(gr->target, GL_TEXTURE_TILING_EXT, GL_LINEAR_TILING_EXT); glTexStorageMem2DEXT(gr->target, 1, internalformat, width, height, mem_object, 0); glBindTexture(gr->target, 0); - gr->is_imported = true; } res->pipe_resource = &gr->base; } diff --git a/src/vrend/vrend_renderer.h b/src/vrend/vrend_renderer.h index adb1213a..d732e7f1 100644 --- a/src/vrend/vrend_renderer.h +++ b/src/vrend/vrend_renderer.h @@ -114,7 +114,6 @@ struct vrend_resource { uint32_t blob_id; struct list_head head; - bool is_imported; }; #define VIRGL_TEXTURE_NEED_SWIZZLE (1 << 0)