mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 12:55:58 +01:00
render/vulkan: generalize YCbCr format support
This commit is contained in:
parent
50b494d0f9
commit
c7ae9dfaf8
2 changed files with 81 additions and 24 deletions
|
@ -150,9 +150,10 @@ struct wlr_vk_render_format_setup {
|
|||
|
||||
VkPipeline tex_identity_pipe;
|
||||
VkPipeline tex_srgb_pipe;
|
||||
VkPipeline tex_nv12_pipe;
|
||||
VkPipeline quad_pipe;
|
||||
VkPipeline output_pipe;
|
||||
|
||||
VkPipeline *tex_ycbcr_pipelines; // same length as wlr_vk_renderer.ycbcr_pipeline_layouts
|
||||
};
|
||||
|
||||
// Renderer-internal represenation of an wlr_buffer imported for rendering.
|
||||
|
@ -207,7 +208,8 @@ struct wlr_vk_renderer {
|
|||
VkShaderModule output_module;
|
||||
|
||||
struct wlr_vk_pipeline_layout default_pipeline_layout;
|
||||
struct wlr_vk_pipeline_layout nv12_pipeline_layout;
|
||||
size_t ycbcr_pipeline_layouts_len;
|
||||
struct wlr_vk_pipeline_layout *ycbcr_pipeline_layouts;
|
||||
|
||||
// for blend->output subpass
|
||||
VkPipelineLayout output_pipe_layout;
|
||||
|
|
|
@ -186,9 +186,13 @@ static void destroy_render_format_setup(struct wlr_vk_renderer *renderer,
|
|||
vkDestroyRenderPass(dev, setup->render_pass, NULL);
|
||||
vkDestroyPipeline(dev, setup->tex_identity_pipe, NULL);
|
||||
vkDestroyPipeline(dev, setup->tex_srgb_pipe, NULL);
|
||||
vkDestroyPipeline(dev, setup->tex_nv12_pipe, NULL);
|
||||
vkDestroyPipeline(dev, setup->output_pipe, NULL);
|
||||
vkDestroyPipeline(dev, setup->quad_pipe, NULL);
|
||||
|
||||
for (size_t i = 0; i < renderer->ycbcr_pipeline_layouts_len; i++) {
|
||||
vkDestroyPipeline(dev, setup->tex_ycbcr_pipelines[i], NULL);
|
||||
}
|
||||
free(setup->tex_ycbcr_pipelines);
|
||||
}
|
||||
|
||||
static void shared_buffer_destroy(struct wlr_vk_renderer *r,
|
||||
|
@ -1385,6 +1389,21 @@ static void vulkan_end(struct wlr_renderer *wlr_renderer) {
|
|||
}
|
||||
}
|
||||
|
||||
static VkPipeline get_texture_pipeline(struct wlr_vk_texture *texture,
|
||||
struct wlr_vk_render_format_setup *render_setup) {
|
||||
if (texture->format->is_ycbcr) {
|
||||
size_t pipeline_layout_index = texture->pipeline_layout - texture->renderer->ycbcr_pipeline_layouts;
|
||||
return render_setup->tex_ycbcr_pipelines[pipeline_layout_index];
|
||||
} else {
|
||||
if (texture->format->is_srgb) {
|
||||
// sRGB formats already have the transfer function applied
|
||||
return render_setup->tex_identity_pipe;
|
||||
} else {
|
||||
return render_setup->tex_srgb_pipe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_renderer,
|
||||
struct wlr_texture *wlr_texture, const struct wlr_fbox *box,
|
||||
const float matrix[static 9], float alpha) {
|
||||
|
@ -1407,17 +1426,8 @@ static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_render
|
|||
}
|
||||
|
||||
VkPipelineLayout pipe_layout = texture->pipeline_layout->vk;
|
||||
VkPipeline pipe = get_texture_pipeline(texture, renderer->current_render_buffer->render_setup);
|
||||
|
||||
VkPipeline pipe;
|
||||
// SRGB formats already have the transfer function applied
|
||||
if (texture->format->drm == DRM_FORMAT_NV12) {
|
||||
pipe = renderer->current_render_buffer->render_setup->tex_nv12_pipe;
|
||||
} else if (texture->format->is_srgb) {
|
||||
pipe = renderer->current_render_buffer->render_setup->tex_identity_pipe;
|
||||
} else {
|
||||
pipe = renderer->current_render_buffer->render_setup->tex_srgb_pipe;
|
||||
}
|
||||
assert(pipe != VK_NULL_HANDLE);
|
||||
if (pipe != renderer->bound_pipe) {
|
||||
vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
|
||||
renderer->bound_pipe = pipe;
|
||||
|
@ -1645,7 +1655,10 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) {
|
|||
vkDestroyShaderModule(dev->dev, renderer->output_module, NULL);
|
||||
|
||||
finish_pipeline_layout(renderer, &renderer->default_pipeline_layout);
|
||||
finish_pipeline_layout(renderer, &renderer->nv12_pipeline_layout);
|
||||
for (size_t i = 0; i < renderer->ycbcr_pipeline_layouts_len; i++) {
|
||||
finish_pipeline_layout(renderer, &renderer->ycbcr_pipeline_layouts[i]);
|
||||
}
|
||||
free(renderer->ycbcr_pipeline_layouts);
|
||||
|
||||
vkDestroySemaphore(dev->dev, renderer->timeline_semaphore, NULL);
|
||||
vkDestroyPipelineLayout(dev->dev, renderer->output_pipe_layout, NULL);
|
||||
|
@ -2452,12 +2465,39 @@ static bool init_static_render_data(struct wlr_vk_renderer *renderer) {
|
|||
return false;
|
||||
}
|
||||
|
||||
const struct wlr_vk_format *nv12_format = vulkan_get_format_from_drm(DRM_FORMAT_NV12);
|
||||
if (nv12_format != NULL && renderer->dev->sampler_ycbcr_conversion &&
|
||||
!init_ycbcr_pipeline_layout(renderer, &renderer->nv12_pipeline_layout, nv12_format)) {
|
||||
size_t formats_len;
|
||||
const struct wlr_vk_format *formats = vulkan_get_format_list(&formats_len);
|
||||
|
||||
size_t ycbcr_formats_len = 0;
|
||||
for (size_t i = 0; i < formats_len; i++) {
|
||||
if (renderer->dev->sampler_ycbcr_conversion && formats[i].is_ycbcr) {
|
||||
ycbcr_formats_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (ycbcr_formats_len > 0) {
|
||||
renderer->ycbcr_pipeline_layouts =
|
||||
calloc(ycbcr_formats_len, sizeof(*renderer->ycbcr_pipeline_layouts));
|
||||
if (renderer->ycbcr_pipeline_layouts == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < formats_len; i++) {
|
||||
const struct wlr_vk_format *format = &formats[i];
|
||||
if (!format->is_ycbcr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct wlr_vk_pipeline_layout *pl =
|
||||
&renderer->ycbcr_pipeline_layouts[renderer->ycbcr_pipeline_layouts_len];
|
||||
if (!init_ycbcr_pipeline_layout(renderer, pl, format)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
renderer->ycbcr_pipeline_layouts_len++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_blend_to_output_layouts(renderer, &renderer->output_ds_layout,
|
||||
&renderer->output_pipe_layout)) {
|
||||
return false;
|
||||
|
@ -2727,12 +2767,22 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (renderer->dev->sampler_ycbcr_conversion && !init_tex_pipeline(renderer,
|
||||
setup->render_pass, renderer->nv12_pipeline_layout.vk,
|
||||
WLR_VK_TEXTURE_TRANSFORM_SRGB, &setup->tex_nv12_pipe)) {
|
||||
if (renderer->ycbcr_pipeline_layouts_len > 0) {
|
||||
setup->tex_ycbcr_pipelines =
|
||||
calloc(renderer->ycbcr_pipeline_layouts_len, sizeof(*setup->tex_ycbcr_pipelines));
|
||||
if (setup->tex_ycbcr_pipelines == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < renderer->ycbcr_pipeline_layouts_len; i++) {
|
||||
struct wlr_vk_pipeline_layout *pipeline_layout = &renderer->ycbcr_pipeline_layouts[i];
|
||||
if (!init_tex_pipeline(renderer, setup->render_pass, pipeline_layout->vk,
|
||||
WLR_VK_TEXTURE_TRANSFORM_SRGB, &setup->tex_ycbcr_pipelines[i])) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_quad_pipeline(renderer, setup->render_pass, renderer->default_pipeline_layout.vk,
|
||||
&setup->quad_pipe)) {
|
||||
goto error;
|
||||
|
@ -2852,9 +2902,14 @@ struct wlr_vk_pipeline_layout *vulkan_get_pipeline_layout(struct wlr_vk_renderer
|
|||
if (!format->is_ycbcr) {
|
||||
return &renderer->default_pipeline_layout;
|
||||
}
|
||||
if (format->drm == DRM_FORMAT_NV12 && renderer->dev->sampler_ycbcr_conversion) {
|
||||
return &renderer->nv12_pipeline_layout;
|
||||
|
||||
for (size_t i = 0; i < renderer->ycbcr_pipeline_layouts_len; i++) {
|
||||
struct wlr_vk_pipeline_layout *pl = &renderer->ycbcr_pipeline_layouts[i];
|
||||
if (pl->ycbcr.format == format->vk) {
|
||||
return pl;
|
||||
}
|
||||
}
|
||||
|
||||
char *name = drmGetFormatName(format->drm);
|
||||
wlr_log(WLR_ERROR, "No pipeline layout found for format %s (0x%08"PRIX32")",
|
||||
name, format->drm);
|
||||
|
|
Loading…
Reference in a new issue