From 03f820d26c107cdc67ba2b49d98f812a0a41394b Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 19 Oct 2023 13:30:12 +0200 Subject: [PATCH] gpu: Add support for immutable samplers to Vulkan Images can now have samplers - meaning they must be rendered with that sampler. It also means that sampler must be handled as an immutable sampler in descriptorsets. These samplers can be created with a samplerYcbcrConversion, so code has been added to pass that conversion when creating the imageview. Also add code to GskVulkanFrame to track immutable samplers. Nobody is making use of this yet. --- gsk/gpu/gskvulkanframe.c | 72 +++++++++++++++++++++++++++------ gsk/gpu/gskvulkanimage.c | 15 ++++++- gsk/gpu/gskvulkanimageprivate.h | 1 + 3 files changed, 74 insertions(+), 14 deletions(-) diff --git a/gsk/gpu/gskvulkanframe.c b/gsk/gpu/gskvulkanframe.c index 1da12e34e4..c4ff64a52e 100644 --- a/gsk/gpu/gskvulkanframe.c +++ b/gsk/gpu/gskvulkanframe.c @@ -26,11 +26,21 @@ #define GDK_ARRAY_NO_MEMSET 1 #include "gdk/gdkarrayimpl.c" +#define GDK_ARRAY_NAME gsk_samplers +#define GDK_ARRAY_TYPE_NAME GskSamplers +#define GDK_ARRAY_ELEMENT_TYPE VkSampler +#define GDK_ARRAY_NULL_TERMINATED 1 +#define GDK_ARRAY_PREALLOC 31 +#define GDK_ARRAY_NO_MEMSET 1 +#include "gdk/gdkarrayimpl.c" + struct _GskVulkanFrame { GskGpuFrame parent_instance; GskVulkanPipelineLayout *pipeline_layout; + GskSamplers immutable_samplers; + GskDescriptorImageInfos descriptor_immutable_images; GskDescriptorImageInfos descriptor_images; GskDescriptorBufferInfos descriptor_buffers; @@ -134,6 +144,8 @@ gsk_vulkan_frame_cleanup (GskGpuFrame *frame) GSK_VK_CHECK (vkResetDescriptorPool, vk_device, self->vk_descriptor_pool, 0); + gsk_samplers_set_size (&self->immutable_samplers, 0); + gsk_descriptor_image_infos_set_size (&self->descriptor_immutable_images, 0); gsk_descriptor_image_infos_set_size (&self->descriptor_images, 0); gsk_descriptor_buffer_infos_set_size (&self->descriptor_buffers, 0); @@ -148,21 +160,38 @@ gsk_vulkan_frame_add_image (GskVulkanFrame *self, GskGpuImage *image, GskGpuSampler sampler) { + GskVulkanImage *vulkan_image = GSK_VULKAN_IMAGE (image); GskVulkanDevice *device; + VkSampler vk_sampler; guint32 result; device = GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (GSK_GPU_FRAME (self))); + vk_sampler = gsk_vulkan_image_get_vk_sampler (vulkan_image); - result = gsk_descriptor_image_infos_get_size (&self->descriptor_images); - g_assert (result < gsk_vulkan_device_get_max_descriptors (device)); - result = result << 1; + if (vk_sampler) + { + result = gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images) << 1 | 1; - gsk_descriptor_image_infos_append (&self->descriptor_images, - &(VkDescriptorImageInfo) { - .sampler = gsk_vulkan_device_get_vk_sampler (device, sampler), - .imageView = gsk_vulkan_image_get_vk_image_view (GSK_VULKAN_IMAGE (image)), - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL - }); + gsk_samplers_append (&self->immutable_samplers, vk_sampler); + gsk_descriptor_image_infos_append (&self->descriptor_immutable_images, + &(VkDescriptorImageInfo) { + .imageView = gsk_vulkan_image_get_vk_image_view (vulkan_image), + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + }); + } + else + { + result = gsk_descriptor_image_infos_get_size (&self->descriptor_images); + g_assert (result < gsk_vulkan_device_get_max_descriptors (device)); + result = result << 1; + + gsk_descriptor_image_infos_append (&self->descriptor_images, + &(VkDescriptorImageInfo) { + .sampler = gsk_vulkan_device_get_vk_sampler (device, sampler), + .imageView = gsk_vulkan_image_get_vk_image_view (vulkan_image), + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL + }); + } return result; } @@ -189,7 +218,7 @@ gsk_vulkan_frame_prepare_descriptor_sets (GskVulkanFrame *self) { GskVulkanDevice *device; VkDevice vk_device; - VkWriteDescriptorSet write_descriptor_sets[GSK_VULKAN_N_DESCRIPTOR_SETS]; + VkWriteDescriptorSet write_descriptor_sets[GSK_VULKAN_N_DESCRIPTOR_SETS + 1]; gsize n_descriptor_sets; VkDescriptorSet descriptor_sets[GSK_VULKAN_N_DESCRIPTOR_SETS]; @@ -209,7 +238,8 @@ gsk_vulkan_frame_prepare_descriptor_sets (GskVulkanFrame *self) .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO, .descriptorSetCount = GSK_VULKAN_N_DESCRIPTOR_SETS, .pDescriptorCounts = (uint32_t[GSK_VULKAN_N_DESCRIPTOR_SETS]) { - MAX (1, gsk_descriptor_image_infos_get_size (&self->descriptor_images)), + MAX (1, gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images) + + gsk_descriptor_image_infos_get_size (&self->descriptor_images)), MAX (1, gsk_descriptor_buffer_infos_get_size (&self->descriptor_buffers)) } } @@ -217,6 +247,18 @@ gsk_vulkan_frame_prepare_descriptor_sets (GskVulkanFrame *self) descriptor_sets); n_descriptor_sets = 0; + if (gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images) > 0) + { + write_descriptor_sets[n_descriptor_sets++] = (VkWriteDescriptorSet) { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = descriptor_sets[GSK_VULKAN_IMAGE_SET_LAYOUT], + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_immutable_images), + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_immutable_images) + }; + } if (gsk_descriptor_image_infos_get_size (&self->descriptor_images) > 0) { write_descriptor_sets[n_descriptor_sets++] = (VkWriteDescriptorSet) { @@ -293,8 +335,8 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame, } self->pipeline_layout = gsk_vulkan_device_acquire_pipeline_layout (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame)), - NULL, - 0); + gsk_samplers_get_data (&self->immutable_samplers), + gsk_samplers_get_size (&self->immutable_samplers)); GSK_VK_CHECK (vkBeginCommandBuffer, self->vk_command_buffer, &(VkCommandBufferBeginInfo) { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -344,6 +386,8 @@ gsk_vulkan_frame_finalize (GObject *object) vkDestroyDescriptorPool (vk_device, self->vk_descriptor_pool, NULL); + gsk_samplers_clear (&self->immutable_samplers); + gsk_descriptor_image_infos_clear (&self->descriptor_immutable_images); gsk_descriptor_image_infos_clear (&self->descriptor_images); gsk_descriptor_buffer_infos_clear (&self->descriptor_buffers); @@ -377,6 +421,8 @@ gsk_vulkan_frame_class_init (GskVulkanFrameClass *klass) static void gsk_vulkan_frame_init (GskVulkanFrame *self) { + gsk_samplers_init (&self->immutable_samplers); + gsk_descriptor_image_infos_init (&self->descriptor_immutable_images); gsk_descriptor_image_infos_init (&self->descriptor_images); gsk_descriptor_buffer_infos_init (&self->descriptor_buffers); } diff --git a/gsk/gpu/gskvulkanimage.c b/gsk/gpu/gskvulkanimage.c index 1fd0491ede..39f313e094 100644 --- a/gsk/gpu/gskvulkanimage.c +++ b/gsk/gpu/gskvulkanimage.c @@ -23,6 +23,7 @@ struct _GskVulkanImage VkImage vk_image; VkImageView vk_image_view; VkFramebuffer vk_framebuffer; + VkSampler vk_sampler; GskVulkanImagePostprocess postprocess; VkPipelineStageFlags vk_pipeline_stage; @@ -518,6 +519,7 @@ gsk_vulkan_device_supports_format (GskVulkanDevice *device, static void gsk_vulkan_image_create_view (GskVulkanImage *self, + VkSamplerYcbcrConversion vk_conversion, const GskMemoryFormatInfo *format) { GSK_VK_CHECK (vkCreateImageView, self->display->vk_device, @@ -534,6 +536,10 @@ gsk_vulkan_image_create_view (GskVulkanImage *self, .baseArrayLayer = 0, .layerCount = 1, }, + .pNext = vk_conversion == VK_NULL_HANDLE ? NULL : &(VkSamplerYcbcrConversionInfo) { + .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, + .conversion = vk_conversion + } }, NULL, &self->vk_image_view); @@ -649,7 +655,7 @@ gsk_vulkan_image_new (GskVulkanDevice *device, self->allocation.vk_memory, self->allocation.offset); - gsk_vulkan_image_create_view (self, vk_format); + gsk_vulkan_image_create_view (self, VK_NULL_HANDLE, vk_format); return self; } @@ -740,6 +746,7 @@ gsk_vulkan_image_new_for_swapchain (GskVulkanDevice *device, gsk_gpu_image_setup (GSK_GPU_IMAGE (self), GDK_MEMORY_DEFAULT, width, height); gsk_vulkan_image_create_view (self, + VK_NULL_HANDLE, &(GskMemoryFormatInfo) { format, { VK_COMPONENT_SWIZZLE_R, @@ -895,6 +902,12 @@ gsk_vulkan_image_get_postprocess (GskVulkanImage *self) return self->postprocess; } +VkSampler +gsk_vulkan_image_get_vk_sampler (GskVulkanImage *self) +{ + return self->vk_sampler; +} + VkImage gsk_vulkan_image_get_vk_image (GskVulkanImage *self) { diff --git a/gsk/gpu/gskvulkanimageprivate.h b/gsk/gpu/gskvulkanimageprivate.h index 85fba730c8..678dc02129 100644 --- a/gsk/gpu/gskvulkanimageprivate.h +++ b/gsk/gpu/gskvulkanimageprivate.h @@ -38,6 +38,7 @@ guchar * gsk_vulkan_image_get_data (GskVulk GskVulkanImagePostprocess gsk_vulkan_image_get_postprocess (GskVulkanImage *self); +VkSampler gsk_vulkan_image_get_vk_sampler (GskVulkanImage *self); VkPipelineStageFlags gsk_vulkan_image_get_vk_pipeline_stage (GskVulkanImage *self); VkImageLayout gsk_vulkan_image_get_vk_image_layout (GskVulkanImage *self); VkAccessFlags gsk_vulkan_image_get_vk_access (GskVulkanImage *self);