[gtk+] vulkan: Fold clip into push constants



commit 81c487b8415fed4990b069b03245b2aa11f12ab7
Author: Benjamin Otte <otte redhat com>
Date:   Sat Dec 24 04:58:51 2016 +0100

    vulkan: Fold clip into push constants
    
    As a side effect, the clipping data is now available inside shaders.
    
    Not that any shader would use them yet, but they could!

 gsk/gskroundedrect.c                 |   30 +++++++++++++
 gsk/gskroundedrectprivate.h          |    2 +
 gsk/gskvulkanclip.c                  |   28 ++++++++++++
 gsk/gskvulkanclipprivate.h           |    4 ++
 gsk/gskvulkanpushconstants.c         |   44 +++++++++++++++++---
 gsk/gskvulkanpushconstantsprivate.h  |   18 +++++++-
 gsk/gskvulkanrenderpass.c            |   76 ++++++++++++++++++---------------
 gsk/resources/vulkan/blit.vert.glsl  |    3 +
 gsk/resources/vulkan/blit.vert.spv   |  Bin 1104 -> 1252 bytes
 gsk/resources/vulkan/color.vert.glsl |    3 +
 gsk/resources/vulkan/color.vert.spv  |  Bin 1632 -> 1780 bytes
 11 files changed, 164 insertions(+), 44 deletions(-)
---
diff --git a/gsk/gskroundedrect.c b/gsk/gskroundedrect.c
index 16ad85e..03f987e 100644
--- a/gsk/gskroundedrect.c
+++ b/gsk/gskroundedrect.c
@@ -501,3 +501,33 @@ gsk_rounded_rect_path (const GskRoundedRect *self,
   cairo_close_path (cr);
 }
 
+/*
+ * Converts to the format we use in our shaders:
+ * vec4 rect;
+ * vec4 corner_widths;
+ * vec4 corner_heights;
+ * rect is (x, y, width, height), the corners are the same
+ * order as in the rounded rect.
+ *
+ * This is so that shaders can use just the first vec4 for
+ * rectilinear rects, the 2nd vec4 for circular rects and
+ * only look at the last vec4 if they have to.
+ */
+void
+gsk_rounded_rect_to_float (const GskRoundedRect *self,
+                           float                 rect[12])
+{
+  guint i;
+
+  rect[0] = self->bounds.origin.x;
+  rect[1] = self->bounds.origin.y;
+  rect[2] = self->bounds.size.width;
+  rect[3] = self->bounds.size.height;
+
+  for (i = 0; i < 4; i++)
+    {
+      rect[4 + i] = self->corner[i].width;
+      rect[8 + i] = self->corner[i].height;
+    }
+}
+
diff --git a/gsk/gskroundedrectprivate.h b/gsk/gskroundedrectprivate.h
index d11567a..5b40cb4 100644
--- a/gsk/gskroundedrectprivate.h
+++ b/gsk/gskroundedrectprivate.h
@@ -11,6 +11,8 @@ gboolean                 gsk_rounded_rect_is_circular           (const GskRounde
 
 void                     gsk_rounded_rect_path                  (const GskRoundedRect     *self,
                                                                  cairo_t                  *cr);
+void                     gsk_rounded_rect_to_float              (const GskRoundedRect     *self,
+                                                                 float                     rect[12]);
 
 G_END_DECLS
 
diff --git a/gsk/gskvulkanclip.c b/gsk/gskvulkanclip.c
index 38755f5..9a3ad86 100644
--- a/gsk/gskvulkanclip.c
+++ b/gsk/gskvulkanclip.c
@@ -128,6 +128,34 @@ gsk_vulkan_clip_intersect_rounded_rect (GskVulkanClip        *dest,
 }
 
 gboolean
+gsk_vulkan_clip_transform (GskVulkanClip           *dest,
+                           const GskVulkanClip     *src,
+                           const graphene_matrix_t *transform,
+                           const graphene_rect_t   *viewport)
+{
+  switch (dest->type)
+    {
+    default:
+      g_assert_not_reached();
+      return FALSE;
+
+    case GSK_VULKAN_CLIP_ALL_CLIPPED:
+      gsk_vulkan_clip_init_copy (dest, src);
+      return TRUE;
+
+    case GSK_VULKAN_CLIP_NONE:
+      gsk_vulkan_clip_init_empty (dest, viewport);
+      return TRUE;
+
+    case GSK_VULKAN_CLIP_RECT:
+    case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
+    case GSK_VULKAN_CLIP_ROUNDED:
+      /* FIXME: Handle 2D operations, in particular transform and scale */
+      return FALSE;
+    }
+}
+
+gboolean
 gsk_vulkan_clip_contains_rect (const GskVulkanClip   *self,
                                const graphene_rect_t *rect)
 {
diff --git a/gsk/gskvulkanclipprivate.h b/gsk/gskvulkanclipprivate.h
index 492ef4c..99450af 100644
--- a/gsk/gskvulkanclipprivate.h
+++ b/gsk/gskvulkanclipprivate.h
@@ -44,6 +44,10 @@ gboolean                gsk_vulkan_clip_intersect_rect                  (GskVulk
 gboolean                gsk_vulkan_clip_intersect_rounded_rect          (GskVulkanClip          *dest,
                                                                          const GskVulkanClip    *src,
                                                                          const GskRoundedRect   *rounded) 
G_GNUC_WARN_UNUSED_RESULT;
+gboolean                gsk_vulkan_clip_transform                       (GskVulkanClip          *dest,
+                                                                         const GskVulkanClip    *src,
+                                                                         const graphene_matrix_t*transform,
+                                                                         const graphene_rect_t  *viewport) 
G_GNUC_WARN_UNUSED_RESULT;
 
 gboolean                gsk_vulkan_clip_contains_rect                   (const GskVulkanClip    *self,
                                                                          const graphene_rect_t  *rect) 
G_GNUC_WARN_UNUSED_RESULT;
diff --git a/gsk/gskvulkanpushconstants.c b/gsk/gskvulkanpushconstants.c
index 4487687..f7daf1a 100644
--- a/gsk/gskvulkanpushconstants.c
+++ b/gsk/gskvulkanpushconstants.c
@@ -2,13 +2,15 @@
 
 #include "gskvulkanpushconstantsprivate.h"
 
-#include <math.h>
+#include "gskroundedrectprivate.h"
 
 void
 gsk_vulkan_push_constants_init (GskVulkanPushConstants  *constants,
-                                const graphene_matrix_t *mvp)
+                                const graphene_matrix_t *mvp,
+                                const graphene_rect_t   *viewport)
 {
   graphene_matrix_init_from_matrix (&constants->mvp, mvp);
+  gsk_vulkan_clip_init_empty (&constants->clip, viewport);
 }
 
 void
@@ -18,13 +20,42 @@ gsk_vulkan_push_constants_init_copy (GskVulkanPushConstants       *self,
   *self = *src;
 }
 
-void
-gsk_vulkan_push_constants_init_transform (GskVulkanPushConstants       *self,
-                                          const GskVulkanPushConstants *src,
-                                          const graphene_matrix_t      *transform)
+gboolean
+gsk_vulkan_push_constants_transform (GskVulkanPushConstants       *self,
+                                     const GskVulkanPushConstants *src,
+                                     const graphene_matrix_t      *transform,
+                                     const graphene_rect_t        *viewport)
 
 {
+  if (!gsk_vulkan_clip_transform (&self->clip, &src->clip, transform, viewport))
+    return FALSE;
+
   graphene_matrix_multiply (transform, &src->mvp, &self->mvp);
+  return TRUE;
+}
+
+gboolean
+gsk_vulkan_push_constants_intersect_rect (GskVulkanPushConstants       *self,
+                                          const GskVulkanPushConstants *src,
+                                          const graphene_rect_t        *rect)
+{
+  if (!gsk_vulkan_clip_intersect_rect (&self->clip, &src->clip, rect))
+    return FALSE;
+
+  graphene_matrix_init_from_matrix (&self->mvp, &src->mvp);
+  return TRUE;
+}
+
+gboolean
+gsk_vulkan_push_constants_intersect_rounded (GskVulkanPushConstants       *self,
+                                             const GskVulkanPushConstants *src,
+                                             const GskRoundedRect         *rect)
+{
+  if (!gsk_vulkan_clip_intersect_rounded_rect (&self->clip, &src->clip, rect))
+    return FALSE;
+
+  graphene_matrix_init_from_matrix (&self->mvp, &src->mvp);
+  return TRUE;
 }
 
 static void
@@ -32,6 +63,7 @@ gsk_vulkan_push_constants_wire_init (GskVulkanPushConstantsWire   *wire,
                                      const GskVulkanPushConstants *self)
 {
   graphene_matrix_to_float (&self->mvp, wire->vertex.mvp);
+  gsk_rounded_rect_to_float (&self->clip.rect, wire->vertex.clip);
 }
 
 void
diff --git a/gsk/gskvulkanpushconstantsprivate.h b/gsk/gskvulkanpushconstantsprivate.h
index bdfd111..4642d52 100644
--- a/gsk/gskvulkanpushconstantsprivate.h
+++ b/gsk/gskvulkanpushconstantsprivate.h
@@ -3,6 +3,7 @@
 
 #include <gdk/gdk.h>
 #include <graphene.h>
+#include <gsk/gskvulkanclipprivate.h>
 
 G_BEGIN_DECLS
 
@@ -12,12 +13,14 @@ typedef struct _GskVulkanPushConstantsWire GskVulkanPushConstantsWire;
 struct _GskVulkanPushConstants
 {
   graphene_matrix_t mvp;
+  GskVulkanClip clip;
 };
 
 struct _GskVulkanPushConstantsWire
 {
   struct {
     float mvp[16];
+    float clip[12];
   } vertex;
 #if 0
   struct {
@@ -30,12 +33,21 @@ const VkPushConstantRange *
 uint32_t                gst_vulkan_push_constants_get_range_count       (void) G_GNUC_PURE;
 
 void                    gsk_vulkan_push_constants_init                  (GskVulkanPushConstants         
*constants,
-                                                                         const graphene_matrix_t        
*mvp);
+                                                                         const graphene_matrix_t        *mvp,
+                                                                         const graphene_rect_t          
*viewport);
 void                    gsk_vulkan_push_constants_init_copy             (GskVulkanPushConstants         
*self,
                                                                          const GskVulkanPushConstants   
*src);
-void                    gsk_vulkan_push_constants_init_transform        (GskVulkanPushConstants         
*self,
+
+gboolean                gsk_vulkan_push_constants_transform             (GskVulkanPushConstants         
*self,
+                                                                         const GskVulkanPushConstants   *src,
+                                                                         const graphene_matrix_t        
*transform,
+                                                                         const graphene_rect_t          
*viewport);
+gboolean                gsk_vulkan_push_constants_intersect_rect        (GskVulkanPushConstants         
*self,
+                                                                         const GskVulkanPushConstants   *src,
+                                                                         const graphene_rect_t          
*rect);
+gboolean                gsk_vulkan_push_constants_intersect_rounded     (GskVulkanPushConstants         
*self,
                                                                          const GskVulkanPushConstants   *src,
-                                                                         const graphene_matrix_t        
*transform);
+                                                                         const GskRoundedRect           
*rect);
 
 void                    gsk_vulkan_push_constants_push_vertex           (const GskVulkanPushConstants   
*self,
                                                                          VkCommandBuffer                 
command_buffer,
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
index 796ba62..dc26f31 100644
--- a/gsk/gskvulkanrenderpass.c
+++ b/gsk/gskvulkanrenderpass.c
@@ -92,7 +92,6 @@ void
 gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
                                  GskVulkanRender               *render,
                                  const GskVulkanPushConstants  *constants,
-                                 const GskVulkanClip           *clip,
                                  GskRenderNode                 *node)
 {
   GskVulkanOp op = {
@@ -111,24 +110,24 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
     case GSK_CAIRO_NODE:
       if (gsk_cairo_node_get_surface (node) == NULL)
         return;
-      if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds))
-        FALLBACK ("Cairo nodes can't deal with clip type %u\n", clip->type);
+      if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+        FALLBACK ("Cairo nodes can't deal with clip type %u\n", constants->clip.type);
       op.type = GSK_VULKAN_OP_SURFACE;
       op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_BLIT);
       g_array_append_val (self->render_ops, op);
       return;
 
     case GSK_TEXTURE_NODE:
-      if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds))
-        FALLBACK ("Texture nodes can't deal with clip type %u\n", clip->type);
+      if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+        FALLBACK ("Texture nodes can't deal with clip type %u\n", constants->clip.type);
       op.type = GSK_VULKAN_OP_TEXTURE;
       op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_BLIT);
       g_array_append_val (self->render_ops, op);
       return;
 
     case GSK_COLOR_NODE:
-      if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds))
-        FALLBACK ("Color nodes can't deal with clip type %u\n", clip->type);
+      if (!gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
+        FALLBACK ("Color nodes can't deal with clip type %u\n", constants->clip.type);
       op.type = GSK_VULKAN_OP_COLOR;
       op.render.pipeline = gsk_vulkan_render_get_pipeline (render, GSK_VULKAN_PIPELINE_COLOR);
       g_array_append_val (self->render_ops, op);
@@ -140,7 +139,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
 
         for (i = 0; i < gsk_container_node_get_n_children (node); i++)
           {
-            gsk_vulkan_render_pass_add_node (self, render, constants, clip, gsk_container_node_get_child 
(node, i));
+            gsk_vulkan_render_pass_add_node (self, render, constants, gsk_container_node_get_child (node, 
i));
           }
       }
       return;
@@ -148,21 +147,21 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
     case GSK_TRANSFORM_NODE:
       {
         graphene_matrix_t transform;
-        GskVulkanClip new_clip;
-        graphene_rect_t rect;
+        GskRenderNode *child;
 
+#if 0
         if (!gsk_vulkan_clip_contains_rect (clip, &node->bounds))
           FALLBACK ("Transform nodes can't deal with clip type %u\n", clip->type);
+#endif
 
         gsk_transform_node_get_transform (node, &transform);
+        child = gsk_transform_node_get_child (node);
+        if (!gsk_vulkan_push_constants_transform (&op.constants.constants, constants, &transform, 
&child->bounds))
+          FALLBACK ("Transform nodes can't deal with clip type %u\n", constants->clip.type);
         op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
-        gsk_vulkan_push_constants_init_transform (&op.constants.constants, constants, &transform);
         g_array_append_val (self->render_ops, op);
 
-        graphene_matrix_transform_bounds (&transform, &clip->rect.bounds, &rect);
-        gsk_vulkan_clip_init_empty (&new_clip, &rect);
-
-        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &new_clip, 
gsk_transform_node_get_child (node));
+        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, child);
         gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants);
         g_array_append_val (self->render_ops, op);
       }
@@ -170,27 +169,37 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
 
     case GSK_CLIP_NODE:
       {
-        GskVulkanClip new_clip;
-
-        if (!gsk_vulkan_clip_intersect_rect (&new_clip, clip, gsk_clip_node_peek_clip (node)))
-          FALLBACK ("Failed to find intersection between clip of type %u and rectangle\n", clip->type);
-        if (new_clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
+        if (!gsk_vulkan_push_constants_intersect_rect (&op.constants.constants, constants, 
gsk_clip_node_peek_clip (node)))
+          FALLBACK ("Failed to find intersection between clip of type %u and rectangle\n", 
constants->clip.type);
+        if (&op.constants.constants.clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
           return;
 
-        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &new_clip, 
gsk_clip_node_get_child (node));
+        op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
+        g_array_append_val (self->render_ops, op);
+
+        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, gsk_clip_node_get_child 
(node));
+
+        gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants);
+        g_array_append_val (self->render_ops, op);
       }
       return;
 
     case GSK_ROUNDED_CLIP_NODE:
       {
-        GskVulkanClip new_clip;
-
-        if (!gsk_vulkan_clip_intersect_rounded_rect (&new_clip, clip, gsk_rounded_clip_node_peek_clip 
(node)))
-          FALLBACK ("Failed to find intersection between clip of type %u and rounded rectangle\n", 
clip->type);
-        if (new_clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
+        if (!gsk_vulkan_push_constants_intersect_rounded (&op.constants.constants,
+                                                          constants,
+                                                          gsk_rounded_clip_node_peek_clip (node)))
+          FALLBACK ("Failed to find intersection between clip of type %u and rounded rectangle\n", 
constants->clip.type);
+        if (&op.constants.constants.clip.type == GSK_VULKAN_CLIP_ALL_CLIPPED)
           return;
 
-        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &new_clip, 
gsk_rounded_clip_node_get_child (node));
+        op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
+        g_array_append_val (self->render_ops, op);
+
+        gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, 
gsk_rounded_clip_node_get_child (node));
+
+        gsk_vulkan_push_constants_init_copy (&op.constants.constants, constants);
+        g_array_append_val (self->render_ops, op);
       }
       return;
     }
@@ -199,19 +208,19 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass           *self,
   return;
 
 fallback:
-  switch (clip->type)
+  switch (constants->clip.type)
     {
       case GSK_VULKAN_CLIP_NONE:
         op.type = GSK_VULKAN_OP_FALLBACK;
         break;
       case GSK_VULKAN_CLIP_RECT:
         op.type = GSK_VULKAN_OP_FALLBACK_CLIP;
-        gsk_rounded_rect_init_copy (&op.render.clip, &clip->rect);
+        gsk_rounded_rect_init_copy (&op.render.clip, &constants->clip.rect);
         break;
       case GSK_VULKAN_CLIP_ROUNDED_CIRCULAR:
       case GSK_VULKAN_CLIP_ROUNDED:
         op.type = GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP;
-        gsk_rounded_rect_init_copy (&op.render.clip, &clip->rect);
+        gsk_rounded_rect_init_copy (&op.render.clip, &constants->clip.rect);
         break;
       case GSK_VULKAN_CLIP_ALL_CLIPPED:
       default:
@@ -231,15 +240,12 @@ gsk_vulkan_render_pass_add (GskVulkanRenderPass     *self,
                             GskRenderNode           *node)
 {
   GskVulkanOp op = { 0, };
-  GskVulkanClip clip;
 
   op.type = GSK_VULKAN_OP_PUSH_VERTEX_CONSTANTS;
-  gsk_vulkan_push_constants_init (&op.constants.constants, mvp);
+  gsk_vulkan_push_constants_init (&op.constants.constants, mvp, viewport);
   g_array_append_val (self->render_ops, op);
 
-  gsk_vulkan_clip_init_empty (&clip, viewport);
-
-  gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, &clip, node);
+  gsk_vulkan_render_pass_add_node (self, render, &op.constants.constants, node);
 }
 
 static void
diff --git a/gsk/resources/vulkan/blit.vert.glsl b/gsk/resources/vulkan/blit.vert.glsl
index 2522b7e..ca78688 100644
--- a/gsk/resources/vulkan/blit.vert.glsl
+++ b/gsk/resources/vulkan/blit.vert.glsl
@@ -5,6 +5,9 @@ layout(location = 1) in vec2 inTexCoord;
 
 layout(push_constant) uniform PushConstants {
     mat4 mvp;
+    vec4 clip_bounds;
+    vec4 clip_widths;
+    vec4 clip_heights;
 } push;
 
 layout(location = 0) out vec2 outTexCoord;
diff --git a/gsk/resources/vulkan/blit.vert.spv b/gsk/resources/vulkan/blit.vert.spv
index 3deee1c..5ce7a27 100644
Binary files a/gsk/resources/vulkan/blit.vert.spv and b/gsk/resources/vulkan/blit.vert.spv differ
diff --git a/gsk/resources/vulkan/color.vert.glsl b/gsk/resources/vulkan/color.vert.glsl
index 78bbfe1..873ccfc 100644
--- a/gsk/resources/vulkan/color.vert.glsl
+++ b/gsk/resources/vulkan/color.vert.glsl
@@ -5,6 +5,9 @@ layout(location = 1) in vec4 inColor;
 
 layout(push_constant) uniform PushConstants {
     mat4 mvp;
+    vec4 clip_bounds;
+    vec4 clip_widths;
+    vec4 clip_heights;
 } push;
 
 layout(location = 0) out vec4 outColor;
diff --git a/gsk/resources/vulkan/color.vert.spv b/gsk/resources/vulkan/color.vert.spv
index f4a8791..0d571ef 100644
Binary files a/gsk/resources/vulkan/color.vert.spv and b/gsk/resources/vulkan/color.vert.spv differ


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