Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3183709
3rdparty/wlroots: expose Vulkan interop helpers
LFRon Jul 17, 2026
fa38fcc
3rdparty/wlroots: batch foreign texture waits on the GPU
LFRon Jul 19, 2026
8e92d0c
3rdparty/wlroots: expose Vulkan backdrop capabilities
LFRon Jul 22, 2026
4c4dcbb
3rdparty/wlroots: batch foreign-texture sampling barriers
LFRon Aug 2, 2026
7426ce2
3rdparty/wlroots: add GPU-side asynchronous staging uploads
LFRon Aug 2, 2026
98a1a18
3rdparty/wlroots: bridge Vulkan texture synchronization
LFRon Aug 13, 2026
75c9dde
3rdparty/wlroots: synchronize preserved color attachments
LFRon Aug 13, 2026
32d8a52
feat(vulkan): integrate Qt Quick with wlroots render buffers
LFRon Aug 13, 2026
0648371
feat(vulkan): wire Treeland policies to the Vulkan renderer
LFRon Aug 13, 2026
57e030e
feat(vulkan): add presentation feedback
LFRon Aug 13, 2026
f3c7dac
feat(vulkan): wait for imported textures on the GPU
LFRon Aug 13, 2026
662b13c
fix(vulkan): read capture frames from wlroots buffers
LFRon Aug 13, 2026
6c7f34b
fix(vulkan): gate wl_drm on implicit DMA-BUF support
LFRon Aug 13, 2026
d99a83d
feat(vulkan): enable DRM hardware cursor
LFRon Aug 13, 2026
aa11fc0
feat(vulkan): batch foreign-texture sampling barriers
LFRon Aug 13, 2026
2208467
feat(vulkan): enable asynchronous staging uploads
LFRon Aug 13, 2026
b4d7134
fix(vulkan): normalize Qt render-pass dependencies
LFRon Aug 13, 2026
371a2d6
feat(vulkan): restore blur effects
LFRon Aug 13, 2026
cb59c5f
docs(waylib): remove stale qwlroots build option
LFRon Aug 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 51 additions & 1 deletion 3rdparty/wlroots/include/render/vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ struct wlr_vk_device {
bool sync_file_import_export;
bool implicit_sync_interop;
bool sampler_ycbcr_conversion;
bool separate_depth_stencil_layouts;

// we only ever need one queue for rendering and transfer commands
uint32_t queue_family;
Expand Down Expand Up @@ -98,6 +99,7 @@ const struct wlr_vk_format *vulkan_get_format_from_drm(uint32_t drm_format);
struct wlr_vk_format_modifier_props {
VkDrmFormatModifierPropertiesEXT props;
VkExtent2D max_extent;
VkExtent2D transfer_src_max_extent;
bool has_mutable_srgb;
};

Expand Down Expand Up @@ -208,6 +210,7 @@ struct wlr_vk_render_buffer {
VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES];
uint32_t mem_count;
VkImage image;
VkImageUsageFlags image_usage;

// Framebuffer and image view for rendering directly onto the buffer image.
// This requires that the image support an _SRGB VkFormat, and does
Expand Down Expand Up @@ -260,6 +263,13 @@ struct wlr_vk_command_buffer {

#define VULKAN_COMMAND_BUFFERS_CAP 64

// Binary semaphore holding an imported foreign-texture DMA-BUF sync_file.
// Reusable once the texture_sync timeline semaphore reaches release_point.
struct wlr_vk_texture_sync_sem {
VkSemaphore semaphore;
uint64_t release_point;
};

// Vulkan wlr_renderer implementation on top of a wlr_vk_device.
struct wlr_vk_renderer {
struct wlr_renderer wlr_renderer;
Expand Down Expand Up @@ -296,6 +306,39 @@ struct wlr_vk_renderer {
VkSemaphore timeline_semaphore;
uint64_t timeline_point;

// Frame-batched waiting on foreign texture DMA-BUF sync_files (Qt/QRhi
// path). Unsignaled sync_files are imported into binary semaphores and
// waited on by a bridge command buffer. Its pipeline barrier extends the
// wait dependency to the later Qt submission on the same queue.
VkSemaphore texture_sync_timeline_semaphore;
uint64_t texture_sync_timeline_point;
struct wl_array texture_sync_semaphores; // struct wlr_vk_texture_sync_sem
struct wl_array texture_sync_pending; // private texture sync wait entries
struct wl_array texture_sync_wait_infos; // VkSemaphoreSubmitInfoKHR scratch
bool texture_sync_batch_active;
bool texture_sync_force_poll; // env WLR_VK_FORCE_SYNC_POLL

// Per-pass batching of foreign-texture acquire/release barriers (Qt/QRhi
// path). Instead of emitting one vkCmdPipelineBarrier per texture, the
// barriers are accumulated while a batch is active and recorded as a
// single call before (acquire phase) or after (release phase) the Qt draw.
struct wl_array texture_acquire_barriers; // VkImageMemoryBarrier
struct wl_array texture_release_barriers; // VkImageMemoryBarrier
bool texture_barrier_batch_active;
bool texture_barrier_batch_release; // current batch is the release phase

// Force the legacy blocking staging-upload path instead of the
// GPU-side asynchronous one (env WLR_VK_FORCE_STAGE_BLOCK).
bool stage_force_block;
// Enable the GPU-side asynchronous staging-upload path. Must only be set
// once the consumer (Qt/QRhi) is confirmed to submit to the same VkQueue,
// since the path relies on the same-queue texture-sync bridge to order the
// upload before the uploaded texture is sampled.
bool stage_async_enabled;
// A stage upload was submitted asynchronously and needs the texture-sync
// bridge barrier before the consumer submits its command buffer.
bool stage_async_needs_bridge;

size_t last_pool_size;
struct wl_list descriptor_pools; // wlr_vk_descriptor_pool.link
struct wl_list render_format_setups; // wlr_vk_render_format_setup.link
Expand Down Expand Up @@ -370,6 +413,13 @@ VkCommandBuffer vulkan_record_stage_cb(struct wlr_vk_renderer *renderer);
// finished execution.
bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer);

// Submits the current stage command buffer without blocking the CPU. The
// staging buffers it used are hidden in the command buffer's stage_buffers
// list and reclaimed once its timeline point is reached. Callers that sample
// the uploaded content must flush the texture-sync bridge and then submit
// their own command buffer to the same queue.
bool vulkan_submit_stage_async(struct wlr_vk_renderer *renderer);

struct wlr_vk_render_pass_texture {
struct wlr_vk_texture *texture;

Expand Down Expand Up @@ -476,7 +526,7 @@ struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture);
VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
const struct wlr_dmabuf_attributes *attribs,
VkDeviceMemory mems[static WLR_DMABUF_MAX_PLANES], uint32_t *n_mems,
bool for_render, bool *using_mutable_srgb);
bool for_render, bool *using_mutable_srgb, VkImageUsageFlags *image_usage);
struct wlr_texture *vulkan_texture_from_buffer(
struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer);
void vulkan_texture_destroy(struct wlr_vk_texture *texture);
Expand Down
58 changes: 53 additions & 5 deletions 3rdparty/wlroots/include/wlr/render/vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct wlr_vk_image_attribs {
VkImage image;
VkImageLayout layout;
VkFormat format;
VkImageUsageFlags usage;
};

struct wlr_renderer *wlr_vk_renderer_create_with_drm_fd(int drm_fd);
Expand All @@ -30,6 +31,9 @@ VkInstance wlr_vk_renderer_get_instance(struct wlr_renderer *renderer);
VkPhysicalDevice wlr_vk_renderer_get_physical_device(struct wlr_renderer *renderer);
VkDevice wlr_vk_renderer_get_device(struct wlr_renderer *renderer);
uint32_t wlr_vk_renderer_get_queue_family(struct wlr_renderer *renderer);
VkQueue wlr_vk_renderer_get_queue(struct wlr_renderer *renderer);
bool wlr_vk_renderer_has_separate_depth_stencil_layouts(
struct wlr_renderer *renderer);

bool wlr_renderer_is_vk(struct wlr_renderer *wlr_renderer);
bool wlr_texture_is_vk(struct wlr_texture *texture);
Expand All @@ -38,15 +42,59 @@ void wlr_vk_texture_get_image_attribs(struct wlr_texture *texture,
struct wlr_vk_image_attribs *attribs);
bool wlr_vk_texture_has_alpha(struct wlr_texture *texture);

/* waylib extensions (not upstream): Qt Quick RHI bridge helpers.
* Reuse wlroots' own wlr_vk_render_buffer (same path as tinywl/scene),
* instead of creating a parallel VkImage import of the scanout dmabuf. */
bool wlr_vk_renderer_prepare_texture_for_sampling(struct wlr_renderer *renderer,
struct wlr_texture *texture, VkCommandBuffer cb,
struct wlr_vk_image_attribs *attribs);
bool wlr_vk_renderer_finish_texture_sampling(struct wlr_renderer *renderer,
struct wlr_texture *texture, VkCommandBuffer cb);

// Collect foreign-texture sync_files while a compositor frame is recorded,
// then submit one semaphore wait with a bridge barrier before the compositor
// command buffer is submitted to the same queue. The barrier extends the wait
// dependency to that later submission. The abort function is idempotent.
bool wlr_vk_renderer_begin_texture_sync_batch(struct wlr_renderer *renderer);
bool wlr_vk_renderer_flush_texture_sync_batch(struct wlr_renderer *renderer);
void wlr_vk_renderer_abort_texture_sync_batch(struct wlr_renderer *renderer);

// Batch the per-texture queue-family-ownership/layout barriers that
// wlr_vk_renderer_prepare_texture_for_sampling() and
// wlr_vk_renderer_finish_texture_sampling() would otherwise emit one at a
// time. Begin a batch (release=false for the pre-draw acquire phase,
// release=true for the post-draw release phase), call prepare/finish for each
// texture, then flush once to record a single vkCmdPipelineBarrier covering
// every accumulated texture. While a batch is active, prepare defers acquire
// barriers and finish defers release barriers; a call belonging to the other
// phase still records immediately so the two phases never mix in one flush.
// abort discards any pending barriers and is idempotent.
bool wlr_vk_renderer_begin_texture_barrier_batch(struct wlr_renderer *renderer,
bool release);
bool wlr_vk_renderer_flush_texture_barrier_batch(struct wlr_renderer *renderer,
VkCommandBuffer cb);
void wlr_vk_renderer_abort_texture_barrier_batch(struct wlr_renderer *renderer);

// Enable the GPU-side asynchronous staging-upload path used for shared-memory
// (CPU-rendered) client buffers. It submits the staging copy without blocking
// the caller and chains the upload through the texture-sync bridge before the
// texture is sampled, so it must only be enabled when the consumer (e.g.
// Qt/QRhi) submits its command buffers to the same VkQueue as the renderer and
// flushes that bridge before submission. When disabled (the default), staging
// uploads use a blocking wait.
void wlr_vk_renderer_set_stage_async_enabled(struct wlr_renderer *renderer,
bool enabled);

bool wlr_vk_renderer_get_render_buffer_attribs(struct wlr_renderer *renderer,
struct wlr_buffer *buffer, struct wlr_vk_image_attribs *attribs);
bool wlr_vk_renderer_record_render_buffer_acquire(struct wlr_renderer *renderer,
struct wlr_buffer *buffer, VkCommandBuffer cb);
bool wlr_vk_renderer_record_render_buffer_release(struct wlr_renderer *renderer,
struct wlr_buffer *buffer, VkCommandBuffer cb, VkImageLayout old_layout);

/* Compatibility names used by the mainline Qt Quick bridge. New waylib code
* should call the wlr_vk_renderer_* variants above directly. */
bool waylib_vk_renderer_get_render_buffer_attribs(struct wlr_renderer *renderer,
struct wlr_buffer *buffer, struct wlr_vk_image_attribs *attribs);
bool waylib_vk_renderer_record_render_buffer_acquire(struct wlr_renderer *renderer,
struct wlr_buffer *buffer, VkCommandBuffer cb);
bool waylib_vk_renderer_record_render_buffer_release(struct wlr_renderer *renderer,
struct wlr_buffer *buffer, VkCommandBuffer cb, VkImageLayout old_layout);
bool waylib_vk_renderer_flush_stage(struct wlr_renderer *renderer);

#endif
17 changes: 17 additions & 0 deletions 3rdparty/wlroots/render/vulkan/pixel_format.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,23 @@ static bool query_modifier_support(struct wlr_vk_device *dev,
}

if (supported) {
// Transfer-source support is optional and must not remove an
// otherwise valid render modifier. Users can inspect the actual
// image usage and fall back when this stricter query fails.
const VkImageUsageFlags transfer_src_usage =
vulkan_render_usage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
const VkFormat variant = p.has_mutable_srgb ?
props->format.vk_srgb : VK_FORMAT_UNDEFINED;
struct wlr_vk_format_modifier_props transfer_src = {0};
const char *transfer_src_errmsg = NULL;
if ((m.drmFormatModifierTilingFeatures &
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) &&
query_modifier_usage_support(dev, props->format.vk,
variant, transfer_src_usage, &m, &transfer_src,
&transfer_src_errmsg)) {
p.transfer_src_max_extent = transfer_src.max_extent;
}

props->dmabuf.render_mods[props->dmabuf.render_mod_count++] = p;
wlr_drm_format_set_add(&dev->dmabuf_render_formats,
props->format.drm, m.drmFormatModifier);
Expand Down
Loading
Loading