From 8d1c6e42ac708927b814518cb7f9e48863b79743 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Sun, 23 Feb 2025 15:08:50 +0100 Subject: [PATCH] render/vulkan: add support for texture transfer functions --- include/render/vulkan.h | 6 +++--- render/vulkan/pass.c | 12 ++++++++++-- render/vulkan/renderer.c | 1 + render/vulkan/texture.c | 14 ++++++++------ 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/include/render/vulkan.h b/include/render/vulkan.h index e2846565c..651106042 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -349,6 +349,7 @@ struct wlr_vk_frag_output_pcr_data { struct wlr_vk_texture_view { struct wl_list link; // struct wlr_vk_texture.views const struct wlr_vk_pipeline_layout *layout; + bool srgb; VkDescriptorSet ds; VkImageView image_view; @@ -363,7 +364,7 @@ struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout( const struct wlr_vk_pipeline_layout_key *key); struct wlr_vk_texture_view *vulkan_texture_get_or_create_view( struct wlr_vk_texture *texture, - const struct wlr_vk_pipeline_layout *layout); + const struct wlr_vk_pipeline_layout *layout, bool srgb); // Creates a vulkan renderer for the given device. struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev); @@ -463,13 +464,12 @@ struct wlr_vk_texture { VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES]; VkImage image; const struct wlr_vk_format *format; - enum wlr_vk_texture_transform transform; struct wlr_vk_command_buffer *last_used_cb; // to track when it can be destroyed bool dmabuf_imported; bool owned; // if dmabuf_imported: whether we have ownership of the image bool transitioned; // if dma_imported: whether we transitioned it away from preinit bool has_alpha; // whether the image is has alpha channel - bool using_mutable_srgb; // is this accessed through _SRGB format view + bool using_mutable_srgb; // can be accessed through _SRGB format view struct wl_list foreign_link; // wlr_vk_renderer.foreign_textures struct wl_list destroy_link; // wlr_vk_command_buffer.destroy_textures struct wl_list link; // wlr_vk_renderer.textures diff --git a/render/vulkan/pass.c b/render/vulkan/pass.c index 75c454c87..95fbd319e 100644 --- a/render/vulkan/pass.c +++ b/render/vulkan/pass.c @@ -781,6 +781,14 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, }; encode_proj_matrix(matrix, vert_pcr_data.mat4); + bool srgb = options->transfer_function == 0 || + options->transfer_function == WLR_COLOR_TRANSFER_FUNCTION_SRGB; + bool srgb_image_view = srgb && texture->using_mutable_srgb; + enum wlr_vk_texture_transform tex_transform = + srgb_image_view || options->transfer_function == WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR ? + WLR_VK_TEXTURE_TRANSFORM_IDENTITY : + WLR_VK_TEXTURE_TRANSFORM_SRGB; + struct wlr_vk_render_format_setup *setup = pass->srgb_pathway ? pass->render_buffer->srgb.render_setup : pass->render_buffer->plain.render_setup; @@ -792,7 +800,7 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, .ycbcr_format = texture->format->is_ycbcr ? texture->format : NULL, .filter_mode = options->filter_mode, }, - .texture_transform = texture->transform, + .texture_transform = tex_transform, .blend_mode = !texture->has_alpha && alpha == 1.0 ? WLR_RENDER_BLEND_MODE_NONE : options->blend_mode, }); @@ -802,7 +810,7 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, } struct wlr_vk_texture_view *view = - vulkan_texture_get_or_create_view(texture, pipe->layout); + vulkan_texture_get_or_create_view(texture, pipe->layout, srgb_image_view); if (!view) { pass->failed = true; return; diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index cbfb022f7..a0e456580 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -2442,6 +2442,7 @@ struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev renderer->dev = dev; wlr_renderer_init(&renderer->wlr_renderer, &renderer_impl, WLR_BUFFER_CAP_DMABUF); + renderer->wlr_renderer.features.input_color_transform = true; renderer->wlr_renderer.features.output_color_transform = true; wl_list_init(&renderer->stage.buffers); wl_list_init(&renderer->foreign_textures); diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index 61a6040ee..2b21d458c 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -269,10 +269,12 @@ static struct wlr_vk_texture *vulkan_texture_create( } struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_texture *texture, - const struct wlr_vk_pipeline_layout *pipeline_layout) { + const struct wlr_vk_pipeline_layout *pipeline_layout, bool srgb) { + assert(texture->using_mutable_srgb || !srgb); + struct wlr_vk_texture_view *view; wl_list_for_each(view, &texture->views, link) { - if (view->layout == pipeline_layout) { + if (view->layout == pipeline_layout && view->srgb == srgb) { return view; } } @@ -283,6 +285,7 @@ struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_text } view->layout = pipeline_layout; + view->srgb = srgb; VkResult res; VkDevice dev = texture->renderer->dev->dev; @@ -290,8 +293,7 @@ struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_text VkImageViewCreateInfo view_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = texture->using_mutable_srgb ? texture->format->vk_srgb - : texture->format->vk, + .format = srgb ? texture->format->vk_srgb : texture->format->vk, .components.r = VK_COMPONENT_SWIZZLE_IDENTITY, .components.g = VK_COMPONENT_SWIZZLE_IDENTITY, .components.b = VK_COMPONENT_SWIZZLE_IDENTITY, @@ -353,10 +355,10 @@ struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_text static void texture_set_format(struct wlr_vk_texture *texture, const struct wlr_vk_format *format, bool has_mutable_srgb) { + assert(!(format->is_ycbcr && has_mutable_srgb)); + texture->format = format; texture->using_mutable_srgb = has_mutable_srgb; - texture->transform = !format->is_ycbcr && has_mutable_srgb ? - WLR_VK_TEXTURE_TRANSFORM_IDENTITY : WLR_VK_TEXTURE_TRANSFORM_SRGB; const struct wlr_pixel_format_info *format_info = drm_get_pixel_format_info(format->drm);