render/vulkan: generalize YCbCr format support

master
Simon Ser 2 years ago
parent 50b494d0f9
commit c7ae9dfaf8

@ -150,9 +150,10 @@ struct wlr_vk_render_format_setup {
VkPipeline tex_identity_pipe; VkPipeline tex_identity_pipe;
VkPipeline tex_srgb_pipe; VkPipeline tex_srgb_pipe;
VkPipeline tex_nv12_pipe;
VkPipeline quad_pipe; VkPipeline quad_pipe;
VkPipeline output_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. // Renderer-internal represenation of an wlr_buffer imported for rendering.
@ -207,7 +208,8 @@ struct wlr_vk_renderer {
VkShaderModule output_module; VkShaderModule output_module;
struct wlr_vk_pipeline_layout default_pipeline_layout; 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 // for blend->output subpass
VkPipelineLayout output_pipe_layout; 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); vkDestroyRenderPass(dev, setup->render_pass, NULL);
vkDestroyPipeline(dev, setup->tex_identity_pipe, NULL); vkDestroyPipeline(dev, setup->tex_identity_pipe, NULL);
vkDestroyPipeline(dev, setup->tex_srgb_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->output_pipe, NULL);
vkDestroyPipeline(dev, setup->quad_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, 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, static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_renderer,
struct wlr_texture *wlr_texture, const struct wlr_fbox *box, struct wlr_texture *wlr_texture, const struct wlr_fbox *box,
const float matrix[static 9], float alpha) { 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; 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) { if (pipe != renderer->bound_pipe) {
vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe); vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
renderer->bound_pipe = 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); vkDestroyShaderModule(dev->dev, renderer->output_module, NULL);
finish_pipeline_layout(renderer, &renderer->default_pipeline_layout); 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); vkDestroySemaphore(dev->dev, renderer->timeline_semaphore, NULL);
vkDestroyPipelineLayout(dev->dev, renderer->output_pipe_layout, 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; return false;
} }
const struct wlr_vk_format *nv12_format = vulkan_get_format_from_drm(DRM_FORMAT_NV12); size_t formats_len;
if (nv12_format != NULL && renderer->dev->sampler_ycbcr_conversion && const struct wlr_vk_format *formats = vulkan_get_format_list(&formats_len);
!init_ycbcr_pipeline_layout(renderer, &renderer->nv12_pipeline_layout, nv12_format)) {
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; 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, if (!init_blend_to_output_layouts(renderer, &renderer->output_ds_layout,
&renderer->output_pipe_layout)) { &renderer->output_pipe_layout)) {
return false; return false;
@ -2727,12 +2767,22 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
goto error; goto error;
} }
if (renderer->dev->sampler_ycbcr_conversion && !init_tex_pipeline(renderer, if (renderer->ycbcr_pipeline_layouts_len > 0) {
setup->render_pass, renderer->nv12_pipeline_layout.vk, setup->tex_ycbcr_pipelines =
WLR_VK_TEXTURE_TRANSFORM_SRGB, &setup->tex_nv12_pipe)) { calloc(renderer->ycbcr_pipeline_layouts_len, sizeof(*setup->tex_ycbcr_pipelines));
if (setup->tex_ycbcr_pipelines == NULL) {
goto error; 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, if (!init_quad_pipeline(renderer, setup->render_pass, renderer->default_pipeline_layout.vk,
&setup->quad_pipe)) { &setup->quad_pipe)) {
goto error; goto error;
@ -2852,9 +2902,14 @@ struct wlr_vk_pipeline_layout *vulkan_get_pipeline_layout(struct wlr_vk_renderer
if (!format->is_ycbcr) { if (!format->is_ycbcr) {
return &renderer->default_pipeline_layout; 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); char *name = drmGetFormatName(format->drm);
wlr_log(WLR_ERROR, "No pipeline layout found for format %s (0x%08"PRIX32")", wlr_log(WLR_ERROR, "No pipeline layout found for format %s (0x%08"PRIX32")",
name, format->drm); name, format->drm);

Loading…
Cancel
Save