[gtk+/wip/otte/vulkan] vulkan: Make GskVulkanRenderer work



commit a3c2b8120e54cd1c43fbcdbada72981bb278ee7d
Author: Benjamin Otte <otte redhat com>
Date:   Tue Dec 6 14:42:46 2016 +0100

    vulkan: Make GskVulkanRenderer work
    
    We now create a Cairo renderer, render to an image surface and upload
    and retnder it with Vulkan.

 gsk/Makefile.am                     |    2 +
 gsk/gskvulkanimage.c                |  288 +++++++++++++++++++++++++++++++++++
 gsk/gskvulkanimageprivate.h         |   23 +++
 gsk/gskvulkanpipeline.c             |   35 ++++-
 gsk/gskvulkanpipelineprivate.h      |    2 +
 gsk/gskvulkanrenderer.c             |  137 ++++++++++++++++-
 gsk/resources/vulkan/blit.frag.glsl |    4 +-
 gsk/resources/vulkan/blit.frag.spv  |  Bin 564 -> 632 bytes
 8 files changed, 486 insertions(+), 5 deletions(-)
---
diff --git a/gsk/Makefile.am b/gsk/Makefile.am
index 84ae987..a29ebc5 100644
--- a/gsk/Makefile.am
+++ b/gsk/Makefile.am
@@ -25,12 +25,14 @@ noinst_LTLIBRARIES =
 if HAVE_VULKAN
 gsk_private_vulan_source_h = \
        gskvulkanbufferprivate.h \
+       gskvulkanimageprivate.h \
        gskvulkanmemoryprivate.h \
        gskvulkanpipelineprivate.h \
        gskvulkanrendererprivate.h \
        gskvulkanshaderprivate.h
 gsk_private_vulkan_source_c = \
        gskvulkanbuffer.c \
+       gskvulkanimage.c \
        gskvulkanmemory.c \
        gskvulkanpipeline.c \
        gskvulkanrenderer.c \
diff --git a/gsk/gskvulkanimage.c b/gsk/gskvulkanimage.c
new file mode 100644
index 0000000..88a134c
--- /dev/null
+++ b/gsk/gskvulkanimage.c
@@ -0,0 +1,288 @@
+#include "config.h"
+
+#include "gskvulkanimageprivate.h"
+#include "gskvulkanmemoryprivate.h"
+#include "gskvulkanpipelineprivate.h"
+
+#include <string.h>
+
+struct _GskVulkanImage
+{
+  GdkVulkanContext *vulkan;
+
+  VkImage vk_image;
+  VkImageView vk_image_view;
+
+  GskVulkanMemory *memory;
+};
+
+static GskVulkanImage *
+gsk_vulkan_image_new (GdkVulkanContext      *context,
+                      gsize                  width,
+                      gsize                  height,
+                      VkImageTiling          tiling,
+                      VkImageUsageFlags      usage,
+                      VkMemoryPropertyFlags  memory)
+{
+  VkMemoryRequirements requirements;
+  GskVulkanImage *self;
+
+  self = g_slice_new0 (GskVulkanImage);
+
+  self->vulkan = g_object_ref (context);
+
+  GSK_VK_CHECK (vkCreateImage, gdk_vulkan_context_get_device (context),
+                                &(VkImageCreateInfo) {
+                                    .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+                                    .flags = 0,
+                                    .imageType = VK_IMAGE_TYPE_2D,
+                                    .format = VK_FORMAT_R8G8B8A8_SRGB,
+                                    .extent = { width, height, 1 },
+                                    .mipLevels = 1,
+                                    .arrayLayers = 1,
+                                    .samples = VK_SAMPLE_COUNT_1_BIT,
+                                    .tiling = tiling,
+                                    .usage = usage,
+                                    .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
+                                    .initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED
+                                },
+                                NULL,
+                                &self->vk_image);
+
+  vkGetImageMemoryRequirements (gdk_vulkan_context_get_device (context),
+                                self->vk_image,
+                                &requirements);
+
+  self->memory = gsk_vulkan_memory_new (context,
+                                        requirements.memoryTypeBits,
+                                        memory,
+                                        requirements.size);
+
+  GSK_VK_CHECK (vkBindImageMemory, gdk_vulkan_context_get_device (context),
+                                   self->vk_image,
+                                   gsk_vulkan_memory_get_device_memory (self->memory),
+                                   0);
+  return self;
+}
+
+static GskVulkanImage *
+gsk_vulkan_image_new_staging (GdkVulkanContext  *context,
+                              guchar            *data,
+                              gsize              width,
+                              gsize              height,
+                              gsize              stride)
+{
+  VkMemoryRequirements requirements;
+  GskVulkanImage *self;
+  guchar *mem;
+  gsize mem_stride;
+
+  self = gsk_vulkan_image_new (context,
+                               width,
+                               height, 
+                               VK_IMAGE_TILING_LINEAR,
+                               VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+                               VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
+
+  mem_stride = width * 4;
+  vkGetImageMemoryRequirements (gdk_vulkan_context_get_device (context),
+                                self->vk_image,
+                                &requirements);
+  if (mem_stride % requirements.alignment != 0)
+    mem_stride = (mem_stride / requirements.alignment + 1) * requirements.alignment;
+
+  mem = gsk_vulkan_memory_map (self->memory);
+
+  if (stride == width * 4 && stride == mem_stride)
+    {
+      memcpy (mem, data, width * height * 4);
+    }
+  else
+    {
+      for (gsize i = 0; i < height; i++)
+        {
+          memcpy (mem + i * mem_stride, data + i * stride, width * 4);
+        }
+    }
+
+  gsk_vulkan_memory_unmap (self->memory);
+
+  return self;
+}
+
+static void
+gsk_vulkan_image_ensure_view (GskVulkanImage *self)
+{
+  GSK_VK_CHECK (vkCreateImageView, gdk_vulkan_context_get_device (self->vulkan),
+                                   &(VkImageViewCreateInfo) {
+                                       .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+                                       .image = self->vk_image,
+                                       .viewType = VK_IMAGE_VIEW_TYPE_2D,
+                                       .format = VK_FORMAT_B8G8R8A8_SRGB,
+                                       .components = {
+                                           .r = VK_COMPONENT_SWIZZLE_R,
+                                           .g = VK_COMPONENT_SWIZZLE_G,
+                                           .b = VK_COMPONENT_SWIZZLE_B,
+                                           .a = VK_COMPONENT_SWIZZLE_A,
+                                       },
+                                       .subresourceRange = {
+                                           .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                                           .baseMipLevel = 0,
+                                           .levelCount = 1,
+                                           .baseArrayLayer = 0,
+                                           .layerCount = 1,
+                                       },
+                                   },
+                                   NULL,
+                                   &self->vk_image_view);
+}
+
+GskVulkanImage *
+gsk_vulkan_image_new_from_data (GdkVulkanContext  *context,
+                                VkCommandBuffer    command_buffer,
+                                guchar            *data,
+                                gsize              width,
+                                gsize              height,
+                                gsize              stride)
+{
+  GskVulkanImage *self, *staging;
+
+  staging = gsk_vulkan_image_new_staging (context, data, width, height, stride);
+
+  self = gsk_vulkan_image_new (context,
+                               width,
+                               height, 
+                               VK_IMAGE_TILING_OPTIMAL,
+                               VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+                               VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+
+  vkCmdPipelineBarrier (command_buffer,
+                        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                        0,
+                        0, NULL,
+                        0, NULL,
+                        2, (VkImageMemoryBarrier[2]) {
+                            {
+                                .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+                                .srcAccessMask = VK_ACCESS_HOST_WRITE_BIT,
+                                .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
+                                .oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED,
+                                .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                .image = staging->vk_image,
+                                .subresourceRange = {
+                                    .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                                    .baseMipLevel = 0,
+                                    .levelCount = 1,
+                                    .baseArrayLayer = 0,
+                                    .layerCount = 1
+                                }
+                            },
+                            {
+                                .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+                                .srcAccessMask = VK_ACCESS_HOST_WRITE_BIT,
+                                .dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+                                .oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED,
+                                .newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                .image = self->vk_image,
+                                .subresourceRange = {
+                                    .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                                    .baseMipLevel = 0,
+                                    .levelCount = 1,
+                                    .baseArrayLayer = 0,
+                                    .layerCount = 1
+                                }
+                            }
+                        });
+
+  vkCmdCopyImage (command_buffer,
+                  staging->vk_image,
+                  VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+                  self->vk_image,
+                  VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                  1,
+                  &(VkImageCopy) {
+                      .srcSubresource = {
+                          .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                          .mipLevel = 0,
+                          .baseArrayLayer = 0,
+                          .layerCount = 1
+                      },
+                      .srcOffset = { 0, 0, 0 },
+                      .dstSubresource = {
+                          .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                          .mipLevel = 0,
+                          .baseArrayLayer = 0,
+                          .layerCount = 1
+                      },
+                      .dstOffset = { 0, 0, 0 },
+                      .extent = { 
+                          .width = width,
+                          .height = height,
+                          .depth = 1
+                      }
+                  });
+
+  vkCmdPipelineBarrier (command_buffer,
+                        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                        0,
+                        0, NULL,
+                        0, NULL,
+                        1, (VkImageMemoryBarrier[1]) {
+                            {
+                                .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+                                .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
+                                .dstAccessMask = VK_ACCESS_SHADER_READ_BIT,
+                                .oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+                                .newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+                                .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
+                                .image = self->vk_image,
+                                .subresourceRange = {
+                                    .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
+                                    .baseMipLevel = 0,
+                                    .levelCount = 1,
+                                    .baseArrayLayer = 0,
+                                    .layerCount = 1
+                                }
+                            }
+                        });
+
+  gsk_vulkan_image_free (staging);
+
+  gsk_vulkan_image_ensure_view (self);
+
+  return self;
+}
+
+void
+gsk_vulkan_image_free (GskVulkanImage *self)
+{
+  gsk_vulkan_memory_free (self->memory);
+
+  vkDestroyImage (gdk_vulkan_context_get_device (self->vulkan),
+                  self->vk_image,
+                  NULL);
+
+  g_object_unref (self->vulkan);
+
+  g_slice_free (GskVulkanImage, self);
+}
+
+VkImage
+gsk_vulkan_image_get_image (GskVulkanImage *self)
+{
+  return self->vk_image;
+}
+
+VkImageView
+gsk_vulkan_image_get_image_view (GskVulkanImage *self)
+{
+  return self->vk_image_view;
+}
+
diff --git a/gsk/gskvulkanimageprivate.h b/gsk/gskvulkanimageprivate.h
new file mode 100644
index 0000000..57686ea
--- /dev/null
+++ b/gsk/gskvulkanimageprivate.h
@@ -0,0 +1,23 @@
+#ifndef __GSK_VULKAN_IMAGE_PRIVATE_H__
+#define __GSK_VULKAN_IMAGE_PRIVATE_H__
+
+#include <gdk/gdk.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GskVulkanImage GskVulkanImage;
+
+GskVulkanImage *        gsk_vulkan_image_new_from_data                  (GdkVulkanContext       *context,
+                                                                         VkCommandBuffer         
command_buffer,
+                                                                         guchar                 *data,
+                                                                         gsize                   width,
+                                                                         gsize                   height,
+                                                                         gsize                   stride);
+void                    gsk_vulkan_image_free                           (GskVulkanImage         *image);
+
+VkImage                 gsk_vulkan_image_get_image                      (GskVulkanImage         *self);
+VkImageView             gsk_vulkan_image_get_image_view                 (GskVulkanImage         *self);
+
+G_END_DECLS
+
+#endif /* __GSK_VULKAN_IMAGE_PRIVATE_H__ */
diff --git a/gsk/gskvulkanpipeline.c b/gsk/gskvulkanpipeline.c
index 93f0cf7..012eb8f 100644
--- a/gsk/gskvulkanpipeline.c
+++ b/gsk/gskvulkanpipeline.c
@@ -12,6 +12,7 @@ struct _GskVulkanPipeline
 
   VkPipeline pipeline;
   VkPipelineLayout pipeline_layout;
+  VkDescriptorSetLayout descriptor_set_layout;
 
   GskVulkanShader *vertex_shader;
   GskVulkanShader *fragment_shader;
@@ -36,6 +37,10 @@ gsk_vulkan_pipeline_finalize (GObject *gobject)
                            self->pipeline_layout,
                            NULL);
 
+  vkDestroyDescriptorSetLayout (device,
+                                self->descriptor_set_layout,
+                                NULL);
+
   g_clear_object (&self->vulkan);
 
   G_OBJECT_CLASS (gsk_vulkan_pipeline_parent_class)->finalize (gobject);
@@ -68,10 +73,27 @@ gsk_vulkan_pipeline_new (GdkVulkanContext *context,
 
   self->vulkan = g_object_ref (context);
 
+  GSK_VK_CHECK (vkCreateDescriptorSetLayout, device,
+                                             &(VkDescriptorSetLayoutCreateInfo) {
+                                                 .sType = 
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+                                                 .bindingCount = 1,
+                                                 .pBindings = (VkDescriptorSetLayoutBinding[1]) {
+                                                     {
+                                                         .binding = 0,
+                                                         .descriptorType = 
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+                                                         .descriptorCount = 1,
+                                                         .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT
+                                                     }
+                                                 }
+                                             },
+                                             NULL,
+                                             &self->descriptor_set_layout);
+
   GSK_VK_CHECK (vkCreatePipelineLayout, device,
                                         &(VkPipelineLayoutCreateInfo) {
                                             .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
-                                            .setLayoutCount = 0,
+                                            .setLayoutCount = 1,
+                                            .pSetLayouts = &self->descriptor_set_layout
                                         },
                                         NULL,
                                         &self->pipeline_layout);
@@ -179,4 +201,15 @@ gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self)
   return self->pipeline;
 }
 
+VkPipelineLayout
+gsk_vulkan_pipeline_get_pipeline_layout (GskVulkanPipeline *self)
+{
+  return self->pipeline_layout;
+}
+
+VkDescriptorSetLayout
+gsk_vulkan_pipeline_get_descriptor_set_layout (GskVulkanPipeline *self)
+{
+  return self->descriptor_set_layout;
+}
 
diff --git a/gsk/gskvulkanpipelineprivate.h b/gsk/gskvulkanpipelineprivate.h
index b4e9e28..8395a2d 100644
--- a/gsk/gskvulkanpipelineprivate.h
+++ b/gsk/gskvulkanpipelineprivate.h
@@ -28,6 +28,8 @@ GskVulkanPipeline *     gsk_vulkan_pipeline_new                         (GdkVulk
                                                                          VkRenderPass            
render_pass);
 
 VkPipeline              gsk_vulkan_pipeline_get_pipeline                (GskVulkanPipeline      *self);
+VkPipelineLayout        gsk_vulkan_pipeline_get_pipeline_layout         (GskVulkanPipeline      *self);
+VkDescriptorSetLayout   gsk_vulkan_pipeline_get_descriptor_set_layout   (GskVulkanPipeline      *self);
 
 G_END_DECLS
 
diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c
index d846449..060459b 100644
--- a/gsk/gskvulkanrenderer.c
+++ b/gsk/gskvulkanrenderer.c
@@ -9,6 +9,7 @@
 #include "gskrendernodeprivate.h"
 #include "gsktextureprivate.h"
 #include "gskvulkanbufferprivate.h"
+#include "gskvulkanimageprivate.h"
 #include "gskvulkanpipelineprivate.h"
 
 typedef struct _GskVulkanTarget GskVulkanTarget;
@@ -33,8 +34,13 @@ struct _GskVulkanRenderer
   VkCommandPool command_pool;
   VkFence command_pool_fence;
 
+  VkDescriptorPool descriptor_pool;
+  VkDescriptorSet descriptor_set;  
+
   GskVulkanPipeline *pipeline;
 
+  VkSampler sampler;
+
 #ifdef G_ENABLE_DEBUG
   ProfileTimers profile_timers;
 #endif
@@ -228,9 +234,48 @@ gsk_vulkan_renderer_realize (GskRenderer  *renderer,
                                NULL,
                                &self->command_pool_fence);
 
-
   self->pipeline = gsk_vulkan_pipeline_new (self->vulkan, self->render_pass);
 
+  GSK_VK_CHECK (vkCreateDescriptorPool, device,
+                                        &(VkDescriptorPoolCreateInfo) {
+                                            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+                                            .maxSets = 1,
+                                            .poolSizeCount = 1,
+                                            .pPoolSizes = (VkDescriptorPoolSize[1]) {
+                                                {
+                                                    .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+                                                    .descriptorCount = 1
+                                                }
+                                            }
+                                        },
+                                        NULL,
+                                        &self->descriptor_pool);
+
+  GSK_VK_CHECK (vkAllocateDescriptorSets, device,
+                                          &(VkDescriptorSetAllocateInfo) {
+                                              .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+                                              .descriptorPool = self->descriptor_pool,
+                                              .descriptorSetCount = 1,
+                                              .pSetLayouts = (VkDescriptorSetLayout[1]) {
+                                                  gsk_vulkan_pipeline_get_descriptor_set_layout 
(self->pipeline)
+                                              }
+                                          },
+                                          &self->descriptor_set);
+
+  GSK_VK_CHECK (vkCreateSampler, device,
+                                 &(VkSamplerCreateInfo) {
+                                     .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+                                     .magFilter = VK_FILTER_LINEAR,
+                                     .minFilter = VK_FILTER_LINEAR,
+                                     .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
+                                     .addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
+                                     .addressModeW = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+                                     .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
+                                     .unnormalizedCoordinates = VK_FALSE
+                                 },
+                                 NULL,
+                                 &self->sampler);
+
   g_signal_connect (self->vulkan,
                     "images-updated",
                     G_CALLBACK (gsk_vulkan_renderer_update_images_cb),
@@ -253,6 +298,19 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
                                        gsk_vulkan_renderer_update_images_cb,
                                        self);
 
+  vkDestroySampler (device,
+                    self->sampler,
+                    NULL);
+  self->sampler = VK_NULL_HANDLE;
+
+  vkDestroyDescriptorPool (device,
+                           self->descriptor_pool,
+                           NULL);
+  self->descriptor_pool = VK_NULL_HANDLE;
+  self->descriptor_set = VK_NULL_HANDLE;
+
+  g_clear_object (&self->pipeline);
+
   vkDestroyFence (device,
                   self->command_pool_fence,
                   NULL);
@@ -271,6 +329,46 @@ gsk_vulkan_renderer_unrealize (GskRenderer *renderer)
   g_clear_object (&self->vulkan);
 }
 
+static GskVulkanImage *
+gsk_vulkan_renderer_prepare_render (GskVulkanRenderer *self,
+                                    VkCommandBuffer    command_buffer,
+                                    GskRenderNode     *root)
+{
+  GdkWindow *window;
+  GskRenderer *fallback;
+  GskVulkanImage *image;
+  cairo_surface_t *surface;
+  cairo_t *cr;
+
+  window = gsk_renderer_get_window (GSK_RENDERER (self));
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                        gdk_window_get_width (window),
+                                        gdk_window_get_height (window));
+  cr = cairo_create (surface);
+  fallback = gsk_renderer_create_fallback (GSK_RENDERER (self),
+                                           &GRAPHENE_RECT_INIT(
+                                               0, 0,
+                                               gdk_window_get_width (window),
+                                               gdk_window_get_height (window)
+                                           ),
+                                           cr);
+
+  gsk_renderer_render (fallback, root, NULL);
+  g_object_unref (fallback);
+  
+  cairo_destroy (cr);
+
+  image = gsk_vulkan_image_new_from_data (self->vulkan,
+                                          command_buffer,
+                                          cairo_image_surface_get_data (surface),
+                                          cairo_image_surface_get_width (surface),
+                                          cairo_image_surface_get_height (surface),
+                                          cairo_image_surface_get_stride (surface));
+  cairo_surface_destroy (surface);
+
+  return image;
+}
+
 static void
 gsk_vulkan_renderer_do_render_commands (GskVulkanRenderer *self,
                                         VkCommandBuffer    command_buffer)
@@ -297,6 +395,15 @@ gsk_vulkan_renderer_do_render_commands (GskVulkanRenderer *self,
                      VK_PIPELINE_BIND_POINT_GRAPHICS,
                      gsk_vulkan_pipeline_get_pipeline (self->pipeline));
 
+  vkCmdBindDescriptorSets (command_buffer,
+                           VK_PIPELINE_BIND_POINT_GRAPHICS,
+                           gsk_vulkan_pipeline_get_pipeline_layout (self->pipeline),
+                           0,
+                           1,
+                           &self->descriptor_set,
+                           0,
+                           NULL);
+
   vkCmdBindVertexBuffers (command_buffer,
                           0,
                           1,
@@ -315,7 +422,7 @@ gsk_vulkan_renderer_do_render_commands (GskVulkanRenderer *self,
 static void
 gsk_vulkan_renderer_do_render_pass (GskVulkanRenderer *self,
                                     VkCommandBuffer    command_buffer,
-                                    GskRenderNode     *root)
+                                    GskVulkanImage    *image)
 {
   GdkRectangle extents;
   GdkWindow *window;
@@ -324,6 +431,25 @@ gsk_vulkan_renderer_do_render_pass (GskVulkanRenderer *self,
   cairo_region_get_extents (gdk_drawing_context_get_clip (gsk_renderer_get_drawing_context (GSK_RENDERER 
(self))),
                             &extents);
 
+  vkUpdateDescriptorSets (gdk_vulkan_context_get_device (self->vulkan),
+                          1,
+                          (VkWriteDescriptorSet[1]) {
+                              {
+                                  .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+                                  .dstSet = self->descriptor_set,
+                                  .dstBinding = 0,
+                                  .dstArrayElement = 0,
+                                  .descriptorCount = 1,
+                                  .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+                                  .pImageInfo = &(VkDescriptorImageInfo) {
+                                      .sampler = self->sampler,
+                                      .imageView = gsk_vulkan_image_get_image_view (image),
+                                      .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+                                  }
+                              }
+                          },
+                          0, NULL);
+
   vkCmdBeginRenderPass (command_buffer,
                         &(VkRenderPassBeginInfo) {
                             .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
@@ -371,6 +497,7 @@ gsk_vulkan_renderer_render (GskRenderer   *renderer,
 {
   GskVulkanRenderer *self = GSK_VULKAN_RENDERER (renderer);
   VkCommandBuffer command_buffer;
+  GskVulkanImage *image;
 #ifdef G_ENABLE_DEBUG
   GskProfiler *profiler;
   gint64 cpu_time;
@@ -396,7 +523,9 @@ gsk_vulkan_renderer_render (GskRenderer   *renderer,
                                           .flags = 0
                                       });
 
-  gsk_vulkan_renderer_do_render_pass (self, command_buffer, root);
+  image = gsk_vulkan_renderer_prepare_render (self, command_buffer, root);
+
+  gsk_vulkan_renderer_do_render_pass (self, command_buffer, image);
 
   GSK_VK_CHECK (vkEndCommandBuffer, command_buffer);
 
@@ -429,6 +558,8 @@ gsk_vulkan_renderer_render (GskRenderer   *renderer,
                                     self->command_pool,
                                     0);
    
+  gsk_vulkan_image_free (image);
+
 #ifdef G_ENABLE_DEBUG
   cpu_time = gsk_profiler_timer_end (profiler, self->profile_timers.cpu_time);
   gsk_profiler_timer_set (profiler, self->profile_timers.cpu_time, cpu_time);
diff --git a/gsk/resources/vulkan/blit.frag.glsl b/gsk/resources/vulkan/blit.frag.glsl
index acc8680..5d7c818 100644
--- a/gsk/resources/vulkan/blit.frag.glsl
+++ b/gsk/resources/vulkan/blit.frag.glsl
@@ -2,9 +2,11 @@
 
 layout(location = 0) in vec2 inTexCoord;
 
+layout(set = 0, binding = 0) uniform sampler2D inTexture;
+
 layout(location = 0) out vec4 color;
 
 void main()
 {
-    color = vec4 (inTexCoord, 0.0, 1.0);
+    color = texture (inTexture, inTexCoord);
 }
diff --git a/gsk/resources/vulkan/blit.frag.spv b/gsk/resources/vulkan/blit.frag.spv
index 05fd469..9dcff6d 100644
Binary files a/gsk/resources/vulkan/blit.frag.spv and b/gsk/resources/vulkan/blit.frag.spv differ


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]