[gtk+/wip/matthiasc/shadertoy] Allow custom pipelines to have textures



commit 4a313a2dbcd80e6ee075b56d19ff6bf332ed4601
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Sep 24 12:18:34 2017 -0400

    Allow custom pipelines to have textures

 gsk/gskrendernode.h                  |   10 ++-
 gsk/gskrendernodeimpl.c              |  111 +++++++++++++++++++++++++++++++---
 gsk/gskrendernodeprivate.h           |    2 +
 gsk/gskvulkancustompipeline.c        |   36 ++++++++++--
 gsk/gskvulkancustompipelineprivate.h |    2 +
 gsk/gskvulkanrender.c                |    3 +-
 gsk/gskvulkanrenderpass.c            |   55 ++++++++++++++++-
 7 files changed, 198 insertions(+), 21 deletions(-)
---
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index dbcaa9f..eae7c6a 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -186,10 +186,12 @@ GskRenderNode *         gsk_blur_node_new                       (GskRenderNode *
                                                                  double         radius);
 
 GDK_AVAILABLE_IN_3_92
-GskRenderNode *         gsk_pixel_shader_node_new               (const graphene_rect_t *bounds,
-                                                                 GBytes                *vertex_bytes,
-                                                                 GBytes                *fragement_bytes,
-                                                                 float                  time);
+GskRenderNode *         gsk_pixel_shader_node_new               (const graphene_rect_t  *bounds,
+                                                                 GskRenderNode          *child1,
+                                                                 GskRenderNode          *child2,
+                                                                 GBytes                 *vertex_bytes,
+                                                                 GBytes                 *fragement_bytes,
+                                                                 float                   time);
 
 GDK_AVAILABLE_IN_3_90
 void                    gsk_render_node_set_scaling_filters     (GskRenderNode *node,
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index d7e3307..ac624ae 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -4372,6 +4372,9 @@ struct _GskPixelShaderNode
   GBytes *fragment_bytes;
 
   float time;
+
+  GskRenderNode *child1;
+  GskRenderNode *child2;
 };
 
 static void
@@ -4381,28 +4384,53 @@ gsk_pixel_shader_node_finalize (GskRenderNode *node)
 
   g_bytes_unref (self->vertex_bytes);
   g_bytes_unref (self->fragment_bytes);
+
+  if (self->child1)
+    gsk_render_node_unref (self->child1);
+  if (self->child2)
+    gsk_render_node_unref (self->child2);
 }
 
 static void
 gsk_pixel_shader_node_draw (GskRenderNode *node,
                             cairo_t       *cr)
 {
+  GskPixelShaderNode *self = (GskPixelShaderNode *) node;
+
   cairo_save (cr);
   cairo_set_source_rgb (cr, 1, 0, 0);
   cairo_paint (cr);
   cairo_restore (cr);
+
+  if (self->child1)
+    gsk_render_node_draw (self->child1, cr);
+  if (self->child2)
+    gsk_render_node_draw (self->child2, cr);
 }
 
-#define GSK_PIXEL_SHADER_NODE_VARIANT_TYPE "(ddddayayd)"
+#define GSK_PIXEL_SHADER_NODE_VARIANT_TYPE "(dddda(uv)ayayd)"
 
 static GVariant *
 gsk_pixel_shader_node_serialize (GskRenderNode *node)
 {
   GskPixelShaderNode *self = (GskPixelShaderNode *) node;
+  GVariantBuilder builder;
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE (GSK_CONTAINER_NODE_VARIANT_TYPE));
+
+  if (self->child1)
+    g_variant_builder_add (&builder, "(uv)",
+                           (guint32) gsk_render_node_get_node_type (self->child1),
+                           gsk_render_node_serialize_node (self->child1));
+  if (self->child2)
+    g_variant_builder_add (&builder, "(uv)",
+                           (guint32) gsk_render_node_get_node_type (self->child2),
+                           gsk_render_node_serialize_node (self->child2));
 
-  return g_variant_new ("(dddd@ay@ayd)",
+  return g_variant_new ("(dddd@ay@ayda(uv))",
                         (double) node->bounds.origin.x, (double) node->bounds.origin.y,
                         (double) node->bounds.size.width, (double) node->bounds.size.height,
+                         &builder,
                          g_variant_new_fixed_array (G_VARIANT_TYPE ("y"),
                                                     g_bytes_get_data (self->vertex_bytes, NULL),
                                                     g_bytes_get_size (self->vertex_bytes), 1),
@@ -4425,10 +4453,37 @@ gsk_pixel_shader_node_deserialize (GVariant  *variant,
   GBytes *vertex_bytes;
   GBytes *fragment_bytes;
   GskRenderNode *node;
+  GVariantIter *iter;
+  gsize i, n_children;
+  guint32 child_type;
+  GVariant *child_variant;
+  GskRenderNode *children[2] = { NULL, NULL };
 
-  g_variant_get (variant, "(dddd@ay@ay)",
+  if (!check_variant_type (variant, GSK_PIXEL_SHADER_NODE_VARIANT_TYPE, error))
+    return NULL;
+
+  g_variant_get (variant, "(dddda(uv)@ay@ay)",
                  &bounds[0], &bounds[1], &bounds[2], &bounds[3],
-                 &vertex_variant, &fragment_variant, &time);
+                 &iter, &vertex_variant, &fragment_variant, &time);
+
+  n_children = g_variant_iter_init (iter, variant);
+  if (n_children > 2)
+    return NULL;
+
+  i = 0;
+  while (g_variant_iter_loop (iter, "(uv)", &child_type, &child_variant))
+    {
+      children[i] = gsk_render_node_deserialize_node (child_type, child_variant, error);
+      if (children[i] == NULL)
+        {
+          guint j;
+          for (j = 0; j < i; j++)
+            gsk_render_node_unref (children[j]);
+          g_variant_unref (child_variant);
+          return NULL;
+        }
+      i++;
+    }
 
   /* XXX: Make this work without copying the data */
   data = g_variant_get_fixed_array (vertex_variant, &length, 1);
@@ -4438,8 +4493,14 @@ gsk_pixel_shader_node_deserialize (GVariant  *variant,
   fragment_bytes = g_bytes_new (data, length);
 
   node = gsk_pixel_shader_node_new (&GRAPHENE_RECT_INIT(bounds[0], bounds[1], bounds[2], bounds[3]),
+                                    children[0], children[1],
                                     vertex_bytes, fragment_bytes, time);
 
+  if (children[0])
+    gsk_render_node_unref (children[0]);
+  if (children[1])
+    gsk_render_node_unref (children[1]);
+
   g_bytes_unref (vertex_bytes);
   g_bytes_unref (fragment_bytes);
   g_variant_unref (vertex_variant);
@@ -4459,16 +4520,30 @@ static const GskRenderNodeClass GSK_PIXEL_SHADER_NODE_CLASS = {
 };
 
 GskRenderNode *
-gsk_pixel_shader_node_new (const graphene_rect_t *bounds,
-                           GBytes                *vertex_bytes,
-                           GBytes                *fragment_bytes,
-                           float                  time)
+gsk_pixel_shader_node_new (const graphene_rect_t  *bounds,
+                           GskRenderNode          *child1,
+                           GskRenderNode          *child2,
+                           GBytes                 *vertex_bytes,
+                           GBytes                 *fragment_bytes,
+                           float                   time)
 {
   GskPixelShaderNode *self;
+  guint i;
 
   self = (GskPixelShaderNode *) gsk_render_node_new (&GSK_PIXEL_SHADER_NODE_CLASS, 0);
 
+  if (child1)
+    self->child1 = gsk_render_node_ref (child1);
+  else
+    self->child1 = NULL;
+
+  if (child2)
+    self->child2 = gsk_render_node_ref (child2);
+  else
+    self->child2 = NULL;
+
   graphene_rect_init_from_rect (&self->render_node.bounds, bounds);
+
   self->vertex_bytes = g_bytes_ref (vertex_bytes);
   self->fragment_bytes = g_bytes_ref (fragment_bytes);
   self->time = time;
@@ -4506,6 +4581,26 @@ gsk_pixel_shader_node_get_time (GskRenderNode *node)
   return self->time;
 }
 
+GskRenderNode *
+gsk_pixel_shader_node_get_child1 (GskRenderNode *node)
+{
+  GskPixelShaderNode *self = (GskPixelShaderNode *) node;
+
+  g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_PIXEL_SHADER_NODE), 0);
+
+  return self->child1;
+}
+
+GskRenderNode *
+gsk_pixel_shader_node_get_child2 (GskRenderNode *node)
+{
+  GskPixelShaderNode *self = (GskPixelShaderNode *) node;
+
+  g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_PIXEL_SHADER_NODE), 0);
+
+  return self->child2;
+}
+
 /*** ***/
 
 static const GskRenderNodeClass *klasses[] = {
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 7b29e94..b674534 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -113,6 +113,8 @@ double gsk_blur_node_get_radius (GskRenderNode *node);
 GBytes * gsk_pixel_shader_node_get_vertex_bytes (GskRenderNode *node);
 GBytes * gsk_pixel_shader_node_get_fragment_bytes (GskRenderNode *node);
 float    gsk_pixel_shader_node_get_time (GskRenderNode *node);
+GskRenderNode *gsk_pixel_shader_node_get_child1     (GskRenderNode *node);
+GskRenderNode *gsk_pixel_shader_node_get_child2     (GskRenderNode *node);
 
 G_END_DECLS
 
diff --git a/gsk/gskvulkancustompipeline.c b/gsk/gskvulkancustompipeline.c
index 4b69f6f..53c45c9 100644
--- a/gsk/gskvulkancustompipeline.c
+++ b/gsk/gskvulkancustompipeline.c
@@ -12,6 +12,8 @@ typedef struct _GskVulkanCustomInstance GskVulkanCustomInstance;
 struct _GskVulkanCustomInstance
 {
   float rect[4];
+  float tex_rect1[4];
+  float tex_rect2[4];
   float time;
 };
 
@@ -37,6 +39,18 @@ gsk_vulkan_custom_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
       {
           .location = 1,
           .binding = 0,
+          .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+          .offset = G_STRUCT_OFFSET (GskVulkanCustomInstance, tex_rect1),
+      },
+      {
+          .location = 2,
+          .binding = 0,
+          .format = VK_FORMAT_R32G32B32A32_SFLOAT,
+          .offset = G_STRUCT_OFFSET (GskVulkanCustomInstance, tex_rect2),
+      },
+      {
+          .location = 3,
+          .binding = 0,
           .format = VK_FORMAT_R32_SFLOAT,
           .offset = G_STRUCT_OFFSET (GskVulkanCustomInstance, time),
       },
@@ -132,15 +146,27 @@ gsk_vulkan_custom_pipeline_count_vertex_data (GskVulkanCustomPipeline *pipeline)
 void
 gsk_vulkan_custom_pipeline_collect_vertex_data (GskVulkanCustomPipeline *pipeline,
                                                 guchar                  *data,
-                                                const graphene_rect_t   *rect,
+                                                const graphene_rect_t   *bounds,
+                                                const graphene_rect_t   *child1_bounds,
+                                                const graphene_rect_t   *child2_bounds,
                                                 float                    time)
 {
   GskVulkanCustomInstance *instance = (GskVulkanCustomInstance *) data;
 
-  instance->rect[0] = rect->origin.x;
-  instance->rect[1] = rect->origin.y;
-  instance->rect[2] = rect->size.width;
-  instance->rect[3] = rect->size.height;
+  instance->rect[0] = bounds->origin.x;
+  instance->rect[1] = bounds->origin.y;
+  instance->rect[2] = bounds->size.width;
+  instance->rect[3] = bounds->size.height;
+
+  instance->tex_rect1[0] = (bounds->origin.x - child1_bounds->origin.x)/child1_bounds->size.width;
+  instance->tex_rect1[1] = (bounds->origin.y - child1_bounds->origin.y)/child1_bounds->size.height;
+  instance->tex_rect1[2] = (bounds->size.width + bounds->origin.x - 
child1_bounds->origin.x)/child1_bounds->size.width;
+  instance->tex_rect1[3] = (bounds->size.height + bounds->origin.y - 
child1_bounds->origin.y)/child1_bounds->size.height;
+
+  instance->tex_rect2[0] = (bounds->origin.x - child2_bounds->origin.x)/child2_bounds->size.width;
+  instance->tex_rect2[1] = (bounds->origin.y - child2_bounds->origin.y)/child2_bounds->size.height;
+  instance->tex_rect2[2] = (bounds->size.width + bounds->origin.x - 
child2_bounds->origin.x)/child2_bounds->size.width;
+  instance->tex_rect2[3] = (bounds->size.height + bounds->origin.y - 
child2_bounds->origin.y)/child2_bounds->size.height;
 
   instance->time = time;
 }
diff --git a/gsk/gskvulkancustompipelineprivate.h b/gsk/gskvulkancustompipelineprivate.h
index f430bc3..e196598 100644
--- a/gsk/gskvulkancustompipelineprivate.h
+++ b/gsk/gskvulkancustompipelineprivate.h
@@ -23,6 +23,8 @@ gsize                   gsk_vulkan_custom_pipeline_count_vertex_data     (GskVul
 void                    gsk_vulkan_custom_pipeline_collect_vertex_data   (GskVulkanCustomPipeline   
*pipeline,
                                                                           guchar                  *data,
                                                                           const graphene_rect_t   *rect,
+                                                                          const graphene_rect_t   
*child1_bounds,
+                                                                          const graphene_rect_t   
*child2_bounds,
                                                                           float                    time);
 gsize                   gsk_vulkan_custom_pipeline_draw                  (GskVulkanCustomPipeline   
*pipeline,
                                                                           VkCommandBuffer          
command_buffer,
diff --git a/gsk/gskvulkanrender.c b/gsk/gskvulkanrender.c
index f5ef788..044f7b3 100644
--- a/gsk/gskvulkanrender.c
+++ b/gsk/gskvulkanrender.c
@@ -418,9 +418,8 @@ gsk_vulkan_render_get_custom_pipeline (GskVulkanRender *self,
 {
   GskVulkanPipeline *pipeline;
 
-
   pipeline = gsk_vulkan_custom_pipeline_new (self->vulkan,
-                                             self->pipeline_layout[0],
+                                             self->pipeline_layout[2],
                                              vertex_bytes,
                                              fragment_bytes,
                                              self->render_pass);
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
index f158616..a339cf0 100644
--- a/gsk/gskvulkanrenderpass.c
+++ b/gsk/gskvulkanrenderpass.c
@@ -787,6 +787,30 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
           }
           break;
 
+        case GSK_VULKAN_OP_PIXEL_SHADER:
+          {
+            GskRenderNode *child1 = gsk_pixel_shader_node_get_child1 (op->render.node);
+            GskRenderNode *child2 = gsk_pixel_shader_node_get_child2 (op->render.node);
+
+            if (child1)
+              op->render.source = gsk_vulkan_render_pass_get_node_as_texture (self,
+                                                                              render,
+                                                                              uploader,
+                                                                              child1,
+                                                                              &child1->bounds);
+            else
+              op->render.source = NULL;
+            if (child2)
+              op->render.source2 = gsk_vulkan_render_pass_get_node_as_texture (self,
+                                                                               render,
+                                                                               uploader,
+                                                                               child2,
+                                                                               &child2->bounds);
+            else
+              op->render.source2 = NULL;
+          }
+          break;
+
         default:
           g_assert_not_reached ();
         case GSK_VULKAN_OP_COLOR:
@@ -795,7 +819,6 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass  *self,
         case GSK_VULKAN_OP_BORDER:
         case GSK_VULKAN_OP_INSET_SHADOW:
         case GSK_VULKAN_OP_OUTSET_SHADOW:
-        case GSK_VULKAN_OP_PIXEL_SHADER:
           break;
         }
     }
@@ -1107,10 +1130,15 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
 
         case GSK_VULKAN_OP_PIXEL_SHADER:
           {
+            GskRenderNode *child1 = gsk_pixel_shader_node_get_child1 (op->render.node);
+            GskRenderNode *child2 = gsk_pixel_shader_node_get_child2 (op->render.node);
+
             op->render.vertex_offset = offset + n_bytes;
             gsk_vulkan_custom_pipeline_collect_vertex_data (GSK_VULKAN_CUSTOM_PIPELINE (op->render.pipeline),
                                                             data + n_bytes + offset,
                                                             &op->render.node->bounds,
+                                                            child1 ? &child1->bounds : 
&GRAPHENE_RECT_INIT(0,0,0,0),
+                                                            child2 ? &child2->bounds : 
&GRAPHENE_RECT_INIT(0,0,0,0),
                                                             gsk_pixel_shader_node_get_time 
(op->render.node));
             n_bytes += op->render.vertex_count;
           }
@@ -1152,6 +1180,13 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
           op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source);
           break;
 
+        case GSK_VULKAN_OP_PIXEL_SHADER:
+          if (op->render.source)
+            op->render.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source);
+          if (op->render.source2)
+            op->render.descriptor_set_index2 = gsk_vulkan_render_reserve_descriptor_set (render, 
op->render.source2);
+          break;
+
         case GSK_VULKAN_OP_TEXT:
         case GSK_VULKAN_OP_COLOR_TEXT:
           op->text.descriptor_set_index = gsk_vulkan_render_reserve_descriptor_set (render, op->text.source);
@@ -1171,7 +1206,6 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
         case GSK_VULKAN_OP_BORDER:
         case GSK_VULKAN_OP_INSET_SHADOW:
         case GSK_VULKAN_OP_OUTSET_SHADOW:
-        case GSK_VULKAN_OP_PIXEL_SHADER:
           break;
         }
     }
@@ -1552,6 +1586,23 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass     *self,
               current_draw_index = 0;
             }
 
+          {
+            VkDescriptorSet ds[2];
+            gsize size = 0;
+            if (op->render.source != NULL)
+              ds[size++] = gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index);
+            if (op->render.source2 != NULL)
+              ds[size++] = gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index2);
+            vkCmdBindDescriptorSets (command_buffer,
+                                     VK_PIPELINE_BIND_POINT_GRAPHICS,
+                                     gsk_vulkan_pipeline_get_pipeline_layout (current_pipeline),
+                                     0,
+                                     size,
+                                     ds,
+                                     0,
+                                     NULL);
+          }
+
           current_draw_index += gsk_vulkan_custom_pipeline_draw (GSK_VULKAN_CUSTOM_PIPELINE 
(current_pipeline),
                                                                  command_buffer,
                                                                  current_draw_index, 1);


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