mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 12: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];
|
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_pipeline *setup_get_or_create_pipeline(
|
||||||
struct wlr_vk_render_format_setup *setup,
|
struct wlr_vk_render_format_setup *setup,
|
||||||
const struct wlr_vk_pipeline_key *key);
|
const struct wlr_vk_pipeline_key *key);
|
||||||
struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
|
struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
|
||||||
struct wlr_vk_renderer *renderer,
|
struct wlr_vk_renderer *renderer,
|
||||||
const struct wlr_vk_pipeline_layout_key *key);
|
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.
|
// Creates a vulkan renderer for the given device.
|
||||||
struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev);
|
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;
|
uint32_t mem_count;
|
||||||
VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES];
|
VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES];
|
||||||
VkImage image;
|
VkImage image;
|
||||||
VkImageView image_view;
|
|
||||||
const struct wlr_vk_format *format;
|
const struct wlr_vk_format *format;
|
||||||
enum wlr_vk_texture_transform transform;
|
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
|
struct wlr_vk_command_buffer *last_used_cb; // to track when it can be destroyed
|
||||||
bool dmabuf_imported;
|
bool dmabuf_imported;
|
||||||
bool owned; // if dmabuf_imported: whether we have ownership of the image
|
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;
|
struct wlr_addon buffer_addon;
|
||||||
// For DMA-BUF implicit sync interop
|
// For DMA-BUF implicit sync interop
|
||||||
VkSemaphore foreign_semaphores[WLR_DMABUF_MAX_PLANES];
|
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);
|
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;
|
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);
|
bind_pipeline(pass, pipe->vk);
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
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,
|
vkCmdPushConstants(cb, pipe->layout->vk,
|
||||||
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vert_pcr_data), &vert_pcr_data);
|
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;
|
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) {
|
if (pipe->vk != renderer->bound_pipe) {
|
||||||
vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe->vk);
|
vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe->vk);
|
||||||
renderer->bound_pipe = pipe->vk;
|
renderer->bound_pipe = pipe->vk;
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
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];
|
float final_matrix[9];
|
||||||
wlr_matrix_multiply(final_matrix, renderer->projection, matrix);
|
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);
|
wl_list_remove(&texture->link);
|
||||||
|
|
||||||
VkDevice dev = texture->renderer->dev->dev;
|
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++) {
|
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);
|
vkDestroyImage(dev, texture->image, NULL);
|
||||||
|
|
||||||
for (unsigned i = 0u; i < texture->mem_count; ++i) {
|
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_impl, width, height);
|
||||||
texture->renderer = renderer;
|
texture->renderer = renderer;
|
||||||
wl_list_insert(&renderer->textures, &texture->link);
|
wl_list_insert(&renderer->textures, &texture->link);
|
||||||
|
wl_list_init(&texture->views);
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool vulkan_texture_init_view(struct wlr_vk_texture *texture) {
|
struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_texture *texture,
|
||||||
VkResult res;
|
const struct wlr_vk_pipeline_layout *pipeline_layout) {
|
||||||
VkDevice dev = texture->renderer->dev->dev;
|
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(
|
view = calloc(1, sizeof(*view));
|
||||||
texture->renderer, &(struct wlr_vk_pipeline_layout_key) {
|
if (!view) {
|
||||||
.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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
view->layout = pipeline_layout;
|
||||||
|
|
||||||
|
VkResult res;
|
||||||
|
VkDevice dev = texture->renderer->dev->dev;
|
||||||
|
|
||||||
const struct wlr_pixel_format_info *format_info =
|
const struct wlr_pixel_format_info *format_info =
|
||||||
drm_get_pixel_format_info(texture->format->drm);
|
drm_get_pixel_format_info(texture->format->drm);
|
||||||
if (format_info != NULL) {
|
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;
|
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) {
|
if (res != VK_SUCCESS) {
|
||||||
|
free(view);
|
||||||
wlr_vk_error("vkCreateImageView failed", res);
|
wlr_vk_error("vkCreateImageView failed", res);
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
texture->ds_pool = vulkan_alloc_texture_ds(texture->renderer, pipeline_layout->ds, &texture->ds);
|
view->ds_pool = vulkan_alloc_texture_ds(texture->renderer, pipeline_layout->ds, &view->ds);
|
||||||
if (!texture->ds_pool) {
|
if (!view->ds_pool) {
|
||||||
|
free(view);
|
||||||
wlr_log(WLR_ERROR, "failed to allocate descriptor");
|
wlr_log(WLR_ERROR, "failed to allocate descriptor");
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDescriptorImageInfo ds_img_info = {
|
VkDescriptorImageInfo ds_img_info = {
|
||||||
.imageView = texture->image_view,
|
.imageView = view->image_view,
|
||||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
.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,
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
.descriptorCount = 1,
|
.descriptorCount = 1,
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||||
.dstSet = texture->ds,
|
.dstSet = view->ds,
|
||||||
.pImageInfo = &ds_img_info,
|
.pImageInfo = &ds_img_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkUpdateDescriptorSets(dev, 1, &ds_write, 0, NULL);
|
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(
|
static struct wlr_texture *vulkan_texture_from_pixels(
|
||||||
|
@ -419,10 +432,6 @@ static struct wlr_texture *vulkan_texture_from_pixels(
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vulkan_texture_init_view(texture)) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixman_region32_t region;
|
pixman_region32_t region;
|
||||||
pixman_region32_init_rect(®ion, 0, 0, width, height);
|
pixman_region32_init_rect(®ion, 0, 0, width, height);
|
||||||
if (!write_pixels(texture, stride, ®ion, data, VK_IMAGE_LAYOUT_UNDEFINED,
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vulkan_texture_init_view(texture)) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture->dmabuf_imported = true;
|
texture->dmabuf_imported = true;
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
|
|
Loading…
Reference in a new issue