vulkan: Implement bindless texture rendering
authorBenjamin Otte <otte@redhat.com>
Sat, 20 May 2023 00:56:02 +0000 (02:56 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 4 Jun 2023 17:42:01 +0000 (19:42 +0200)
Instead of having a descriptor set per operation, we just have one
descriptor set and bind all our images into it.

Then the shaders get to use an index into the large texture array
instead.

Getting this to work - because it's a Vulkan extension that needs to be
manually enabled, even though it's officially part of Vulkan 1.2 - is
insane.

32 files changed:
gdk/gdkvulkancontext.c
gsk/vulkan/gskvulkanblendmodepipeline.c
gsk/vulkan/gskvulkanblendmodepipelineprivate.h
gsk/vulkan/gskvulkanblurpipeline.c
gsk/vulkan/gskvulkanblurpipelineprivate.h
gsk/vulkan/gskvulkancolortextpipeline.c
gsk/vulkan/gskvulkancolortextpipelineprivate.h
gsk/vulkan/gskvulkancrossfadepipeline.c
gsk/vulkan/gskvulkancrossfadepipelineprivate.h
gsk/vulkan/gskvulkaneffectpipeline.c
gsk/vulkan/gskvulkaneffectpipelineprivate.h
gsk/vulkan/gskvulkanrender.c
gsk/vulkan/gskvulkanrenderpass.c
gsk/vulkan/gskvulkanrenderprivate.h
gsk/vulkan/gskvulkantextpipeline.c
gsk/vulkan/gskvulkantextpipelineprivate.h
gsk/vulkan/gskvulkantexturepipeline.c
gsk/vulkan/gskvulkantexturepipelineprivate.h
gsk/vulkan/resources/blendmode.frag
gsk/vulkan/resources/blendmode.vert
gsk/vulkan/resources/blur.frag
gsk/vulkan/resources/blur.vert
gsk/vulkan/resources/color-matrix.frag
gsk/vulkan/resources/color-matrix.vert
gsk/vulkan/resources/common.frag.glsl [new file with mode: 0644]
gsk/vulkan/resources/crossfade.frag
gsk/vulkan/resources/crossfade.vert
gsk/vulkan/resources/mask.frag
gsk/vulkan/resources/mask.vert
gsk/vulkan/resources/meson.build
gsk/vulkan/resources/texture.frag
gsk/vulkan/resources/texture.vert

index eb9b8ad83ab9c8e0da020875bd3f6dc5de15de8c..93bf2ce917f4f52dd35ea63100ca8068970425ac 100644 (file)
@@ -1053,26 +1053,30 @@ gdk_display_create_vulkan_device (GdkDisplay  *display,
 
               device_extensions = g_ptr_array_new ();
               g_ptr_array_add (device_extensions, (gpointer) VK_KHR_SWAPCHAIN_EXTENSION_NAME);
+              g_ptr_array_add (device_extensions, (gpointer) VK_KHR_MAINTENANCE_3_EXTENSION_NAME);
+              g_ptr_array_add (device_extensions, (gpointer) VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME);
               if (has_incremental_present)
                 g_ptr_array_add (device_extensions, (gpointer) VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
 
               GDK_DISPLAY_DEBUG (display, VULKAN, "Using Vulkan device %u, queue %u", i, j);
               if (GDK_VK_CHECK (vkCreateDevice, devices[i],
                                                 &(VkDeviceCreateInfo) {
-                                                    VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
-                                                    NULL,
-                                                    0,
-                                                    1,
-                                                    &(VkDeviceQueueCreateInfo) {
+                                                    .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+                                                    .queueCreateInfoCount = 1,
+                                                    .pQueueCreateInfos = &(VkDeviceQueueCreateInfo) {
                                                         .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
                                                         .queueFamilyIndex = j,
                                                         .queueCount = 1,
                                                         .pQueuePriorities = (float []) { 1.0f },
                                                     },
-                                                    0,
-                                                    NULL,
-                                                    device_extensions->len,
-                                                    (const char * const *) device_extensions->pdata
+                                                    .enabledExtensionCount = device_extensions->len,
+                                                    .ppEnabledExtensionNames = (const char * const *) device_extensions->pdata,
+                                                    .pNext = &(VkPhysicalDeviceDescriptorIndexingFeatures) {
+                                                      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES,
+                                                      .descriptorBindingPartiallyBound = VK_TRUE,
+                                                      .descriptorBindingVariableDescriptorCount = VK_TRUE,
+                                                      .descriptorBindingSampledImageUpdateAfterBind = VK_TRUE,
+                                                    }
                                                 },
                                                 NULL,
                                                 &display->vk_device) != VK_SUCCESS)
@@ -1144,6 +1148,7 @@ gdk_display_create_vulkan_instance (GdkDisplay  *display,
 
   used_extensions = g_ptr_array_new ();
   g_ptr_array_add (used_extensions, (gpointer) VK_KHR_SURFACE_EXTENSION_NAME);
+  g_ptr_array_add (used_extensions, (gpointer) VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
   g_ptr_array_add (used_extensions, (gpointer) GDK_DISPLAY_GET_CLASS (display)->vk_extension_name);
 
   for (i = 0; i < n_extensions; i++)
@@ -1215,7 +1220,7 @@ gdk_display_create_vulkan_instance (GdkDisplay  *display,
                                              .enabledLayerCount = used_layers->len,
                                              .ppEnabledLayerNames = (const char * const *) used_layers->pdata,
                                              .enabledExtensionCount = used_extensions->len,
-                                             .ppEnabledExtensionNames = (const char * const *) used_extensions->pdata
+                                             .ppEnabledExtensionNames = (const char * const *) used_extensions->pdata,
                                          },
                                          NULL,
                                          &display->vk_instance);
index bbd649701d679d193314d249f716adc0dc31f53b..e9ea9c2dc701300fd083a60c392336deb3d4aebd 100644 (file)
@@ -14,6 +14,8 @@ struct _GskVulkanBlendModeInstance
   float rect[4];
   float start_tex_rect[4];
   float end_tex_rect[4];
+  guint32 start_tex_id;
+  guint32 end_tex_id;
   guint32 blend_mode;
 };
 
@@ -52,6 +54,18 @@ gsk_vulkan_blend_mode_pipeline_get_input_state_create_info (GskVulkanPipeline *s
           .location = 3,
           .binding = 0,
           .format = VK_FORMAT_R32_UINT,
+          .offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, start_tex_id),
+      },
+      {
+          .location = 4,
+          .binding = 0,
+          .format = VK_FORMAT_R32_UINT,
+          .offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, end_tex_id),
+      },
+      {
+          .location = 5,
+          .binding = 0,
+          .format = VK_FORMAT_R32_UINT,
           .offset = G_STRUCT_OFFSET (GskVulkanBlendModeInstance, blend_mode),
       }
   };
@@ -101,6 +115,8 @@ gsk_vulkan_blend_mode_pipeline_new (GdkVulkanContext        *context,
 void
 gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GskVulkanBlendModePipeline *pipeline,
                                                     guchar                     *data,
+                                                    guint32                     start_tex_id,
+                                                    guint32                     end_tex_id,
                                                     const graphene_point_t     *offset,
                                                     const graphene_rect_t      *bounds,
                                                     const graphene_rect_t      *start_tex_rect,
@@ -124,6 +140,8 @@ gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GskVulkanBlendModePipeline *
   instance->end_tex_rect[2] = end_tex_rect->size.width;
   instance->end_tex_rect[3] = end_tex_rect->size.height;
 
+  instance->start_tex_id = start_tex_id;
+  instance->end_tex_id = end_tex_id;
   instance->blend_mode = blend_mode;
 }
 
index 00d28994f8bc4c736cbd465f67961369e43dfb4d..94d565d9752dd59e490f6fb6d1c80509bb41771e 100644 (file)
@@ -20,6 +20,8 @@ GskVulkanPipeline * gsk_vulkan_blend_mode_pipeline_new                 (GdkVulka
 
 void                gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GskVulkanBlendModePipeline *pipeline,
                                                                         guchar                     *data,
+                                                                        guint32                     start_tex_id,
+                                                                        guint32                     end_tex_id,
                                                                         const graphene_point_t     *offset,
                                                                         const graphene_rect_t      *bounds,
                                                                         const graphene_rect_t      *start_bounds,
index 48705a92ac25dfe0cb37d5887a93d48175154513..462d8c50459a2025cb1087d5041f44757e552e77 100644 (file)
@@ -14,6 +14,7 @@ struct _GskVulkanBlurInstance
   float rect[4];
   float tex_rect[4];
   float blur_radius;
+  guint32 tex_id;
 };
 
 G_DEFINE_TYPE (GskVulkanBlurPipeline, gsk_vulkan_blur_pipeline, GSK_TYPE_VULKAN_PIPELINE)
@@ -46,6 +47,12 @@ gsk_vulkan_blur_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
           .binding = 0,
           .format = VK_FORMAT_R32_SFLOAT,
           .offset = G_STRUCT_OFFSET (GskVulkanBlurInstance, blur_radius),
+      },
+      {
+          .location = 3,
+          .binding = 0,
+          .format = VK_FORMAT_R32_UINT,
+          .offset = G_STRUCT_OFFSET (GskVulkanBlurInstance, tex_id),
       }
   };
   static const VkPipelineVertexInputStateCreateInfo info = {
@@ -94,6 +101,7 @@ gsk_vulkan_blur_pipeline_new (GdkVulkanContext        *context,
 void
 gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline  *pipeline,
                                               guchar                 *data,
+                                              guint32                 tex_id,
                                               const graphene_point_t *offset,
                                               const graphene_rect_t  *rect,
                                               const graphene_rect_t  *tex_rect,
@@ -110,6 +118,7 @@ gsk_vulkan_blur_pipeline_collect_vertex_data (GskVulkanBlurPipeline  *pipeline,
   instance->tex_rect[2] = tex_rect->size.width;
   instance->tex_rect[3] = tex_rect->size.height;
   instance->blur_radius = blur_radius;
+  instance->tex_id = tex_id;
 }
 
 gsize
index 278c8a8b5cc03f0266f4fbee16e9e20a44085a1b..5e7435aba63ce598a0057d0d71fcc14336292552 100644 (file)
@@ -19,6 +19,7 @@ GskVulkanPipeline *     gsk_vulkan_blur_pipeline_new                   (GdkVulka
 
 void                    gsk_vulkan_blur_pipeline_collect_vertex_data   (GskVulkanBlurPipeline   *pipeline,
                                                                         guchar                  *data,
+                                                                        guint32                  tex_id,
                                                                         const graphene_point_t  *offset,
                                                                         const graphene_rect_t   *rect,
                                                                         const graphene_rect_t   *tex_rect,
index 2922c06a7f841316a642fd267ddad214cc5352e0..1a8515b9429de39ff0a4510fd39f113aac1c818e 100644 (file)
@@ -13,6 +13,7 @@ struct _GskVulkanColorTextInstance
 {
   float rect[4];
   float tex_rect[4];
+  guint32 tex_id;
 };
 
 G_DEFINE_TYPE (GskVulkanColorTextPipeline, gsk_vulkan_color_text_pipeline, GSK_TYPE_VULKAN_PIPELINE)
@@ -40,6 +41,12 @@ gsk_vulkan_color_text_pipeline_get_input_state_create_info (GskVulkanPipeline *s
           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
           .offset = G_STRUCT_OFFSET (GskVulkanColorTextInstance, tex_rect),
       },
+      {
+          .location = 2,
+          .binding = 0,
+          .format = VK_FORMAT_R32_UINT,
+          .offset = G_STRUCT_OFFSET (GskVulkanColorTextInstance, tex_id),
+      }
   };
   static const VkPipelineVertexInputStateCreateInfo info = {
       .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
@@ -89,6 +96,7 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
                                                     guchar                     *data,
                                                     GskVulkanRenderer          *renderer,
                                                     const graphene_rect_t      *rect,
+                                                    guint                       tex_id,
                                                     PangoFont                  *font,
                                                     guint                       total_glyphs,
                                                     const PangoGlyphInfo       *glyphs,
@@ -133,6 +141,8 @@ gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *
           instance->tex_rect[2] = glyph->tw;
           instance->tex_rect[3] = glyph->th;
 
+          instance->tex_id = tex_id;
+
           count++;
        }
      x_position += gi->geometry.width;
index c5670ea22c3b570bbde5bea77e9713b806689fd6..00943987852aaf55a321b28a9d4885cb05ca255f 100644 (file)
@@ -22,6 +22,7 @@ void                    gsk_vulkan_color_text_pipeline_collect_vertex_data   (Gs
                                                                               guchar                         *data,
                                                                               GskVulkanRenderer              *renderer,
                                                                               const graphene_rect_t          *rect,
+                                                                              guint                           tex_id,
                                                                               PangoFont                      *font,
                                                                               guint                           total_glyphs,
                                                                               const PangoGlyphInfo           *glyphs,
index bdcf07acb9842772f1dca30bd4a2181d99cbcd65..9763aa762f27260bfd25eac84539993fcc12b21a 100644 (file)
@@ -14,6 +14,8 @@ struct _GskVulkanCrossFadeInstance
   float rect[4];
   float start_tex_rect[4];
   float end_tex_rect[4];
+  float start_tex_id;
+  float end_tex_id;
   float progress;
 };
 
@@ -51,6 +53,18 @@ gsk_vulkan_cross_fade_pipeline_get_input_state_create_info (GskVulkanPipeline *s
       {
           .location = 3,
           .binding = 0,
+          .format = VK_FORMAT_R32_UINT,
+          .offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, start_tex_id),
+      },
+      {
+          .location = 4,
+          .binding = 0,
+          .format = VK_FORMAT_R32_UINT,
+          .offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, end_tex_id),
+      },
+      {
+          .location = 5,
+          .binding = 0,
           .format = VK_FORMAT_R32_SFLOAT,
           .offset = G_STRUCT_OFFSET (GskVulkanCrossFadeInstance, progress),
       }
@@ -101,6 +115,8 @@ gsk_vulkan_cross_fade_pipeline_new (GdkVulkanContext        *context,
 void
 gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GskVulkanCrossFadePipeline *pipeline,
                                                     guchar                     *data,
+                                                    guint32                     start_tex_id,
+                                                    guint32                     end_tex_id,
                                                     const graphene_point_t     *offset,
                                                     const graphene_rect_t      *bounds,
                                                     const graphene_rect_t      *start_tex_rect,
@@ -124,6 +140,8 @@ gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GskVulkanCrossFadePipeline *
   instance->end_tex_rect[2] = end_tex_rect->size.width;
   instance->end_tex_rect[3] = end_tex_rect->size.height;
 
+  instance->start_tex_id = start_tex_id;
+  instance->end_tex_id = end_tex_id;
   instance->progress = progress;
 }
 
index 7b8b6d8f96ef93622ef11bcf94d613fee5506eed..f4249318cc44868652def5a3961521f7f7ac72db 100644 (file)
@@ -19,6 +19,8 @@ GskVulkanPipeline * gsk_vulkan_cross_fade_pipeline_new                 (GdkVulka
 
 void                gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GskVulkanCrossFadePipeline *pipeline,
                                                                         guchar                     *data,
+                                                                        guint32                     start_tex_id,
+                                                                        guint32                     end_tex_id,
                                                                         const graphene_point_t     *offset,
                                                                         const graphene_rect_t      *bounds,
                                                                         const graphene_rect_t      *start_bounds,
index 3faf769276fc9cc566ba56d52571aefd9090c246..578a47d44c01769d6f1b48aa725f054b2f8080a6 100644 (file)
@@ -15,6 +15,7 @@ struct _GskVulkanEffectInstance
   float tex_rect[4];
   float color_matrix[16];
   float color_offset[4];
+  guint32 tex_id;
 };
 
 G_DEFINE_TYPE (GskVulkanEffectPipeline, gsk_vulkan_effect_pipeline, GSK_TYPE_VULKAN_PIPELINE)
@@ -71,6 +72,12 @@ gsk_vulkan_effect_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
           .binding = 0,
           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
           .offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, color_offset),
+      },
+      {
+          .location = 7,
+          .binding = 0,
+          .format = VK_FORMAT_R32_UINT,
+          .offset = G_STRUCT_OFFSET (GskVulkanEffectInstance, tex_id),
       }
   };
   static const VkPipelineVertexInputStateCreateInfo info = {
@@ -119,6 +126,7 @@ gsk_vulkan_effect_pipeline_new (GdkVulkanContext        *context,
 void
 gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipeline,
                                                 guchar                  *data,
+                                                guint32                  tex_id,
                                                 const graphene_point_t  *offset,
                                                 const graphene_rect_t   *rect,
                                                 const graphene_rect_t   *tex_rect,
@@ -137,6 +145,7 @@ gsk_vulkan_effect_pipeline_collect_vertex_data (GskVulkanEffectPipeline *pipelin
   instance->tex_rect[3] = tex_rect->size.height;
   graphene_matrix_to_float (color_matrix, instance->color_matrix);
   graphene_vec4_to_float (color_offset, instance->color_offset);
+  instance->tex_id = tex_id;
 }
 
 gsize
index ecd1df2667c9e839738b18be26e061b144a1ed4f..f7239386bdfe74cee302967104202a8e900888c0 100644 (file)
@@ -19,6 +19,7 @@ GskVulkanPipeline *     gsk_vulkan_effect_pipeline_new                  (GdkVulk
 
 void                    gsk_vulkan_effect_pipeline_collect_vertex_data  (GskVulkanEffectPipeline        *pipeline,
                                                                          guchar                         *data,
+                                                                         guint32                         tex_id,
                                                                          const graphene_point_t         *offset,
                                                                          const graphene_rect_t          *rect,
                                                                          const graphene_rect_t          *tex_rect,
index 333941a681f6237c6c197412c9a0534bed4e8b28..441e0f6a6b84295f9f30d20958e3e8369e86a049 100644 (file)
 #include "gskvulkantexturepipelineprivate.h"
 #include "gskvulkanpushconstantsprivate.h"
 
-#define DESCRIPTOR_POOL_MAXSETS 128
-#define DESCRIPTOR_POOL_MAXSETS_INCREASE 128
+#define DESCRIPTOR_POOL_MAXITEMS 50000
+
+#define GDK_ARRAY_NAME gsk_descriptor_image_infos
+#define GDK_ARRAY_TYPE_NAME GskDescriptorImageInfos
+#define GDK_ARRAY_ELEMENT_TYPE VkDescriptorImageInfo
+#define GDK_ARRAY_BY_VALUE 1
+#define GDK_ARRAY_PREALLOC 1024
+#define GDK_ARRAY_NO_MEMSET 1
+#include "gdk/gdkarrayimpl.c"
 
 struct _GskVulkanRender
 {
@@ -43,11 +50,9 @@ struct _GskVulkanRender
   VkPipelineLayout pipeline_layout;
   GskVulkanUploader *uploader;
 
-  GHashTable *descriptor_set_indexes;
+  GskDescriptorImageInfos descriptor_image_infos;
   VkDescriptorPool descriptor_pool;
-  uint32_t descriptor_pool_maxsets;
-  VkDescriptorSet *descriptor_sets;
-  gsize n_descriptor_sets;
+  VkDescriptorSet descriptor_set;
   GskVulkanPipeline *pipelines[GSK_VULKAN_N_PIPELINES];
 
   GskVulkanImage *target;
@@ -103,9 +108,6 @@ gsk_vulkan_render_setup (GskVulkanRender       *self,
     }
 }
 
-static guint desc_set_index_hash (gconstpointer v);
-static gboolean desc_set_index_equal (gconstpointer v1, gconstpointer v2);
-
 GskVulkanRender *
 gsk_vulkan_render_new (GskRenderer      *renderer,
                        GdkVulkanContext *context)
@@ -118,7 +120,7 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
   self->vulkan = context;
   self->renderer = renderer;
   self->framebuffers = g_hash_table_new (g_direct_hash, g_direct_equal);
-  self->descriptor_set_indexes = g_hash_table_new_full (desc_set_index_hash, desc_set_index_equal, NULL, g_free);
+  gsk_descriptor_image_infos_init (&self->descriptor_image_infos);
 
   device = gdk_vulkan_context_get_device (self->vulkan);
 
@@ -131,16 +133,16 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
                                NULL,
                                &self->fence);
 
-  self->descriptor_pool_maxsets = DESCRIPTOR_POOL_MAXSETS;
   GSK_VK_CHECK (vkCreateDescriptorPool, device,
                                         &(VkDescriptorPoolCreateInfo) {
                                             .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
-                                            .maxSets = self->descriptor_pool_maxsets,
+                                            .flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
+                                            .maxSets = 1,
                                             .poolSizeCount = 1,
                                             .pPoolSizes = (VkDescriptorPoolSize[1]) {
                                                 {
                                                     .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-                                                    .descriptorCount = self->descriptor_pool_maxsets
+                                                    .descriptorCount = DESCRIPTOR_POOL_MAXITEMS
                                                 }
                                             }
                                         },
@@ -191,13 +193,23 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
                                              &(VkDescriptorSetLayoutCreateInfo) {
                                                  .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
                                                  .bindingCount = 1,
+                                                 .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
                                                  .pBindings = (VkDescriptorSetLayoutBinding[1]) {
                                                      {
                                                          .binding = 0,
                                                          .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-                                                         .descriptorCount = 1,
+                                                         .descriptorCount = DESCRIPTOR_POOL_MAXITEMS,
                                                          .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
                                                      }
+                                                 },
+                                                 .pNext = &(VkDescriptorSetLayoutBindingFlagsCreateInfo) {
+                                                   .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
+                                                   .bindingCount = 1,
+                                                   .pBindingFlags = &(VkDescriptorBindingFlags) {
+                                                     VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT
+                                                     | VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT
+                                                     | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
+                                                   },
                                                  }
                                              },
                                              NULL,
@@ -206,9 +218,8 @@ gsk_vulkan_render_new (GskRenderer      *renderer,
   GSK_VK_CHECK (vkCreatePipelineLayout, device,
                                         &(VkPipelineLayoutCreateInfo) {
                                             .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
-                                            .setLayoutCount = 2,
-                                            .pSetLayouts = (VkDescriptorSetLayout[2]) {
-                                              self->descriptor_set_layout,
+                                            .setLayoutCount = 1,
+                                            .pSetLayouts = (VkDescriptorSetLayout[1]) {
                                               self->descriptor_set_layout
                                             },
                                             .pushConstantRangeCount = gsk_vulkan_push_constants_get_range_count (),
@@ -425,35 +436,9 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender       *self,
 }
 
 VkDescriptorSet
-gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self,
-                                      gsize            id)
+gsk_vulkan_render_get_descriptor_set (GskVulkanRender *self)
 {
-  g_assert (id < self->n_descriptor_sets);
-
-  return self->descriptor_sets[id];
-}
-
-typedef struct {
-  gsize index;
-  GskVulkanImage *image;
-  gboolean repeat;
-} HashDescriptorSetIndexEntry;
-
-static guint
-desc_set_index_hash (gconstpointer v)
-{
-  const HashDescriptorSetIndexEntry *e = v;
-
-  return GPOINTER_TO_UINT (e->image) + e->repeat;
-}
-
-static gboolean
-desc_set_index_equal (gconstpointer v1, gconstpointer v2)
-{
-  const HashDescriptorSetIndexEntry *e1 = v1;
-  const HashDescriptorSetIndexEntry *e2 = v2;
-
-  return e1->image == e2->image && e1->repeat == e2->repeat;
+  return self->descriptor_set;
 }
 
 gsize
@@ -461,35 +446,26 @@ gsk_vulkan_render_reserve_descriptor_set (GskVulkanRender *self,
                                           GskVulkanImage  *source,
                                           gboolean         repeat)
 {
-  HashDescriptorSetIndexEntry lookup;
-  HashDescriptorSetIndexEntry *entry;
-
-  g_assert (source != NULL);
-
-  lookup.image = source;
-  lookup.repeat = repeat;
+  VkDescriptorImageInfo info = {
+    .sampler = repeat ? self->repeating_sampler : self->sampler,
+    .imageView = gsk_vulkan_image_get_image_view (source),
+    .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+  };
+  gsize result;
 
-  entry = g_hash_table_lookup (self->descriptor_set_indexes, &lookup);
-  if (entry)
-    return entry->index;
+  result = gsk_descriptor_image_infos_get_size (&self->descriptor_image_infos);
+  gsk_descriptor_image_infos_append (&self->descriptor_image_infos, &info);
 
-  entry = g_new (HashDescriptorSetIndexEntry, 1);
-  entry->image = source;
-  entry->repeat = repeat;
-  entry->index = g_hash_table_size (self->descriptor_set_indexes);
-  g_hash_table_add (self->descriptor_set_indexes, entry);
+  g_assert (result < DESCRIPTOR_POOL_MAXITEMS);
 
-  return entry->index;
+  return result;
 }
 
 static void
 gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self)
 {
-  GHashTableIter iter;
-  gpointer key;
   VkDevice device;
   GList *l;
-  guint i, needed_sets;
 
   device = gdk_vulkan_context_get_device (self->vulkan);
 
@@ -499,88 +475,39 @@ gsk_vulkan_render_prepare_descriptor_sets (GskVulkanRender *self)
       gsk_vulkan_render_pass_reserve_descriptor_sets (pass, self);
     }
   
-  needed_sets = g_hash_table_size (self->descriptor_set_indexes);
-  if (needed_sets == 0)
+  if (gsk_descriptor_image_infos_get_size (&self->descriptor_image_infos) == 0)
     return;
 
-  if (needed_sets > self->n_descriptor_sets)
-    {
-      if (needed_sets > self->descriptor_pool_maxsets)
-        {
-          guint added_sets = needed_sets - self->descriptor_pool_maxsets;
-          added_sets = added_sets + DESCRIPTOR_POOL_MAXSETS_INCREASE - 1;
-          added_sets -= added_sets % DESCRIPTOR_POOL_MAXSETS_INCREASE;
-
-          vkDestroyDescriptorPool (device,
-                                   self->descriptor_pool,
-                                   NULL);
-          self->descriptor_pool_maxsets += added_sets;
-          GSK_VK_CHECK (vkCreateDescriptorPool, device,
-                                                &(VkDescriptorPoolCreateInfo) {
-                                                    .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
-                                                    .maxSets = self->descriptor_pool_maxsets,
-                                                    .poolSizeCount = 1,
-                                                    .pPoolSizes = (VkDescriptorPoolSize[1]) {
-                                                        {
-                                                            .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-                                                            .descriptorCount = self->descriptor_pool_maxsets
-                                                        }
-                                                    }
-                                                },
-                                                NULL,
-                                                &self->descriptor_pool);
-        }
-      else
-        {
-          GSK_VK_CHECK (vkResetDescriptorPool, device,
-                                               self->descriptor_pool,
-                                               0);
-        }
-
-      self->n_descriptor_sets = needed_sets;
-      self->descriptor_sets = g_renew (VkDescriptorSet, self->descriptor_sets, needed_sets);
-    }
-
-  VkDescriptorSetLayout *layouts = g_newa (VkDescriptorSetLayout, needed_sets);
-  for (i = 0; i < needed_sets; i++)
-    layouts[i] = self->descriptor_set_layout;
-
   GSK_VK_CHECK (vkAllocateDescriptorSets, device,
                                           &(VkDescriptorSetAllocateInfo) {
                                               .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
                                               .descriptorPool = self->descriptor_pool,
-                                              .descriptorSetCount = needed_sets,
-                                              .pSetLayouts = layouts
+                                              .descriptorSetCount = 1,
+                                              .pSetLayouts = &self->descriptor_set_layout,
+                                              .pNext = &(VkDescriptorSetVariableDescriptorCountAllocateInfo) {
+                                                .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO,
+                                                .descriptorSetCount = 1,
+                                                .pDescriptorCounts = (uint32_t[1]) {
+                                                  gsk_descriptor_image_infos_get_size (&self->descriptor_image_infos)
+                                                }
+                                              }
                                           },
-                                          self->descriptor_sets);
-
-  g_hash_table_iter_init (&iter, self->descriptor_set_indexes);
-  while (g_hash_table_iter_next (&iter, &key, NULL))
-    {
-      HashDescriptorSetIndexEntry *entry = key;
-      GskVulkanImage *image = entry->image;
-      gsize id = entry->index;
-      gboolean repeat = entry->repeat;
-
-      vkUpdateDescriptorSets (device,
-                              1,
-                              (VkWriteDescriptorSet[1]) {
-                                  {
-                                      .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
-                                      .dstSet = self->descriptor_sets[id],
-                                      .dstBinding = 0,
-                                      .dstArrayElement = 0,
-                                      .descriptorCount = 1,
-                                      .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
-                                      .pImageInfo = &(VkDescriptorImageInfo) {
-                                          .sampler = repeat ? self->repeating_sampler : self->sampler,
-                                          .imageView = gsk_vulkan_image_get_image_view (image),
-                                          .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
-                                      }
-                                  }
-                              },
-                              0, NULL);
-    }
+                                          &self->descriptor_set);
+
+  vkUpdateDescriptorSets (device,
+                          1,
+                          (VkWriteDescriptorSet[1]) {
+                              {
+                                  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+                                  .dstSet = self->descriptor_set,
+                                  .dstBinding = 0,
+                                  .dstArrayElement = 0,
+                                  .descriptorCount = gsk_descriptor_image_infos_get_size (&self->descriptor_image_infos),
+                                  .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+                                  .pImageInfo = gsk_descriptor_image_infos_get_data (&self->descriptor_image_infos)
+                              }
+                          },
+                          0, NULL);
 }
 
 void
@@ -670,10 +597,10 @@ gsk_vulkan_render_cleanup (GskVulkanRender *self)
 
   gsk_vulkan_command_pool_reset (self->command_pool);
 
-  g_hash_table_remove_all (self->descriptor_set_indexes);
   GSK_VK_CHECK (vkResetDescriptorPool, device,
                                        self->descriptor_pool,
                                        0);
+  gsk_descriptor_image_infos_set_size (&self->descriptor_image_infos, 0);
 
   g_list_free_full (self->render_passes, (GDestroyNotify) gsk_vulkan_render_pass_free);
   self->render_passes = NULL;
@@ -715,6 +642,7 @@ gsk_vulkan_render_free (GskVulkanRender *self)
 
   g_clear_pointer (&self->uploader, gsk_vulkan_uploader_free);
 
+
   vkDestroyPipelineLayout (device,
                            self->pipeline_layout,
                            NULL);
@@ -726,8 +654,7 @@ gsk_vulkan_render_free (GskVulkanRender *self)
   vkDestroyDescriptorPool (device,
                            self->descriptor_pool,
                            NULL);
-  g_free (self->descriptor_sets);
-  g_hash_table_unref (self->descriptor_set_indexes);
+  gsk_descriptor_image_infos_clear (&self->descriptor_image_infos);
 
   vkDestroyDescriptorSetLayout (device,
                                 self->descriptor_set_layout,
index 674ae1b14bc75225b25d02b19bf3fedb20211b03..975dc0cbff0d4f2aa5e01cfbe3ee35d44a68fac2 100644 (file)
@@ -1798,6 +1798,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_TEXTURE:
           gsk_vulkan_texture_pipeline_collect_vertex_data (GSK_VULKAN_TEXTURE_PIPELINE (op->render.pipeline),
                                                            data + op->render.vertex_offset,
+                                                           op->render.descriptor_set_index,
                                                            &op->render.offset,
                                                            &op->render.node->bounds,
                                                            &op->render.source_rect);
@@ -1806,6 +1807,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_REPEAT:
           gsk_vulkan_texture_pipeline_collect_vertex_data (GSK_VULKAN_TEXTURE_PIPELINE (op->render.pipeline),
                                                            data + op->render.vertex_offset,
+                                                           op->render.descriptor_set_index,
                                                            &op->render.offset,
                                                            &op->render.node->bounds,
                                                            &op->render.source_rect);
@@ -1816,6 +1818,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
                                                         data + op->text.vertex_offset,
                                                         GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
                                                         &op->text.node->bounds,
+                                                        op->text.descriptor_set_index,
                                                         (PangoFont *)gsk_text_node_get_font (op->text.node),
                                                         gsk_text_node_get_num_glyphs (op->text.node),
                                                         gsk_text_node_get_glyphs (op->text.node, NULL),
@@ -1834,6 +1837,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
                                                               data + op->text.vertex_offset,
                                                               GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
                                                               &op->text.node->bounds,
+                                                              op->text.descriptor_set_index,
                                                               (PangoFont *)gsk_text_node_get_font (op->text.node),
                                                               gsk_text_node_get_num_glyphs (op->text.node),
                                                               gsk_text_node_get_glyphs (op->text.node, NULL),
@@ -1882,6 +1886,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
 
             gsk_vulkan_effect_pipeline_collect_vertex_data (GSK_VULKAN_EFFECT_PIPELINE (op->render.pipeline),
                                                             data + op->render.vertex_offset,
+                                                            op->render.descriptor_set_index,
                                                             &op->render.offset,
                                                             &op->render.node->bounds,
                                                             &op->render.source_rect,
@@ -1893,6 +1898,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_BLUR:
           gsk_vulkan_blur_pipeline_collect_vertex_data (GSK_VULKAN_BLUR_PIPELINE (op->render.pipeline),
                                                         data + op->render.vertex_offset,
+                                                        op->render.descriptor_set_index,
                                                         &op->render.offset,
                                                         &op->render.node->bounds,
                                                         &op->render.source_rect,
@@ -1902,6 +1908,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_COLOR_MATRIX:
           gsk_vulkan_effect_pipeline_collect_vertex_data (GSK_VULKAN_EFFECT_PIPELINE (op->render.pipeline),
                                                           data + op->render.vertex_offset,
+                                                          op->render.descriptor_set_index,
                                                           &op->render.offset,
                                                           &op->render.node->bounds,
                                                           &op->render.source_rect,
@@ -1945,6 +1952,8 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_CROSS_FADE:
           gsk_vulkan_cross_fade_pipeline_collect_vertex_data (GSK_VULKAN_CROSS_FADE_PIPELINE (op->render.pipeline),
                                                               data + op->render.vertex_offset,
+                                                              op->render.descriptor_set_index,
+                                                              op->render.descriptor_set_index2,
                                                               &op->render.offset,
                                                               &op->render.node->bounds,
                                                               &op->render.source_rect,
@@ -1955,6 +1964,8 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_BLEND_MODE:
           gsk_vulkan_blend_mode_pipeline_collect_vertex_data (GSK_VULKAN_BLEND_MODE_PIPELINE (op->render.pipeline),
                                                               data + op->render.vertex_offset,
+                                                              op->render.descriptor_set_index,
+                                                              op->render.descriptor_set_index2,
                                                               &op->render.offset,
                                                               &op->render.node->bounds,
                                                               &op->render.source_rect,
@@ -2111,17 +2122,6 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
                                  gsk_vulkan_pipeline_get_pipeline (current_pipeline));
             }
 
-          vkCmdBindDescriptorSets (command_buffer,
-                                   VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                   pipeline_layout,
-                                   0,
-                                   1,
-                                   (VkDescriptorSet[1]) {
-                                       gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index)
-                                   },
-                                   0,
-                                   NULL);
-
           gsk_vulkan_texture_pipeline_draw (GSK_VULKAN_TEXTURE_PIPELINE (current_pipeline),
                                             command_buffer,
                                             op->render.vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (current_pipeline),
@@ -2137,17 +2137,6 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
                                  gsk_vulkan_pipeline_get_pipeline (current_pipeline));
             }
 
-          vkCmdBindDescriptorSets (command_buffer,
-                                   VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                   pipeline_layout,
-                                   0,
-                                   1,
-                                   (VkDescriptorSet[1]) {
-                                       gsk_vulkan_render_get_descriptor_set (render, op->text.descriptor_set_index)
-                                   },
-                                   0,
-                                   NULL);
-
           gsk_vulkan_text_pipeline_draw (GSK_VULKAN_TEXT_PIPELINE (current_pipeline),
                                          command_buffer,
                                          op->text.vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (current_pipeline),
@@ -2163,17 +2152,6 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
                                  gsk_vulkan_pipeline_get_pipeline (current_pipeline));
             }
 
-          vkCmdBindDescriptorSets (command_buffer,
-                                   VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                   pipeline_layout,
-                                   0,
-                                   1,
-                                   (VkDescriptorSet[1]) {
-                                       gsk_vulkan_render_get_descriptor_set (render, op->text.descriptor_set_index)
-                                   },
-                                   0,
-                                   NULL);
-
           gsk_vulkan_color_text_pipeline_draw (GSK_VULKAN_COLOR_TEXT_PIPELINE (current_pipeline),
                                                command_buffer,
                                                op->text.vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (current_pipeline),
@@ -2192,17 +2170,6 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
                                  gsk_vulkan_pipeline_get_pipeline (current_pipeline));
             }
 
-          vkCmdBindDescriptorSets (command_buffer,
-                                   VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                   pipeline_layout,
-                                   0,
-                                   1,
-                                   (VkDescriptorSet[1]) {
-                                       gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index)
-                                   },
-                                   0,
-                                   NULL);
-
           gsk_vulkan_effect_pipeline_draw (GSK_VULKAN_EFFECT_PIPELINE (current_pipeline),
                                            command_buffer,
                                            op->render.vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (current_pipeline),
@@ -2220,17 +2187,6 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
                                  gsk_vulkan_pipeline_get_pipeline (current_pipeline));
             }
 
-          vkCmdBindDescriptorSets (command_buffer,
-                                   VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                   pipeline_layout,
-                                   0,
-                                   1,
-                                   (VkDescriptorSet[1]) {
-                                       gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index)
-                                   },
-                                   0,
-                                   NULL);
-
           gsk_vulkan_blur_pipeline_draw (GSK_VULKAN_BLUR_PIPELINE (current_pipeline),
                                          command_buffer,
                                          op->render.vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (current_pipeline),
@@ -2331,18 +2287,6 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
                                  gsk_vulkan_pipeline_get_pipeline (current_pipeline));
             }
 
-          vkCmdBindDescriptorSets (command_buffer,
-                                   VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                   pipeline_layout,
-                                   0,
-                                   2,
-                                   (VkDescriptorSet[2]) {
-                                       gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index),
-                                       gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index2)
-                                   },
-                                   0,
-                                   NULL);
-
           gsk_vulkan_cross_fade_pipeline_draw (GSK_VULKAN_CROSS_FADE_PIPELINE (current_pipeline),
                                                command_buffer,
                                                op->render.vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (current_pipeline),
@@ -2360,18 +2304,6 @@ gsk_vulkan_render_pass_draw_rect (GskVulkanRenderPass     *self,
                                  gsk_vulkan_pipeline_get_pipeline (current_pipeline));
             }
 
-          vkCmdBindDescriptorSets (command_buffer,
-                                   VK_PIPELINE_BIND_POINT_GRAPHICS,
-                                   pipeline_layout,
-                                   0,
-                                   2,
-                                   (VkDescriptorSet[2]) {
-                                       gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index),
-                                       gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index2)
-                                   },
-                                   0,
-                                   NULL);
-
           gsk_vulkan_blend_mode_pipeline_draw (GSK_VULKAN_BLEND_MODE_PIPELINE (current_pipeline),
                                                command_buffer,
                                                op->render.vertex_offset / gsk_vulkan_pipeline_get_vertex_stride (current_pipeline),
@@ -2391,6 +2323,7 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
                              VkPipelineLayout     pipeline_layout,
                              VkCommandBuffer      command_buffer)
 {
+  VkDescriptorSet descriptor_set;
   cairo_rectangle_int_t rect;
 
   vkCmdSetViewport (command_buffer,
@@ -2423,6 +2356,17 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
                         },
                         VK_SUBPASS_CONTENTS_INLINE);
 
+  descriptor_set = gsk_vulkan_render_get_descriptor_set (render);
+  if (descriptor_set)
+    vkCmdBindDescriptorSets (command_buffer,
+                             VK_PIPELINE_BIND_POINT_GRAPHICS,
+                             pipeline_layout,
+                             0,
+                             1,
+                             &descriptor_set,
+                             0,
+                             NULL);
+
   gsk_vulkan_render_pass_draw_rect (self, render, pipeline_layout, command_buffer);
 
   vkCmdEndRenderPass (command_buffer);
index 1f7a23db382e6267eb5b4da77cd3bfdd04ff71e3..457c587e5b3fc5436e08d93f8f7602cfed37681a 100644 (file)
@@ -76,11 +76,11 @@ void                    gsk_vulkan_render_upload                        (GskVulk
 
 GskVulkanPipeline *     gsk_vulkan_render_get_pipeline                  (GskVulkanRender        *self,
                                                                          GskVulkanPipelineType   pipeline_type);
-VkDescriptorSet         gsk_vulkan_render_get_descriptor_set            (GskVulkanRender        *self,
-                                                                         gsize                   id);
 gsize                   gsk_vulkan_render_reserve_descriptor_set        (GskVulkanRender        *self,
                                                                          GskVulkanImage         *source,
                                                                          gboolean                repeat);
+VkDescriptorSet         gsk_vulkan_render_get_descriptor_set            (GskVulkanRender        *self);
+
 void                    gsk_vulkan_render_draw                          (GskVulkanRender        *self);
 
 void                    gsk_vulkan_render_submit                        (GskVulkanRender        *self);
index 0e817da8c0920f386893a97bb89b9b9412a5da04..ed810b7f683f7f29af6226b1f770acdf2be62aa0 100644 (file)
@@ -14,6 +14,7 @@ struct _GskVulkanTextInstance
   float rect[4];
   float tex_rect[4];
   float color[4];
+  guint32 tex_id;
 };
 
 G_DEFINE_TYPE (GskVulkanTextPipeline, gsk_vulkan_text_pipeline, GSK_TYPE_VULKAN_PIPELINE)
@@ -46,6 +47,12 @@ gsk_vulkan_text_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
           .binding = 0,
           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
           .offset = G_STRUCT_OFFSET (GskVulkanTextInstance, color),
+      },
+      {
+          .location = 3,
+          .binding = 0,
+          .format = VK_FORMAT_R32_UINT,
+          .offset = G_STRUCT_OFFSET (GskVulkanTextInstance, tex_id),
       }
   };
   static const VkPipelineVertexInputStateCreateInfo info = {
@@ -96,6 +103,7 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline  *pipeline,
                                               guchar                 *data,
                                               GskVulkanRenderer      *renderer,
                                               const graphene_rect_t  *rect,
+                                              guint                   tex_id,
                                               PangoFont              *font,
                                               guint                   total_glyphs,
                                               const PangoGlyphInfo   *glyphs,
@@ -146,6 +154,8 @@ gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline  *pipeline,
           instance->color[2] = color->blue;
           instance->color[3] = color->alpha;
 
+          instance->tex_id = tex_id;
+
           count++;
         }
       x_position += gi->geometry.width;
index c434fa1aef203ff37d166a8c1af929ca8a43a609..8f05e4350067cba09f422374a3f608b89c7a9652 100644 (file)
@@ -22,6 +22,7 @@ void                    gsk_vulkan_text_pipeline_collect_vertex_data   (GskVulka
                                                                         guchar                        *data,
                                                                         GskVulkanRenderer             *renderer,
                                                                         const graphene_rect_t         *rect,
+                                                                        guint32                        tex_id,
                                                                         PangoFont                     *font,
                                                                         guint                          total_glyphs,
                                                                         const PangoGlyphInfo          *glyphs,
index 437eeeda39523a358a53b930b5fcdaeb2fc1d056..dc01cca9c3c7d0e41c488892bdeb0fb8ad0be54a 100644 (file)
@@ -13,6 +13,7 @@ struct _GskVulkanTextureInstance
 {
   float rect[4];
   float tex_rect[4];
+  guint32 tex_id;
 };
 
 G_DEFINE_TYPE (GskVulkanTexturePipeline, gsk_vulkan_texture_pipeline, GSK_TYPE_VULKAN_PIPELINE)
@@ -39,6 +40,12 @@ gsk_vulkan_texture_pipeline_get_input_state_create_info (GskVulkanPipeline *self
           .binding = 0,
           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
           .offset = G_STRUCT_OFFSET (GskVulkanTextureInstance, tex_rect),
+      },
+      {
+          .location = 2,
+          .binding = 0,
+          .format = VK_FORMAT_R32_UINT,
+          .offset = G_STRUCT_OFFSET (GskVulkanTextureInstance, tex_id),
       }
   };
   static const VkPipelineVertexInputStateCreateInfo info = {
@@ -87,6 +94,7 @@ gsk_vulkan_texture_pipeline_new (GdkVulkanContext *context,
 void
 gsk_vulkan_texture_pipeline_collect_vertex_data (GskVulkanTexturePipeline *pipeline,
                                                  guchar                   *data,
+                                                 guint32                   tex_id,
                                                  const graphene_point_t   *offset,
                                                  const graphene_rect_t    *rect,
                                                  const graphene_rect_t    *tex_rect)
@@ -101,6 +109,7 @@ gsk_vulkan_texture_pipeline_collect_vertex_data (GskVulkanTexturePipeline *pipel
   instance->tex_rect[1] = tex_rect->origin.y;
   instance->tex_rect[2] = tex_rect->size.width;
   instance->tex_rect[3] = tex_rect->size.height;
+  instance->tex_id = tex_id;
 }
 
 gsize
index a188a56f916768587a0bf4cc7027f4ad08f4d27f..d837e4d9d2bd921ac570848fd0b1962c1ddd94f9 100644 (file)
@@ -19,6 +19,7 @@ GskVulkanPipeline *     gsk_vulkan_texture_pipeline_new                 (GdkVulk
 
 void                    gsk_vulkan_texture_pipeline_collect_vertex_data (GskVulkanTexturePipeline *pipeline,
                                                                          guchar                   *data,
+                                                                         guint32                   tex_id,
                                                                          const graphene_point_t   *offset,
                                                                          const graphene_rect_t    *rect,
                                                                          const graphene_rect_t    *tex_rect);
index a8b23e98912aa6fa917a9d4a583589138933369e..ad1d9c98b31bdd7cb53ad9bf69f1e3e089e4b2ff 100644 (file)
@@ -1,14 +1,14 @@
 #version 420 core
 
+#include "common.frag.glsl"
 #include "clip.frag.glsl"
 
 layout(location = 0) in vec2 inPos;
 layout(location = 1) in vec2 inStartTexCoord;
 layout(location = 2) in vec2 inEndTexCoord;
-layout(location = 3) flat in uint inBlendMode;
-
-layout(set = 0, binding = 0) uniform sampler2D startTexture;
-layout(set = 1, binding = 0) uniform sampler2D endTexture;
+layout(location = 3) flat in uint inStartTexId;
+layout(location = 4) flat in uint inEndTexId;
+layout(location = 5) flat in uint inBlendMode;
 
 layout(location = 0) out vec4 outColor;
 
@@ -271,8 +271,8 @@ luminosity (vec4 Cs, vec4 Cb)
 
 void main()
 {
-  vec4 source = texture (startTexture, inStartTexCoord);
-  vec4 backdrop = texture (endTexture, inEndTexCoord);
+  vec4 source = texture (textures[inStartTexId], inStartTexCoord);
+  vec4 backdrop = texture (textures[inEndTexId], inEndTexCoord);
   vec4 result;
 
   if (inBlendMode == 0)
index b4c890302a43e3a53d27162f00d6d0bdf41d2508..e0c13a5fe22bf1b13fa5853e6b89b4dfd14b0cde 100644 (file)
@@ -5,12 +5,16 @@
 layout(location = 0) in vec4 inRect;
 layout(location = 1) in vec4 inStartTexRect;
 layout(location = 2) in vec4 inEndTexRect;
-layout(location = 3) in uint inBlendMode;
+layout(location = 3) in uint inStartTexId;
+layout(location = 4) in uint inEndTexId;
+layout(location = 5) in uint inBlendMode;
 
 layout(location = 0) out vec2 outPos;
 layout(location = 1) out vec2 outStartTexCoord;
 layout(location = 2) out vec2 outEndTexCoord;
-layout(location = 3) flat out uint outBlendMode;
+layout(location = 3) flat out uint outStartTexId;
+layout(location = 4) flat out uint outEndTexId;
+layout(location = 5) flat out uint outBlendMode;
 
 vec2 offsets[6] = { vec2(0.0, 0.0),
                     vec2(1.0, 0.0),
@@ -35,6 +39,7 @@ void main() {
 
   outStartTexCoord = starttexrect.xy + starttexrect.zw * offsets[gl_VertexIndex];
   outEndTexCoord = endtexrect.xy + endtexrect.zw * offsets[gl_VertexIndex];
-
+  outStartTexId = inStartTexId;
+  outEndTexId = inEndTexId;
   outBlendMode = inBlendMode;
 }
index 2dd584b0c657882789cd23aa9e4af023d6f85a06..c67063bb8ca6702ae4ba4462216cd2d2b9c08ad4 100644 (file)
@@ -1,13 +1,13 @@
 #version 420 core
 
+#include "common.frag.glsl"
 #include "clip.frag.glsl"
 
 layout(location = 0) in vec2 inPos;
 layout(location = 1) in flat vec2 inSize;
 layout(location = 2) in vec2 inTexCoord;
 layout(location = 3) in float inRadius;
-
-layout(set = 0, binding = 0) uniform sampler2D inTexture;
+layout(location = 4) in flat uint inTexId;
 
 layout(location = 0) out vec4 color;
 
@@ -38,7 +38,7 @@ vec4 blur_pixel (in vec2 uv)
           float fx = Gaussian (inRadius, float(x) - float(half_samples_x));
           float offset_x = float(x - half_samples_x) * pixel_size_x;
           total += fx * fy;
-          ret += texture(inTexture, uv + vec2(offset_x, offset_y)) * fx * fy;
+          ret += texture(textures[inTexId], uv + vec2(offset_x, offset_y)) * fx * fy;
         }
     }
   return ret / total;
index 7ba604685236729cf4fe7d174d9ba8f689a54258..5a5fd6cbcec38a17096fd6f5a11e7d7725283167 100644 (file)
@@ -6,11 +6,13 @@
 layout(location = 0) in vec4 inRect;
 layout(location = 1) in vec4 inTexRect;
 layout(location = 2) in float inRadius;
+layout(location = 3) in uint inTexId;
 
 layout(location = 0) out vec2 outPos;
 layout(location = 1) out flat vec2 outSize;
 layout(location = 2) out vec2 outTexCoord;
 layout(location = 3) out flat float outRadius;
+layout(location = 4) out flat uint outTexId;
 
 vec2 offsets[6] = { vec2(0.0, 0.0),
                     vec2(1.0, 0.0),
@@ -32,6 +34,6 @@ void main() {
   texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy,
                  inTexRect.zw * texrect.zw);
   outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex];
-
+  outTexId = inTexId;
   outRadius = inRadius;
 }
index 8787eb443f2a36b9791bc2acb7d8dfab85a5d03b..ebed0638afffde6f0beba8bc2573a193adc11946 100644 (file)
@@ -1,13 +1,13 @@
 #version 420 core
 
+#include "common.frag.glsl"
 #include "clip.frag.glsl"
 
 layout(location = 0) in vec2 inPos;
 layout(location = 1) in vec2 inTexCoord;
 layout(location = 2) in flat mat4 inColorMatrix;
 layout(location = 6) in flat vec4 inColorOffset;
-
-layout(set = 0, binding = 0) uniform sampler2D inTexture;
+layout(location = 7) in flat uint inTexId;
 
 layout(location = 0) out vec4 color;
 
@@ -29,5 +29,5 @@ color_matrix (vec4 color, mat4 color_matrix, vec4 color_offset)
 
 void main()
 {
-  color = clip (inPos, color_matrix (texture (inTexture, inTexCoord), inColorMatrix, inColorOffset));
+  color = clip (inPos, color_matrix (texture (textures[inTexId], inTexCoord), inColorMatrix, inColorOffset));
 }
index 99487c9063d5fb6782bc28708c9e8defc117fb0c..8f92fff2314f04c257b6424c11ef386af3c71261 100644 (file)
@@ -6,11 +6,13 @@ layout(location = 0) in vec4 inRect;
 layout(location = 1) in vec4 inTexRect;
 layout(location = 2) in mat4 inColorMatrix;
 layout(location = 6) in vec4 inColorOffset;
+layout(location = 7) in uint inTexId;
 
 layout(location = 0) out vec2 outPos;
 layout(location = 1) out vec2 outTexCoord;
 layout(location = 2) out flat mat4 outColorMatrix;
 layout(location = 6) out flat vec4 outColorOffset;
+layout(location = 7) out flat uint outTexId;
 
 vec2 offsets[6] = { vec2(0.0, 0.0),
                     vec2(1.0, 0.0),
@@ -31,6 +33,7 @@ void main() {
   texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy,
                  inTexRect.zw * texrect.zw);
   outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex];
+  outTexId = inTexId;
   outColorMatrix = inColorMatrix;
   outColorOffset = inColorOffset;
 }
diff --git a/gsk/vulkan/resources/common.frag.glsl b/gsk/vulkan/resources/common.frag.glsl
new file mode 100644 (file)
index 0000000..239691d
--- /dev/null
@@ -0,0 +1,2 @@
+
+layout(set = 0, binding = 0) uniform sampler2D textures[50000];
index 8293b1d5d836e48a231c4add5d7d0bd36b91bfe4..413663734658ea84c74e5abc3e36bbbd8b3c8a20 100644 (file)
@@ -1,21 +1,21 @@
 #version 420 core
 
+#include "common.frag.glsl"
 #include "clip.frag.glsl"
 
 layout(location = 0) in vec2 inPos;
 layout(location = 1) in vec2 inStartTexCoord;
 layout(location = 2) in vec2 inEndTexCoord;
-layout(location = 3) in float inProgress;
-
-layout(set = 0, binding = 0) uniform sampler2D startTexture;
-layout(set = 1, binding = 0) uniform sampler2D endTexture;
+layout(location = 3) flat in uint inStartTexId;
+layout(location = 4) flat in uint inEndTexId;
+layout(location = 5) in float inProgress;
 
 layout(location = 0) out vec4 color;
 
 void main()
 {
-  vec4 start = texture (startTexture, inStartTexCoord);
-  vec4 end = texture (endTexture, inEndTexCoord);
+  vec4 start = texture (textures[inStartTexId], inStartTexCoord);
+  vec4 end = texture (textures[inEndTexId], inEndTexCoord);
 
   color = clip (inPos, mix (start, end, inProgress));
 }
index eb7a00767a599232387343e6f672e6f8d71754c2..ff3e73b6dfe2945e4511ccb173d473c7b62c49bd 100644 (file)
@@ -5,12 +5,16 @@
 layout(location = 0) in vec4 inRect;
 layout(location = 1) in vec4 inStartTexRect;
 layout(location = 2) in vec4 inEndTexRect;
-layout(location = 3) in float inProgress;
+layout(location = 3) in uint inStartTexId;
+layout(location = 4) in uint inEndTexId;
+layout(location = 5) in float inProgress;
 
 layout(location = 0) out vec2 outPos;
 layout(location = 1) out vec2 outStartTexCoord;
 layout(location = 2) out vec2 outEndTexCoord;
-layout(location = 3) out float outProgress;
+layout(location = 3) flat out uint outStartTexId;
+layout(location = 4) flat out uint outEndTexId;
+layout(location = 5) flat out float outProgress;
 
 vec2 offsets[6] = { vec2(0.0, 0.0),
                     vec2(1.0, 0.0),
@@ -35,6 +39,7 @@ void main() {
 
   outStartTexCoord = starttexrect.xy + starttexrect.zw * offsets[gl_VertexIndex];
   outEndTexCoord = endtexrect.xy + endtexrect.zw * offsets[gl_VertexIndex];
-
+  outStartTexId = inStartTexId;
+  outEndTexId = inEndTexId;
   outProgress = inProgress;
 }
index 81f6833ef29b504f1f835aec3e13b4bd597fb6a9..08d3ec57704f6151ca08d3e6c1841736c88a86c9 100644 (file)
@@ -1,16 +1,16 @@
 #version 420 core
 
+#include "common.frag.glsl"
 #include "clip.frag.glsl"
 
 layout(location = 0) in vec2 inPos;
 layout(location = 1) in vec2 inTexCoord;
 layout(location = 2) in vec4 inColor;
-
-layout(set = 0, binding = 0) uniform sampler2D inTexture;
+layout(location = 3) flat in uint inTexId;
 
 layout(location = 0) out vec4 color;
 
 void main()
 {
-  color = clip (inPos, vec4(inColor.rgb * inColor.a, inColor.a) * texture(inTexture, inTexCoord).a);
+  color = clip (inPos, vec4(inColor.rgb * inColor.a, inColor.a) * texture(textures[inTexId], inTexCoord).a);
 }
index 1406bfd1d1ad8fd04012c43cadcf6a3e37b0402e..09bc2a9909d38b59056cddb647b5ffe24375f95a 100644 (file)
@@ -5,10 +5,12 @@
 layout(location = 0) in vec4 inRect;
 layout(location = 1) in vec4 inTexRect;
 layout(location = 2) in vec4 inColor;
+layout(location = 3) in uint inTexId;
 
 layout(location = 0) out vec2 outPos;
 layout(location = 1) out vec2 outTexCoord;
 layout(location = 2) out flat vec4 outColor;
+layout(location = 3) out flat uint outTexId;
 
 vec2 offsets[6] = { vec2(0.0, 0.0),
                     vec2(1.0, 0.0),
@@ -29,6 +31,6 @@ void main() {
   texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy,
                  inTexRect.zw * texrect.zw);
   outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex];
-
+  outTexId = inTexId;
   outColor = inColor;
 }
index 46a065ad0968f09f043b72acd32f60fea8b6c42f..6eb9057ce88dd32de6d508c2cfb8928c9834bbd2 100644 (file)
@@ -1,6 +1,7 @@
 gsk_private_vulkan_include_shaders = [
   'clip.frag.glsl',
   'clip.vert.glsl',
+  'common.frag.glsl',
   'common.vert.glsl',
   'constants.glsl',
   'rect.glsl',
index 557a63746aa845a10925992c98923deefc5736f0..eaaba70fbd6d66b4464f0b10e249eb1b777c5c0c 100644 (file)
@@ -1,18 +1,18 @@
 #version 420 core
 
+#include "common.frag.glsl"
 #include "clip.frag.glsl"
 #include "rect.frag.glsl"
 
 layout(location = 0) in vec2 inPos;
 layout(location = 1) in Rect inRect;
 layout(location = 2) in vec2 inTexCoord;
-
-layout(set = 0, binding = 0) uniform sampler2D inTexture;
+layout(location = 3) flat in uint inTexId;
 
 layout(location = 0) out vec4 color;
 
 void main()
 {
   float alpha = rect_coverage (inRect, inPos);
-  color = clip_scaled (inPos, texture (inTexture, inTexCoord) * alpha);
+  color = clip_scaled (inPos, texture (textures[inTexId], inTexCoord) * alpha);
 }
index 49d30e2e471be814875a19544e20fe0356c80f91..69d5a4937d68cba50e872f6f90d94a3613199ec0 100644 (file)
@@ -5,10 +5,12 @@
 
 layout(location = 0) in vec4 inRect;
 layout(location = 1) in vec4 inTexRect;
+layout(location = 2) in uint inTexId;
 
 layout(location = 0) out vec2 outPos;
 layout(location = 1) out flat Rect outRect;
 layout(location = 2) out vec2 outTexCoord;
+layout(location = 3) out flat uint outTexId;
 
 void main() {
   Rect r = rect_from_gsk (inRect);
@@ -17,4 +19,5 @@ void main() {
   outPos = pos;
   outRect = r;
   outTexCoord = scale_tex_coord (pos, r, inTexRect);
+  outTexId = inTexId;
 }