Merge branch 'vk-shm-upload' into 'master'

Draft: render/vulkan: Delay shm texture updates till render

See merge request wlroots/wlroots!4734
This commit is contained in:
Kenny Levinsen 2025-06-08 00:26:54 +00:00
commit 7283d62058
3 changed files with 51 additions and 15 deletions

View file

@ -11,6 +11,7 @@
#include <wlr/render/interface.h> #include <wlr/render/interface.h>
#include <wlr/util/addon.h> #include <wlr/util/addon.h>
#include "util/rect_union.h" #include "util/rect_union.h"
#include <pixman.h>
struct wlr_vk_descriptor_pool; struct wlr_vk_descriptor_pool;
struct wlr_vk_texture; struct wlr_vk_texture;
@ -469,6 +470,9 @@ struct wlr_vk_texture {
struct wlr_addon buffer_addon; struct wlr_addon buffer_addon;
struct wl_list views; // struct wlr_vk_texture_ds.link struct wl_list views; // struct wlr_vk_texture_ds.link
// For SHM buffers
pixman_region32_t invalidated;
}; };
struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture); struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture);
@ -479,6 +483,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
struct wlr_texture *vulkan_texture_from_buffer( struct wlr_texture *vulkan_texture_from_buffer(
struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer); struct wlr_renderer *wlr_renderer, struct wlr_buffer *buffer);
void vulkan_texture_destroy(struct wlr_vk_texture *texture); void vulkan_texture_destroy(struct wlr_vk_texture *texture);
void vulkan_texture_update(struct wlr_vk_texture *texture);
struct wlr_vk_descriptor_pool { struct wlr_vk_descriptor_pool {
VkDescriptorPool pool; VkDescriptorPool pool;

View file

@ -703,6 +703,8 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
wl_list_insert(&renderer->foreign_textures, &texture->foreign_link); wl_list_insert(&renderer->foreign_textures, &texture->foreign_link);
} }
vulkan_texture_update(texture);
struct wlr_fbox src_box; struct wlr_fbox src_box;
wlr_render_texture_options_get_src_box(options, &src_box); wlr_render_texture_options_get_src_box(options, &src_box);
struct wlr_box dst_box; struct wlr_box dst_box;

View file

@ -153,6 +153,26 @@ static bool write_pixels(struct wlr_vk_texture *texture,
return true; return true;
} }
void vulkan_texture_update(struct wlr_vk_texture *texture) {
if (pixman_region32_empty(&texture->invalidated)) {
return;
}
void *data;
uint32_t format;
size_t stride;
if (wlr_buffer_begin_data_ptr_access(texture->buffer,
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
write_pixels(texture, stride, &texture->invalidated, data, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT);
wlr_buffer_end_data_ptr_access(texture->buffer);
}
pixman_region32_clear(&texture->invalidated);
wlr_buffer_unlock(texture->buffer);
texture->buffer = NULL;
}
static bool vulkan_texture_update_from_buffer(struct wlr_texture *wlr_texture, static bool vulkan_texture_update_from_buffer(struct wlr_texture *wlr_texture,
struct wlr_buffer *buffer, const pixman_region32_t *damage) { struct wlr_buffer *buffer, const pixman_region32_t *damage) {
struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture);
@ -172,8 +192,12 @@ static bool vulkan_texture_update_from_buffer(struct wlr_texture *wlr_texture,
goto out; goto out;
} }
ok = write_pixels(texture, stride, damage, data, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, if (texture->buffer) {
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT); wlr_buffer_unlock(texture->buffer);
}
texture->buffer = wlr_buffer_lock(buffer);
pixman_region32_union(&texture->invalidated, &texture->invalidated, damage);
out: out:
wlr_buffer_end_data_ptr_access(buffer); wlr_buffer_end_data_ptr_access(buffer);
@ -198,6 +222,7 @@ void vulkan_texture_destroy(struct wlr_vk_texture *texture) {
} }
wl_list_remove(&texture->link); wl_list_remove(&texture->link);
pixman_region32_fini(&texture->invalidated);
VkDevice dev = texture->renderer->dev->dev; VkDevice dev = texture->renderer->dev->dev;
@ -219,13 +244,18 @@ void vulkan_texture_destroy(struct wlr_vk_texture *texture) {
static void vulkan_texture_unref(struct wlr_texture *wlr_texture) { static void vulkan_texture_unref(struct wlr_texture *wlr_texture) {
struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture); struct wlr_vk_texture *texture = vulkan_get_texture(wlr_texture);
if (texture->buffer != NULL) { if (texture->buffer) {
wlr_buffer_unlock(texture->buffer);
if (texture->dmabuf_imported) {
// Keep the texture around, in case the buffer is re-used later. We're // Keep the texture around, in case the buffer is re-used later. We're
// still listening to the buffer's destroy event. // still listening to the buffer's destroy event.
wlr_buffer_unlock(texture->buffer); return;
} else {
vulkan_texture_destroy(texture);
} }
// The buffer is temporary and has no add-on, clear it before destroy
texture->buffer = NULL;
}
vulkan_texture_destroy(texture);
} }
static bool vulkan_texture_read_pixels(struct wlr_texture *wlr_texture, static bool vulkan_texture_read_pixels(struct wlr_texture *wlr_texture,
@ -265,6 +295,7 @@ static struct wlr_vk_texture *vulkan_texture_create(
texture->renderer = renderer; texture->renderer = renderer;
wl_list_insert(&renderer->textures, &texture->link); wl_list_insert(&renderer->textures, &texture->link);
wl_list_init(&texture->views); wl_list_init(&texture->views);
pixman_region32_init(&texture->invalidated);
return texture; return texture;
} }
@ -370,9 +401,11 @@ static void texture_set_format(struct wlr_vk_texture *texture,
static struct wlr_texture *vulkan_texture_from_pixels( static struct wlr_texture *vulkan_texture_from_pixels(
struct wlr_vk_renderer *renderer, uint32_t drm_fmt, uint32_t stride, struct wlr_vk_renderer *renderer, uint32_t drm_fmt, uint32_t stride,
uint32_t width, uint32_t height, const void *data) { struct wlr_buffer *buffer) {
VkResult res; VkResult res;
VkDevice dev = renderer->dev->dev; VkDevice dev = renderer->dev->dev;
int32_t width = buffer->width;
int32_t height = buffer->height;
const struct wlr_vk_format_props *fmt = const struct wlr_vk_format_props *fmt =
vulkan_format_props_from_drm(renderer->dev, drm_fmt); vulkan_format_props_from_drm(renderer->dev, drm_fmt);
@ -459,12 +492,8 @@ static struct wlr_texture *vulkan_texture_from_pixels(
goto error; goto error;
} }
pixman_region32_t region; pixman_region32_init_rect(&texture->invalidated, 0, 0, width, height);
pixman_region32_init_rect(&region, 0, 0, width, height); texture->buffer = wlr_buffer_lock(buffer);
if (!write_pixels(texture, stride, &region, data, VK_IMAGE_LAYOUT_UNDEFINED,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0)) {
goto error;
}
return &texture->wlr_texture; return &texture->wlr_texture;
@ -815,7 +844,7 @@ struct wlr_texture *vulkan_texture_from_buffer(struct wlr_renderer *wlr_renderer
} else if (wlr_buffer_begin_data_ptr_access(buffer, } else if (wlr_buffer_begin_data_ptr_access(buffer,
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
struct wlr_texture *tex = vulkan_texture_from_pixels(renderer, struct wlr_texture *tex = vulkan_texture_from_pixels(renderer,
format, stride, buffer->width, buffer->height, data); format, stride, buffer);
wlr_buffer_end_data_ptr_access(buffer); wlr_buffer_end_data_ptr_access(buffer);
return tex; return tex;
} else { } else {