mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-04 20:55:58 +01:00
render/vulkan: Dynamically create texture views
Now that we are dynamically creating pipeline layouts, we need separate texture views for each pipeline layout we choose to use with a texture.
This commit is contained in:
parent
7c5a3afd60
commit
3ee0f52e09
4 changed files with 62 additions and 33 deletions
|
@ -295,12 +295,24 @@ struct wlr_vk_vert_pcr_data {
|
|||
float uv_size[2];
|
||||
};
|
||||
|
||||
struct wlr_vk_texture_view {
|
||||
struct wl_list link; // struct wlr_vk_texture.views
|
||||
const struct wlr_vk_pipeline_layout *layout;
|
||||
|
||||
VkDescriptorSet ds;
|
||||
VkImageView image_view;
|
||||
struct wlr_vk_descriptor_pool *ds_pool;
|
||||
};
|
||||
|
||||
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);
|
||||
struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(
|
||||
struct wlr_vk_texture *texture,
|
||||
const struct wlr_vk_pipeline_layout *layout);
|
||||
|
||||
// Creates a vulkan renderer for the given device.
|
||||
struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev);
|
||||
|
@ -373,11 +385,8 @@ struct wlr_vk_texture {
|
|||
uint32_t mem_count;
|
||||
VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES];
|
||||
VkImage image;
|
||||
VkImageView image_view;
|
||||
const struct wlr_vk_format *format;
|
||||
enum wlr_vk_texture_transform transform;
|
||||
VkDescriptorSet ds;
|
||||
struct wlr_vk_descriptor_pool *ds_pool;
|
||||
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
|
||||
|
@ -392,6 +401,8 @@ struct wlr_vk_texture {
|
|||
struct wlr_addon buffer_addon;
|
||||
// For DMA-BUF implicit sync interop
|
||||
VkSemaphore foreign_semaphores[WLR_DMABUF_MAX_PLANES];
|
||||
|
||||
struct wl_list views; // struct wlr_vk_texture_ds.link
|
||||
};
|
||||
|
||||
struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture);
|
||||
|
|
|
@ -555,10 +555,17 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
|||
return;
|
||||
}
|
||||
|
||||
struct wlr_vk_texture_view *view =
|
||||
vulkan_texture_get_or_create_view(texture, pipe->layout);
|
||||
if (!view) {
|
||||
pass->failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
bind_pipeline(pass, pipe->vk);
|
||||
|
||||
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipe->layout->vk, 0, 1, &texture->ds, 0, NULL);
|
||||
pipe->layout->vk, 0, 1, &view->ds, 0, NULL);
|
||||
|
||||
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
||||
|
|
|
@ -1419,13 +1419,19 @@ static bool vulkan_render_subtexture_with_matrix(struct wlr_renderer *wlr_render
|
|||
return false;
|
||||
}
|
||||
|
||||
struct wlr_vk_texture_view *view =
|
||||
vulkan_texture_get_or_create_view(texture, pipe->layout);
|
||||
if (!view) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pipe->vk != renderer->bound_pipe) {
|
||||
vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe->vk);
|
||||
renderer->bound_pipe = pipe->vk;
|
||||
}
|
||||
|
||||
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipe->layout->vk, 0, 1, &texture->ds, 0, NULL);
|
||||
pipe->layout->vk, 0, 1, &view->ds, 0, NULL);
|
||||
|
||||
float final_matrix[9];
|
||||
wlr_matrix_multiply(final_matrix, renderer->projection, matrix);
|
||||
|
|
|
@ -214,8 +214,12 @@ void vulkan_texture_destroy(struct wlr_vk_texture *texture) {
|
|||
wl_list_remove(&texture->link);
|
||||
|
||||
VkDevice dev = texture->renderer->dev->dev;
|
||||
if (texture->ds && texture->ds_pool) {
|
||||
vulkan_free_ds(texture->renderer, texture->ds_pool, texture->ds);
|
||||
|
||||
struct wlr_vk_texture_view *view, *tmp_view;
|
||||
wl_list_for_each_safe(view, tmp_view, &texture->views, link) {
|
||||
vulkan_free_ds(texture->renderer, view->ds_pool, view->ds);
|
||||
vkDestroyImageView(dev, view->image_view, NULL);
|
||||
free(view);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < WLR_DMABUF_MAX_PLANES; i++) {
|
||||
|
@ -224,7 +228,6 @@ void vulkan_texture_destroy(struct wlr_vk_texture *texture) {
|
|||
}
|
||||
}
|
||||
|
||||
vkDestroyImageView(dev, texture->image_view, NULL);
|
||||
vkDestroyImage(dev, texture->image, NULL);
|
||||
|
||||
for (unsigned i = 0u; i < texture->mem_count; ++i) {
|
||||
|
@ -262,22 +265,29 @@ static struct wlr_vk_texture *vulkan_texture_create(
|
|||
&texture_impl, width, height);
|
||||
texture->renderer = renderer;
|
||||
wl_list_insert(&renderer->textures, &texture->link);
|
||||
wl_list_init(&texture->views);
|
||||
return texture;
|
||||
}
|
||||
|
||||
static bool vulkan_texture_init_view(struct wlr_vk_texture *texture) {
|
||||
VkResult res;
|
||||
VkDevice dev = texture->renderer->dev->dev;
|
||||
struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_texture *texture,
|
||||
const struct wlr_vk_pipeline_layout *pipeline_layout) {
|
||||
struct wlr_vk_texture_view *view;
|
||||
wl_list_for_each(view, &texture->views, link) {
|
||||
if (view->layout == pipeline_layout) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
view = calloc(1, sizeof(*view));
|
||||
if (!view) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
view->layout = pipeline_layout;
|
||||
|
||||
VkResult res;
|
||||
VkDevice dev = texture->renderer->dev->dev;
|
||||
|
||||
const struct wlr_pixel_format_info *format_info =
|
||||
drm_get_pixel_format_info(texture->format->drm);
|
||||
if (format_info != NULL) {
|
||||
|
@ -317,20 +327,22 @@ static bool vulkan_texture_init_view(struct wlr_vk_texture *texture) {
|
|||
view_info.pNext = &ycbcr_conversion_info;
|
||||
}
|
||||
|
||||
res = vkCreateImageView(dev, &view_info, NULL, &texture->image_view);
|
||||
res = vkCreateImageView(dev, &view_info, NULL, &view->image_view);
|
||||
if (res != VK_SUCCESS) {
|
||||
free(view);
|
||||
wlr_vk_error("vkCreateImageView failed", res);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
texture->ds_pool = vulkan_alloc_texture_ds(texture->renderer, pipeline_layout->ds, &texture->ds);
|
||||
if (!texture->ds_pool) {
|
||||
view->ds_pool = vulkan_alloc_texture_ds(texture->renderer, pipeline_layout->ds, &view->ds);
|
||||
if (!view->ds_pool) {
|
||||
free(view);
|
||||
wlr_log(WLR_ERROR, "failed to allocate descriptor");
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VkDescriptorImageInfo ds_img_info = {
|
||||
.imageView = texture->image_view,
|
||||
.imageView = view->image_view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
|
||||
|
@ -338,13 +350,14 @@ static bool vulkan_texture_init_view(struct wlr_vk_texture *texture) {
|
|||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.dstSet = texture->ds,
|
||||
.dstSet = view->ds,
|
||||
.pImageInfo = &ds_img_info,
|
||||
};
|
||||
|
||||
vkUpdateDescriptorSets(dev, 1, &ds_write, 0, NULL);
|
||||
|
||||
return true;
|
||||
wl_list_insert(&texture->views, &view->link);
|
||||
return view;
|
||||
}
|
||||
|
||||
static struct wlr_texture *vulkan_texture_from_pixels(
|
||||
|
@ -419,10 +432,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (!vulkan_texture_init_view(texture)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
pixman_region32_t region;
|
||||
pixman_region32_init_rect(®ion, 0, 0, width, height);
|
||||
if (!write_pixels(texture, stride, ®ion, data, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
|
@ -706,10 +715,6 @@ static struct wlr_vk_texture *vulkan_texture_from_dmabuf(
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (!vulkan_texture_init_view(texture)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
texture->dmabuf_imported = true;
|
||||
|
||||
return texture;
|
||||
|
|
Loading…
Reference in a new issue