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.
This commit is contained in:
Benjamin Otte
2023-10-19 13:30:12 +02:00
parent bf39fa3b3b
commit 03f820d26c
3 changed files with 74 additions and 14 deletions

View File

@@ -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);
}

View File

@@ -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)
{

View File

@@ -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);