mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-12-22 09:59:48 +01:00
render/vulkan: Dynamically create pipeline layouts
These will happen lazily when pipelines get created.
This commit is contained in:
parent
3623005858
commit
8a387b5558
4 changed files with 148 additions and 145 deletions
|
@ -123,7 +123,13 @@ const struct wlr_vk_format_modifier_props *vulkan_format_props_find_modifier(
|
|||
struct wlr_vk_format_props *props, uint64_t mod, bool render);
|
||||
void vulkan_format_props_finish(struct wlr_vk_format_props *props);
|
||||
|
||||
struct wlr_vk_pipeline_layout_key {
|
||||
const struct wlr_vk_format *ycbcr_format;
|
||||
};
|
||||
|
||||
struct wlr_vk_pipeline_layout {
|
||||
struct wlr_vk_pipeline_layout_key key;
|
||||
|
||||
VkPipelineLayout vk;
|
||||
VkDescriptorSetLayout ds;
|
||||
VkSampler sampler;
|
||||
|
@ -133,6 +139,8 @@ struct wlr_vk_pipeline_layout {
|
|||
VkSamplerYcbcrConversion conversion;
|
||||
VkFormat format;
|
||||
} ycbcr;
|
||||
|
||||
struct wl_list link; // struct wlr_vk_renderer.pipeline_layouts
|
||||
};
|
||||
|
||||
// Constants used to pick the color transform for the texture drawing
|
||||
|
@ -148,8 +156,8 @@ enum wlr_vk_shader_source {
|
|||
};
|
||||
|
||||
struct wlr_vk_pipeline_key {
|
||||
struct wlr_vk_pipeline_layout_key layout;
|
||||
enum wlr_vk_shader_source source;
|
||||
struct wlr_vk_pipeline_layout *layout;
|
||||
enum wlr_render_blend_mode blend_mode;
|
||||
|
||||
// only used if source is texture
|
||||
|
@ -160,6 +168,7 @@ struct wlr_vk_pipeline {
|
|||
struct wlr_vk_pipeline_key key;
|
||||
|
||||
VkPipeline vk;
|
||||
const struct wlr_vk_pipeline_layout *layout;
|
||||
struct wlr_vk_render_format_setup *setup;
|
||||
struct wl_list link; // struct wlr_vk_render_format_setup
|
||||
};
|
||||
|
@ -168,7 +177,7 @@ struct wlr_vk_pipeline {
|
|||
// and therefore also separate pipelines.
|
||||
struct wlr_vk_render_format_setup {
|
||||
struct wl_list link; // wlr_vk_renderer.render_format_setups
|
||||
VkFormat render_format; // used in renderpass
|
||||
const struct wlr_vk_format *render_format; // used in renderpass
|
||||
VkRenderPass render_pass;
|
||||
|
||||
VkPipeline output_pipe;
|
||||
|
@ -228,9 +237,7 @@ struct wlr_vk_renderer {
|
|||
VkShaderModule quad_frag_module;
|
||||
VkShaderModule output_module;
|
||||
|
||||
struct wlr_vk_pipeline_layout default_pipeline_layout;
|
||||
size_t ycbcr_pipeline_layouts_len;
|
||||
struct wlr_vk_pipeline_layout *ycbcr_pipeline_layouts;
|
||||
struct wl_list pipeline_layouts; // struct wlr_vk_pipeline_layout.link
|
||||
|
||||
// for blend->output subpass
|
||||
VkPipelineLayout output_pipe_layout;
|
||||
|
@ -291,6 +298,9 @@ struct wlr_vk_vert_pcr_data {
|
|||
struct wlr_vk_pipeline *setup_get_or_create_pipeline(
|
||||
struct wlr_vk_render_format_setup *setup,
|
||||
const struct wlr_vk_pipeline_key *key);
|
||||
struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
|
||||
struct wlr_vk_renderer *renderer,
|
||||
const struct wlr_vk_pipeline_layout_key *key);
|
||||
|
||||
// Creates a vulkan renderer for the given device.
|
||||
struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev);
|
||||
|
@ -344,9 +354,6 @@ struct wlr_vk_format_props *vulkan_format_props_from_drm(
|
|||
struct wlr_vk_device *dev, uint32_t drm_format);
|
||||
struct wlr_vk_renderer *vulkan_get_renderer(struct wlr_renderer *r);
|
||||
|
||||
struct wlr_vk_pipeline_layout *vulkan_get_pipeline_layout(struct wlr_vk_renderer *renderer,
|
||||
const struct wlr_vk_format *format);
|
||||
|
||||
struct wlr_vk_command_buffer *vulkan_acquire_command_buffer(
|
||||
struct wlr_vk_renderer *renderer);
|
||||
uint64_t vulkan_end_command_buffer(struct wlr_vk_command_buffer *cb,
|
||||
|
@ -368,7 +375,6 @@ struct wlr_vk_texture {
|
|||
VkImage image;
|
||||
VkImageView image_view;
|
||||
const struct wlr_vk_format *format;
|
||||
struct wlr_vk_pipeline_layout *pipeline_layout;
|
||||
enum wlr_vk_texture_transform transform;
|
||||
VkDescriptorSet ds;
|
||||
struct wlr_vk_descriptor_pool *ds_pool;
|
||||
|
|
|
@ -404,7 +404,6 @@ error:
|
|||
static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
||||
const struct wlr_render_rect_options *options) {
|
||||
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
||||
struct wlr_vk_renderer *renderer = pass->renderer;
|
||||
VkCommandBuffer cb = pass->command_buffer->vk;
|
||||
|
||||
// Input color values are given in sRGB space, shader expects
|
||||
|
@ -436,7 +435,7 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
|||
pass->render_buffer->render_setup,
|
||||
&(struct wlr_vk_pipeline_key) {
|
||||
.source = WLR_VK_SHADER_SOURCE_SINGLE_COLOR,
|
||||
.layout = &renderer->default_pipeline_layout,
|
||||
.layout = { .ycbcr_format = NULL },
|
||||
});
|
||||
if (!pipe) {
|
||||
pass->failed = true;
|
||||
|
@ -450,9 +449,9 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
|||
mat3_to_mat4(matrix, vert_pcr_data.mat4);
|
||||
|
||||
bind_pipeline(pass, pipe->vk);
|
||||
vkCmdPushConstants(cb, renderer->default_pipeline_layout.vk,
|
||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
||||
vkCmdPushConstants(cb, renderer->default_pipeline_layout.vk,
|
||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(vert_pcr_data), sizeof(float) * 4,
|
||||
linear_color);
|
||||
|
||||
|
@ -546,21 +545,24 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
|||
render_buffer->render_setup,
|
||||
&(struct wlr_vk_pipeline_key) {
|
||||
.source = WLR_VK_SHADER_SOURCE_TEXTURE,
|
||||
.layout = texture->pipeline_layout,
|
||||
.layout = {
|
||||
.ycbcr_format = texture->format->is_ycbcr ? texture->format : NULL,
|
||||
},
|
||||
.texture_transform = texture->transform,
|
||||
});
|
||||
if (!pipe) {
|
||||
pass->failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
bind_pipeline(pass, pipe->vk);
|
||||
|
||||
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipe->key.layout->vk, 0, 1, &texture->ds, 0, NULL);
|
||||
pipe->layout->vk, 0, 1, &texture->ds, 0, NULL);
|
||||
|
||||
vkCmdPushConstants(cb, pipe->key.layout->vk,
|
||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
||||
vkCmdPushConstants(cb, pipe->key.layout->vk,
|
||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(vert_pcr_data), sizeof(float),
|
||||
&alpha);
|
||||
|
||||
|
|
|
@ -56,7 +56,8 @@ struct wlr_vk_renderer *vulkan_get_renderer(struct wlr_renderer *wlr_renderer) {
|
|||
}
|
||||
|
||||
static struct wlr_vk_render_format_setup *find_or_create_render_setup(
|
||||
struct wlr_vk_renderer *renderer, VkFormat format, bool has_blending_buffer);
|
||||
struct wlr_vk_renderer *renderer, const struct wlr_vk_format *format,
|
||||
bool has_blending_buffer);
|
||||
|
||||
// https://www.w3.org/Graphics/Color/srgb
|
||||
static float color_to_linear(float non_linear) {
|
||||
|
@ -793,7 +794,7 @@ static struct wlr_vk_render_buffer *create_render_buffer(
|
|||
bool has_blending_buffer = !fmt->format.is_srgb;
|
||||
|
||||
buffer->render_setup = find_or_create_render_setup(
|
||||
renderer, fmt->format.vk, has_blending_buffer);
|
||||
renderer, &fmt->format, has_blending_buffer);
|
||||
if (!buffer->render_setup) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -1409,7 +1410,9 @@ static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_render
|
|||
struct wlr_vk_pipeline *pipe = setup_get_or_create_pipeline(
|
||||
renderer->current_render_buffer->render_setup,
|
||||
&(struct wlr_vk_pipeline_key) {
|
||||
.layout = texture->pipeline_layout,
|
||||
.layout = {
|
||||
.ycbcr_format = texture->format->is_ycbcr ? texture->format : NULL,
|
||||
},
|
||||
.texture_transform = texture->transform,
|
||||
});
|
||||
if (!pipe) {
|
||||
|
@ -1422,7 +1425,7 @@ static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_render
|
|||
}
|
||||
|
||||
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipe->key.layout->vk, 0, 1, &texture->ds, 0, NULL);
|
||||
pipe->layout->vk, 0, 1, &texture->ds, 0, NULL);
|
||||
|
||||
float final_matrix[9];
|
||||
wlr_matrix_multiply(final_matrix, renderer->projection, matrix);
|
||||
|
@ -1435,9 +1438,9 @@ static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_render
|
|||
vert_pcr_data.uv_size[0] = box->width / wlr_texture->width;
|
||||
vert_pcr_data.uv_size[1] = box->height / wlr_texture->height;
|
||||
|
||||
vkCmdPushConstants(cb, pipe->key.layout->vk,
|
||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
||||
vkCmdPushConstants(cb, pipe->key.layout->vk,
|
||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(vert_pcr_data), sizeof(float),
|
||||
&alpha);
|
||||
vkCmdDraw(cb, 4, 1, 0, 0);
|
||||
|
@ -1512,7 +1515,9 @@ static void vulkan_render_quad_with_matrix(struct wlr_renderer *wlr_renderer,
|
|||
renderer->current_render_buffer->render_setup,
|
||||
&(struct wlr_vk_pipeline_key) {
|
||||
.source = WLR_VK_SHADER_SOURCE_SINGLE_COLOR,
|
||||
.layout = &renderer->default_pipeline_layout,
|
||||
.layout = {
|
||||
.ycbcr_format = NULL,
|
||||
},
|
||||
});
|
||||
if (!pipe) {
|
||||
return;
|
||||
|
@ -1546,9 +1551,9 @@ static void vulkan_render_quad_with_matrix(struct wlr_renderer *wlr_renderer,
|
|||
linear_color[2] = color_to_linear(color[2]);
|
||||
linear_color[3] = color[3]; // no conversion for alpha
|
||||
|
||||
vkCmdPushConstants(cb, renderer->default_pipeline_layout.vk,
|
||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
||||
vkCmdPushConstants(cb, renderer->default_pipeline_layout.vk,
|
||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(vert_pcr_data), sizeof(float) * 4,
|
||||
linear_color);
|
||||
vkCmdDraw(cb, 4, 1, 0, 0);
|
||||
|
@ -1578,15 +1583,6 @@ static uint32_t vulkan_preferred_read_format(
|
|||
return dmabuf.format;
|
||||
}
|
||||
|
||||
static void finish_pipeline_layout(struct wlr_vk_renderer *renderer,
|
||||
struct wlr_vk_pipeline_layout *pipeline_layout) {
|
||||
struct wlr_vk_device *dev = renderer->dev;
|
||||
vkDestroyPipelineLayout(dev->dev, pipeline_layout->vk, NULL);
|
||||
vkDestroyDescriptorSetLayout(dev->dev, pipeline_layout->ds, NULL);
|
||||
vkDestroySampler(dev->dev, pipeline_layout->sampler, NULL);
|
||||
vkDestroySamplerYcbcrConversion(dev->dev, pipeline_layout->ycbcr.conversion, NULL);
|
||||
}
|
||||
|
||||
static void vulkan_destroy(struct wlr_renderer *wlr_renderer) {
|
||||
struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer);
|
||||
struct wlr_vk_device *dev = renderer->dev;
|
||||
|
@ -1651,11 +1647,14 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) {
|
|||
vkDestroyShaderModule(dev->dev, renderer->quad_frag_module, NULL);
|
||||
vkDestroyShaderModule(dev->dev, renderer->output_module, NULL);
|
||||
|
||||
finish_pipeline_layout(renderer, &renderer->default_pipeline_layout);
|
||||
for (size_t i = 0; i < renderer->ycbcr_pipeline_layouts_len; i++) {
|
||||
finish_pipeline_layout(renderer, &renderer->ycbcr_pipeline_layouts[i]);
|
||||
struct wlr_vk_pipeline_layout *pipeline_layout, *pipeline_layout_tmp;
|
||||
wl_list_for_each_safe(pipeline_layout, pipeline_layout_tmp,
|
||||
&renderer->pipeline_layouts, link) {
|
||||
vkDestroyPipelineLayout(dev->dev, pipeline_layout->vk, NULL);
|
||||
vkDestroyDescriptorSetLayout(dev->dev, pipeline_layout->ds, NULL);
|
||||
vkDestroySampler(dev->dev, pipeline_layout->sampler, NULL);
|
||||
vkDestroySamplerYcbcrConversion(dev->dev, pipeline_layout->ycbcr.conversion, NULL);
|
||||
}
|
||||
free(renderer->ycbcr_pipeline_layouts);
|
||||
|
||||
vkDestroySemaphore(dev->dev, renderer->timeline_semaphore, NULL);
|
||||
vkDestroyPipelineLayout(dev->dev, renderer->output_pipe_layout, NULL);
|
||||
|
@ -1698,7 +1697,7 @@ static bool vulkan_read_pixels(struct wlr_renderer *wlr_renderer,
|
|||
return false;
|
||||
}
|
||||
VkFormat dst_format = wlr_vk_format->vk;
|
||||
VkFormat src_format = vk_renderer->current_render_buffer->render_setup->render_format;
|
||||
VkFormat src_format = vk_renderer->current_render_buffer->render_setup->render_format->vk;
|
||||
VkFormatProperties dst_format_props = {0}, src_format_props = {0};
|
||||
vkGetPhysicalDeviceFormatProperties(vk_renderer->dev->phdev, dst_format, &dst_format_props);
|
||||
vkGetPhysicalDeviceFormatProperties(vk_renderer->dev->phdev, src_format, &src_format_props);
|
||||
|
@ -2094,9 +2093,22 @@ static bool init_blend_to_output_layouts(struct wlr_vk_renderer *renderer,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool pipeline_layout_key_equals(
|
||||
const struct wlr_vk_pipeline_layout_key *a,
|
||||
const struct wlr_vk_pipeline_layout_key *b) {
|
||||
assert(!a->ycbcr_format || a->ycbcr_format->is_ycbcr);
|
||||
assert(!b->ycbcr_format || b->ycbcr_format->is_ycbcr);
|
||||
|
||||
if (a->ycbcr_format != b->ycbcr_format) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pipeline_key_equals(const struct wlr_vk_pipeline_key *a,
|
||||
const struct wlr_vk_pipeline_key *b) {
|
||||
if (a->layout != b->layout) {
|
||||
if (!pipeline_layout_key_equals(&a->layout, &b->layout)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2128,15 +2140,22 @@ struct wlr_vk_pipeline *setup_get_or_create_pipeline(
|
|||
}
|
||||
}
|
||||
|
||||
struct wlr_vk_renderer *renderer = setup->renderer;
|
||||
|
||||
struct wlr_vk_pipeline_layout *pipeline_layout = get_or_create_pipeline_layout(
|
||||
renderer, &key->layout);
|
||||
if (!pipeline_layout) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pipeline = calloc(1, sizeof(*pipeline));
|
||||
if (!pipeline) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_vk_renderer *renderer = setup->renderer;
|
||||
|
||||
pipeline->setup = setup;
|
||||
pipeline->key = *key;
|
||||
pipeline->layout = pipeline_layout;
|
||||
|
||||
VkResult res;
|
||||
VkDevice dev = renderer->dev->dev;
|
||||
|
@ -2246,7 +2265,7 @@ struct wlr_vk_pipeline *setup_get_or_create_pipeline(
|
|||
|
||||
VkGraphicsPipelineCreateInfo pinfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||
.layout = key->layout->vk,
|
||||
.layout = pipeline_layout->vk,
|
||||
.renderPass = setup->render_pass,
|
||||
.subpass = 0,
|
||||
.stageCount = 2,
|
||||
|
@ -2386,31 +2405,51 @@ static bool init_pipeline_layout(struct wlr_vk_renderer *renderer,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool init_ycbcr_pipeline_layout(struct wlr_vk_renderer *renderer,
|
||||
struct wlr_vk_pipeline_layout *pipeline_layout,
|
||||
const struct wlr_vk_format *format) {
|
||||
VkResult res;
|
||||
|
||||
assert(format->is_ycbcr);
|
||||
pipeline_layout->ycbcr.format = format->vk;
|
||||
|
||||
VkSamplerYcbcrConversionCreateInfo conversion_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
|
||||
.format = format->vk,
|
||||
.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601,
|
||||
.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
|
||||
.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
|
||||
.yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
|
||||
.chromaFilter = VK_FILTER_LINEAR,
|
||||
};
|
||||
res = vkCreateSamplerYcbcrConversion(renderer->dev->dev,
|
||||
&conversion_create_info, NULL, &pipeline_layout->ycbcr.conversion);
|
||||
if (res != VK_SUCCESS) {
|
||||
wlr_vk_error("vkCreateSamplerYcbcrConversion", res);
|
||||
return false;
|
||||
struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
|
||||
struct wlr_vk_renderer *renderer,
|
||||
const struct wlr_vk_pipeline_layout_key *key) {
|
||||
struct wlr_vk_pipeline_layout *pipeline_layout;
|
||||
wl_list_for_each(pipeline_layout, &renderer->pipeline_layouts, link) {
|
||||
if (pipeline_layout_key_equals(&pipeline_layout->key, key)) {
|
||||
return pipeline_layout;
|
||||
}
|
||||
}
|
||||
|
||||
return init_pipeline_layout(renderer, pipeline_layout);
|
||||
pipeline_layout = calloc(1, sizeof(*pipeline_layout));
|
||||
if (!pipeline_layout) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pipeline_layout->key = *key;
|
||||
|
||||
VkResult res;
|
||||
|
||||
if (key->ycbcr_format) {
|
||||
VkSamplerYcbcrConversionCreateInfo conversion_create_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
|
||||
.format = key->ycbcr_format->vk,
|
||||
.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601,
|
||||
.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_NARROW,
|
||||
.xChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
|
||||
.yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
|
||||
.chromaFilter = VK_FILTER_LINEAR,
|
||||
};
|
||||
res = vkCreateSamplerYcbcrConversion(renderer->dev->dev,
|
||||
&conversion_create_info, NULL, &pipeline_layout->ycbcr.conversion);
|
||||
if (res != VK_SUCCESS) {
|
||||
wlr_vk_error("vkCreateSamplerYcbcrConversion", res);
|
||||
free(pipeline_layout);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_pipeline_layout(renderer, pipeline_layout)) {
|
||||
free(pipeline_layout);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wl_list_insert(&renderer->pipeline_layouts, &pipeline_layout->link);
|
||||
return pipeline_layout;
|
||||
}
|
||||
|
||||
// Creates static render data, such as sampler, layouts and shader modules
|
||||
|
@ -2420,41 +2459,6 @@ static bool init_static_render_data(struct wlr_vk_renderer *renderer) {
|
|||
VkResult res;
|
||||
VkDevice dev = renderer->dev->dev;
|
||||
|
||||
if (!init_pipeline_layout(renderer, &renderer->default_pipeline_layout)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t ycbcr_formats_len = 0;
|
||||
for (size_t i = 0; i < renderer->dev->format_prop_count; i++) {
|
||||
struct wlr_vk_format_props *props = &renderer->dev->format_props[i];
|
||||
if (renderer->dev->sampler_ycbcr_conversion && props->format.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 < renderer->dev->format_prop_count; i++) {
|
||||
const struct wlr_vk_format *format = &renderer->dev->format_props[i].format;
|
||||
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;
|
||||
|
@ -2510,7 +2514,8 @@ static bool init_static_render_data(struct wlr_vk_renderer *renderer) {
|
|||
}
|
||||
|
||||
static struct wlr_vk_render_format_setup *find_or_create_render_setup(
|
||||
struct wlr_vk_renderer *renderer, VkFormat format, bool has_blending_buffer) {
|
||||
struct wlr_vk_renderer *renderer, const struct wlr_vk_format *format,
|
||||
bool has_blending_buffer) {
|
||||
struct wlr_vk_render_format_setup *setup;
|
||||
wl_list_for_each(setup, &renderer->render_format_setups, link) {
|
||||
if (setup->render_format == format) {
|
||||
|
@ -2544,7 +2549,7 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
|
|||
.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
},
|
||||
{
|
||||
.format = format,
|
||||
.format = format->vk,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
|
@ -2649,7 +2654,7 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
|
|||
}
|
||||
} else {
|
||||
VkAttachmentDescription attachment = {
|
||||
.format = format,
|
||||
.format = format->vk,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
||||
|
@ -2718,7 +2723,7 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
|
|||
|
||||
if (!setup_get_or_create_pipeline(setup, &(struct wlr_vk_pipeline_key){
|
||||
.source = WLR_VK_SHADER_SOURCE_SINGLE_COLOR,
|
||||
.layout = &renderer->default_pipeline_layout,
|
||||
.layout = { .ycbcr_format = NULL },
|
||||
})) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -2726,7 +2731,7 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
|
|||
if (!setup_get_or_create_pipeline(setup, &(struct wlr_vk_pipeline_key){
|
||||
.source = WLR_VK_SHADER_SOURCE_TEXTURE,
|
||||
.texture_transform = WLR_VK_TEXTURE_TRANSFORM_IDENTITY,
|
||||
.layout = &renderer->default_pipeline_layout,
|
||||
.layout = {.ycbcr_format = NULL },
|
||||
})) {
|
||||
goto error;
|
||||
}
|
||||
|
@ -2734,18 +2739,24 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup(
|
|||
if (!setup_get_or_create_pipeline(setup, &(struct wlr_vk_pipeline_key){
|
||||
.source = WLR_VK_SHADER_SOURCE_TEXTURE,
|
||||
.texture_transform = WLR_VK_TEXTURE_TRANSFORM_SRGB,
|
||||
.layout = &renderer->default_pipeline_layout,
|
||||
.layout = {.ycbcr_format = NULL },
|
||||
})) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < renderer->ycbcr_pipeline_layouts_len; i++) {
|
||||
if (!setup_get_or_create_pipeline(setup, &(struct wlr_vk_pipeline_key){
|
||||
.source = WLR_VK_SHADER_SOURCE_TEXTURE,
|
||||
.texture_transform = WLR_VK_TEXTURE_TRANSFORM_SRGB,
|
||||
.layout = &renderer->ycbcr_pipeline_layouts[i],
|
||||
})) {
|
||||
goto error;
|
||||
for (size_t i = 0; i < renderer->dev->format_prop_count; i++) {
|
||||
const struct wlr_vk_format *format = &renderer->dev->format_props[i].format;
|
||||
const struct wlr_vk_pipeline_layout_key layout = {
|
||||
.ycbcr_format = format,
|
||||
};
|
||||
|
||||
if (format->is_ycbcr) {
|
||||
if (!setup_get_or_create_pipeline(setup, &(struct wlr_vk_pipeline_key){
|
||||
.texture_transform = WLR_VK_TEXTURE_TRANSFORM_SRGB,
|
||||
.layout = layout
|
||||
})) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2774,6 +2785,7 @@ struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev
|
|||
wl_list_init(&renderer->output_descriptor_pools);
|
||||
wl_list_init(&renderer->render_format_setups);
|
||||
wl_list_init(&renderer->render_buffers);
|
||||
wl_list_init(&renderer->pipeline_layouts);
|
||||
|
||||
if (!init_static_render_data(renderer)) {
|
||||
goto error;
|
||||
|
@ -2858,26 +2870,6 @@ struct wlr_renderer *wlr_vk_renderer_create_with_drm_fd(int drm_fd) {
|
|||
return vulkan_renderer_create_for_device(dev);
|
||||
}
|
||||
|
||||
struct wlr_vk_pipeline_layout *vulkan_get_pipeline_layout(struct wlr_vk_renderer *renderer,
|
||||
const struct wlr_vk_format *format) {
|
||||
if (!format->is_ycbcr) {
|
||||
return &renderer->default_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);
|
||||
free(name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VkInstance wlr_vk_renderer_get_instance(struct wlr_renderer *renderer) {
|
||||
struct wlr_vk_renderer *vk_renderer = vulkan_get_renderer(renderer);
|
||||
return vk_renderer->dev->instance->instance;
|
||||
|
@ -2902,6 +2894,6 @@ void wlr_vk_renderer_get_current_image_attribs(struct wlr_renderer *renderer,
|
|||
struct wlr_vk_image_attribs *attribs) {
|
||||
struct wlr_vk_renderer *vk_renderer = vulkan_get_renderer(renderer);
|
||||
attribs->image = vk_renderer->current_render_buffer->image;
|
||||
attribs->format = vk_renderer->current_render_buffer->render_setup->render_format;
|
||||
attribs->format = vk_renderer->current_render_buffer->render_setup->render_format->vk;
|
||||
attribs->layout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
}
|
||||
|
|
|
@ -269,6 +269,15 @@ static bool vulkan_texture_init_view(struct wlr_vk_texture *texture) {
|
|||
VkResult res;
|
||||
VkDevice dev = texture->renderer->dev->dev;
|
||||
|
||||
struct wlr_vk_pipeline_layout *pipeline_layout = get_or_create_pipeline_layout(
|
||||
texture->renderer, &(struct wlr_vk_pipeline_layout_key) {
|
||||
.ycbcr_format = texture->format->is_ycbcr ? texture->format : NULL,
|
||||
});
|
||||
if (!pipeline_layout) {
|
||||
wlr_log(WLR_ERROR, "Failed to create a pipeline layout for a texture");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct wlr_pixel_format_info *format_info =
|
||||
drm_get_pixel_format_info(texture->format->drm);
|
||||
if (format_info != NULL) {
|
||||
|
@ -300,10 +309,10 @@ static bool vulkan_texture_init_view(struct wlr_vk_texture *texture) {
|
|||
|
||||
VkSamplerYcbcrConversionInfo ycbcr_conversion_info;
|
||||
if (texture->format->is_ycbcr) {
|
||||
assert(texture->pipeline_layout->ycbcr.conversion != VK_NULL_HANDLE);
|
||||
assert(pipeline_layout->ycbcr.conversion != VK_NULL_HANDLE);
|
||||
ycbcr_conversion_info = (VkSamplerYcbcrConversionInfo){
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
|
||||
.conversion = texture->pipeline_layout->ycbcr.conversion,
|
||||
.conversion = pipeline_layout->ycbcr.conversion,
|
||||
};
|
||||
view_info.pNext = &ycbcr_conversion_info;
|
||||
}
|
||||
|
@ -314,7 +323,7 @@ static bool vulkan_texture_init_view(struct wlr_vk_texture *texture) {
|
|||
return false;
|
||||
}
|
||||
|
||||
texture->ds_pool = vulkan_alloc_texture_ds(texture->renderer, texture->pipeline_layout->ds, &texture->ds);
|
||||
texture->ds_pool = vulkan_alloc_texture_ds(texture->renderer, pipeline_layout->ds, &texture->ds);
|
||||
if (!texture->ds_pool) {
|
||||
wlr_log(WLR_ERROR, "failed to allocate descriptor");
|
||||
return false;
|
||||
|
@ -360,7 +369,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(
|
|||
}
|
||||
|
||||
texture->format = &fmt->format;
|
||||
texture->pipeline_layout = &renderer->default_pipeline_layout;
|
||||
|
||||
VkImageCreateInfo img_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
|
@ -692,11 +700,6 @@ static struct wlr_vk_texture *vulkan_texture_from_dmabuf(
|
|||
texture->transform = !texture->format->is_ycbcr && texture->format->is_srgb ?
|
||||
WLR_VK_TEXTURE_TRANSFORM_IDENTITY : WLR_VK_TEXTURE_TRANSFORM_SRGB;
|
||||
|
||||
texture->pipeline_layout = vulkan_get_pipeline_layout(renderer, texture->format);
|
||||
if (texture->pipeline_layout == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
texture->image = vulkan_import_dmabuf(renderer, attribs,
|
||||
texture->memories, &texture->mem_count, false);
|
||||
if (!texture->image) {
|
||||
|
|
Loading…
Reference in a new issue