[Git][xorg-team/wayland/weston][upstream-experimental] 9 commits: vulkan-renderer: move capture commands before present
Dylan Aïssi (@daissi) <[email protected]> Thu, 09 Jul 2026 08:18:33 +0000
| Newsgroups | gmane.linux.debian.devel.x |
|---|---|
| Message-ID | <[email protected]> |
Dylan Aïssi pushed to branch upstream-experimental at X Strike Force / wayland / weston Commits: a10bff42 by Erico Nunes at 2026-07-01T09:46:58+02:00 vulkan-renderer: move capture commands before present At least for the swapchain output case, it is not allowed by the spec to do anything with the VkImage after it has been passed to vkQueuePresentKHR. Solve this by moving the capture commands to be recorded before the presentation. Signed-off-by: Erico Nunes <[email protected]> - - - - - 054f103c by Erico Nunes at 2026-07-01T09:49:53+02:00 vulkan-renderer: initialize image handle for swapchain outputs This is used in the read pixels path and causes a crash if not initialized. Signed-off-by: Erico Nunes <[email protected]> - - - - - a50dcb9b by Erico Nunes at 2026-07-01T09:49:53+02:00 vulkan-renderer: fix layout for swapchain output capture The capture code should transition from a PRESENT_SRC layout when the output is a swapchain. Signed-off-by: Erico Nunes <[email protected]> - - - - - a8b6adc7 by Erico Nunes at 2026-07-01T09:49:53+02:00 vulkan-renderer: fix read pixels for output with borders The stride and origin of the source buffer may not match the destination buffer for capture. Notably this is the case when capturing a screenshot of a buffer with borders (e.g. wayland backend with decoration). Fix it by adjusting the calculated regions for the capture considering each stride separately. Signed-off-by: Erico Nunes <[email protected]> - - - - - 4418efdb by Daniel Stone at 2026-07-01T15:37:45+01:00 vulkan-renderer: Properly sync texture upload against itself SHM texture uploads follow the same model as GL, where the surface itself owns a single VkBuffer (for staging) and VkImage (for sampling). Every client SHM buffer gets uploaded to this staging buffer and image during flush_damage(). The renderer was diligently inserting the right Vulkan pipeline barriers to avoid any races between output repaint sampling the textures, and damage flush uploading the textures. Given how asynchronous Vulkan is, it was also using a VkFence to protect against itself: placing a fence on the vkQueueSubmit which will be signaled when the VkBuffer -> VkImage copy has finished (so the staging buffer is free for reuse), and then waiting for that before doing more uploads. Unfortunately the wait was after we copied into the VkBuffer's memory map. Fixes flakes in output-damage test, which showed this up really nicely: the first repaint (issued asynchronously with no wait as it was not captured for a screenshot) proceeded, then the second repaint would overwrite it with all cyan (for the second buffer which would get screenshot), as the second texture upload could complete the memcpy into the staging VkBuffer before the first VkBuffer -> VkImage copy had completed. This was visible by noting that the flake could be hidden by taking a screenshot after the first grey-only surface commit - to force a full pipeline stall immediately after repaint - or just a client-side sleep immediately after it. Signed-off-by: Daniel Stone <[email protected]> - - - - - 0819d0a4 by Robert Mader at 2026-07-02T12:55:57+02:00 backend-drm: Tie plane color pipeline support to color-management We currently enable DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE unconditionally, even color-management is not enabled. Unfortunately this disables the legacy COLOR_ENCODING and COLOR_RANGE DRM properties in the kernel, breaking YCbCr offloading in various cases. This is worsened by the fact that the client cap is supported by recent kernels unconditionally, even for drivers without any color pipeline support(1). In the future there will be a color pipeline replacement for the legacy properties(2), which we'll want to use whenever available. However that has neither landed in the kernel nor do we support it Weston yet. Only enable DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE if color-management is enabled for now. 1: https://lore.kernel.org/dri-devel/[email protected]/ 2: https://lore.kernel.org/dri-devel/[email protected]/ Signed-off-by: Robert Mader <[email protected]> - - - - - 5518f8a6 by Marius Vlad at 2026-07-03T12:48:04+02:00 gitlab-ci: Bump libwayland to 1.24 and libdrm to 2.4.130 This former is required to grab wl_display_dispatch_timeout() and the later for DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE. Signed-off-by: Marius Vlad <[email protected]> - - - - - f970a16d by Marius Vlad at 2026-07-07T11:51:11+03:00 build: bump to version 15.0.93 for the RC1 release Signed-off-by: Marius Vlad <[email protected]> - - - - - d853611c by Dylan Aïssi at 2026-07-09T10:10:13+02:00 New upstream version 15.0.93 - - - - - 5 changed files: - .gitlab-ci.yml - .gitlab-ci/build-deps.sh - libweston/backend-drm/kms.c - libweston/renderer-vulkan/vulkan-renderer.c - meson.build Changes: ===================================== .gitlab-ci.yml ===================================== @@ -43,7 +43,7 @@ variables: FDO_UPSTREAM_REPO: wayland/weston FDO_REPO_SUFFIX: "$BUILD_OS-$FDO_DISTRIBUTION_VERSION/$BUILD_ARCH" - FDO_DISTRIBUTION_TAG: '2026-06-15-linux-7.1-mesa-26.1.2' + FDO_DISTRIBUTION_TAG: '2026-07-02-libwayland-1.24-libdrm-2.4.130' include: ===================================== .gitlab-ci/build-deps.sh ===================================== @@ -106,7 +106,7 @@ fdo_log_section_end install_kernel # Build and install Wayland; keep this version in sync with our dependency # in meson.build. fdo_log_section_start_collapsed install_wayland "install_wayland" -git clone --branch 1.22.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland +git clone --branch 1.24.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland cd wayland git show -s HEAD meson setup build --wrap-mode=nofallback -Ddocumentation=false @@ -126,12 +126,10 @@ cd .. rm -rf wayland-protocols fdo_log_section_end install_wayland -# Build and install our own version of libdrm. Debian 11 (bullseye) provides -# libdrm 2.4.104 which doesn't have the IN_FORMATS iterator api, and Mesa -# depends on 2.4.109 as well. -# Bump to 2.4.118 to include DRM_FORMAT_NV{15,20,30} +# Build and install our own version of libdrm. +# 2.4.130 is the first version defining DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE. fdo_log_section_start_collapsed install_libdrm "install_libdrm" -git clone --branch libdrm-2.4.118 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git +git clone --branch libdrm-2.4.130 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git cd drm meson setup build --wrap-mode=nofallback -Dauto_features=disabled \ -Dvc4=disabled -Dfreedreno=disabled -Detnaviv=disabled ===================================== libweston/backend-drm/kms.c ===================================== @@ -2629,8 +2629,20 @@ init_kms_caps(struct drm_device *device) drmSetClientCap(device->kms_device->fd, DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1); #ifdef DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE - ret = drmSetClientCap(device->kms_device->fd, DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE, 1); - device->color_pipeline_supported = (ret == 0); + /* + * color_manager being present at this point implies color-management + * being enabled as the no-op color manager will only be created after + * all backends are loaded. Only enable plane color pipelines in that + * case as there is no color pipeline replacement for the legacy + * COLOR_ENCODING and COLOR_RANGE properties yet. + */ + if (b->compositor->color_manager) { + ret = drmSetClientCap(device->kms_device->fd, + DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE, 1); + device->color_pipeline_supported = (ret == 0); + } else { + device->color_pipeline_supported = false; + } #else device->color_pipeline_supported = false; #endif ===================================== libweston/renderer-vulkan/vulkan-renderer.c ===================================== @@ -1305,14 +1305,17 @@ vulkan_renderer_cmd_end_wait(struct vulkan_renderer *vr, static bool vulkan_renderer_do_read_pixels(struct vulkan_renderer *vr, VkImage color_attachment, + VkImageLayout image_layout, struct vulkan_output_state *vo, const struct pixel_format_info *pixel_format, - void *pixels, int stride, + void *pixels, int dst_stride, + int dst_x, int dst_y, const struct weston_geometry *rect) { VkBuffer dst_buffer; VkDeviceMemory dst_memory; - VkDeviceSize buffer_size = stride * vo->fb_size.height; + int src_stride = vo->fb_size.width * (pixel_format->bpp / 8); + VkDeviceSize buffer_size = src_stride * vo->fb_size.height; VkResult result; create_buffer(vr, buffer_size, @@ -1325,7 +1328,7 @@ vulkan_renderer_do_read_pixels(struct vulkan_renderer *vr, vulkan_renderer_cmd_begin(vr, &cmd_buffer); transition_image_layout(cmd_buffer, color_attachment, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + image_layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED); @@ -1333,13 +1336,13 @@ vulkan_renderer_do_read_pixels(struct vulkan_renderer *vr, copy_sub_image_to_buffer(cmd_buffer, dst_buffer, color_attachment, vo->fb_size.width, vo->fb_size.height, - (stride / (pixel_format->bpp/8)), + vo->fb_size.width, pixel_format->bpp, rect->x, rect->y, rect->width, rect->height); transition_image_layout(cmd_buffer, color_attachment, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, image_layout, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED); @@ -1348,7 +1351,7 @@ vulkan_renderer_do_read_pixels(struct vulkan_renderer *vr, vulkan_renderer_cmd_end_wait(vr, &cmd_buffer); /* Map image memory so we can start copying from it */ - void* buffer_map; + void *buffer_map; result = vkMapMemory(vr->dev, dst_memory, 0, VK_WHOLE_SIZE, 0, &buffer_map); check_vk_success(result, "vkMapMemory"); @@ -1358,12 +1361,12 @@ vulkan_renderer_do_read_pixels(struct vulkan_renderer *vr, pixman_image_t *image_src; image_src = pixman_image_create_bits_no_clear(pixel_format->pixman_format, vo->fb_size.width, vo->fb_size.height, - buffer_map, stride); + buffer_map, src_stride); pixman_image_t *image_dst; image_dst = pixman_image_create_bits_no_clear(pixel_format->pixman_format, - vo->fb_size.width, vo->fb_size.height, - pixels, stride); + rect->width, rect->height, + pixels, dst_stride); pixman_image_composite32(PIXMAN_OP_SRC, image_src, /* src */ @@ -1371,7 +1374,7 @@ vulkan_renderer_do_read_pixels(struct vulkan_renderer *vr, image_dst, /* dest */ rect->x, rect->y, /* src x,y */ 0, 0, /* mask x,y */ - rect->x, rect->y, /* dest x,y */ + dst_x, dst_y, /* dest x,y */ rect->width, rect->height); pixman_image_unref(image_src); @@ -1385,6 +1388,7 @@ vulkan_renderer_do_read_pixels(struct vulkan_renderer *vr, static bool vulkan_renderer_do_capture(struct vulkan_renderer *vr, VkImage color_attachment, + VkImageLayout image_layout, struct vulkan_output_state *vo, struct weston_buffer *into, const struct weston_geometry *rect) @@ -1398,8 +1402,10 @@ vulkan_renderer_do_capture(struct vulkan_renderer *vr, wl_shm_buffer_begin_access(shm); - ret = vulkan_renderer_do_read_pixels(vr, color_attachment, vo, pixel_format, - wl_shm_buffer_get_data(shm), into->stride, rect); + /* This always copies the requested rect into the start + * of the target shm, so dest coords 0,0 */ + ret = vulkan_renderer_do_read_pixels(vr, color_attachment, image_layout, vo, pixel_format, + wl_shm_buffer_get_data(shm), into->stride, 0, 0, rect); wl_shm_buffer_end_access(shm); @@ -1409,6 +1415,7 @@ vulkan_renderer_do_capture(struct vulkan_renderer *vr, static void vulkan_renderer_do_capture_tasks(struct vulkan_renderer *vr, VkImage color_attachment, + VkImageLayout image_layout, struct weston_output *output, enum weston_output_capture_source source) { @@ -1454,7 +1461,8 @@ vulkan_renderer_do_capture_tasks(struct vulkan_renderer *vr, continue; } - if (vulkan_renderer_do_capture(vr, color_attachment, vo, buffer, &rect)) + if (vulkan_renderer_do_capture(vr, color_attachment, image_layout, + vo, buffer, &rect)) weston_capture_task_retire_complete(ct); else weston_capture_task_retire_failed(ct, "Vulkan: capture failed"); @@ -2346,6 +2354,7 @@ vulkan_renderer_create_swapchain(struct weston_output *output, for (uint32_t i = 0; i < vo->image_count; i++) { struct vulkan_renderer_image *im = &vo->images[i]; + im->image = swapchain_images[i]; create_image_view(vr->dev, swapchain_images[i], format, &im->image_view); create_framebuffer(vr->dev, vo->renderpass, im->image_view, @@ -2386,6 +2395,7 @@ vulkan_renderer_repaint_output(struct weston_output *output, struct weston_paint_node *pnode; VkResult result; uint32_t swapchain_index; + VkImageLayout expected_layout; assert(vo); assert(!renderbuffer || @@ -2442,11 +2452,13 @@ vulkan_renderer_repaint_output(struct weston_output *output, im = &vo->images[swapchain_index]; rb = im->renderbuffer; + expected_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; break; case VULKAN_OUTPUT_HEADLESS: assert(renderbuffer); rb = renderbuffer; im = rb->image; + expected_layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; break; default: abort(); @@ -2557,6 +2569,34 @@ vulkan_renderer_repaint_output(struct weston_output *output, result = vkQueueSubmit(vr->queue, 1, &submit_info, fr->fence); check_vk_success(result, "vkQueueSubmit"); + vulkan_renderer_do_capture_tasks(vr, im->image, expected_layout, output, + WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER); + vulkan_renderer_do_capture_tasks(vr, im->image, expected_layout, output, + WESTON_OUTPUT_CAPTURE_SOURCE_FULL_FRAMEBUFFER); + + if (rb->buffer) { + uint32_t *pixels = rb->buffer; + int width = vo->fb_size.width; + int stride = width * (compositor->read_format->bpp >> 3); + pixman_box32_t extents; + + assert(rb->stride == stride); + + extents = weston_matrix_transform_rect(&output->matrix, + rb->damage.extents); + + const struct weston_geometry rect = { + .x = vo->area.x + extents.x1, + .y = vo->area.y + extents.y1, + .width = extents.x2 - extents.x1, + .height = extents.y2 - extents.y1, + }; + + vulkan_renderer_do_read_pixels(vr, im->image, expected_layout, + vo, compositor->read_format, + pixels, stride, rect.x, rect.y, &rect); + } + if (vo->output_type == VULKAN_OUTPUT_SWAPCHAIN) { assert(vulkan_device_has(vr, EXTENSION_KHR_SWAPCHAIN)); @@ -2613,39 +2653,11 @@ vulkan_renderer_repaint_output(struct weston_output *output, fd_update(&vo->render_fence_fd, fd); } - vulkan_renderer_do_capture_tasks(vr, im->image, output, - WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER); - vulkan_renderer_do_capture_tasks(vr, im->image, output, - WESTON_OUTPUT_CAPTURE_SOURCE_FULL_FRAMEBUFFER); - rb->border_status = BORDER_STATUS_CLEAN; vo->border_status = BORDER_STATUS_CLEAN; update_buffer_release_fences(compositor, output); - if (rb->buffer) { - uint32_t *pixels = rb->buffer; - int width = vo->fb_size.width; - int stride = width * (compositor->read_format->bpp >> 3); - pixman_box32_t extents; - - assert(rb->stride == stride); - - extents = weston_matrix_transform_rect(&output->matrix, - rb->damage.extents); - - const struct weston_geometry rect = { - .x = vo->area.x + extents.x1, - .y = vo->area.y + extents.y1, - .width = extents.x2 - extents.x1, - .height = extents.y2 - extents.y1, - }; - - vulkan_renderer_do_read_pixels(vr, im->image, vo, - compositor->read_format, - pixels, stride, &rect); - } - pixman_region32_clear(&rb->damage); vo->frame_index = (vo->frame_index + 1) % vo->num_frames; @@ -2714,13 +2726,13 @@ update_texture_image(struct vulkan_renderer *vr, VkDeviceSize image_size = pitch * buffer_height * (pixel_format->bpp/8); VkResult result; + vkWaitForFences(vr->dev, 1, &texture->upload_fence, VK_TRUE, UINT64_MAX); + vkResetFences(vr->dev, 1, &texture->upload_fence); + assert(pixels); memcpy(texture->staging_map, pixels, (size_t)image_size); - vkWaitForFences(vr->dev, 1, &texture->upload_fence, VK_TRUE, UINT64_MAX); - vkResetFences(vr->dev, 1, &texture->upload_fence); - const VkCommandBufferBeginInfo begin_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, ===================================== meson.build ===================================== @@ -1,6 +1,6 @@ project('weston', ['c', 'cpp'], - version: '15.0.92', + version: '15.0.93', default_options: [ 'warning_level=3', 'c_std=gnu11', View it on GitLab: https://salsa.debian.org/xorg-team/wayland/weston/-/compare/fb163cf52d40f337acec41625547cf32bd2943dc...d853611cb8dd3f140c5243ba67590ee5881fb998 -- View it on GitLab: https://salsa.debian.org/xorg-team/wayland/weston/-/compare/fb163cf52d40f337acec41625547cf32bd2943dc...d853611cb8dd3f140c5243ba67590ee5881fb998 You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help