vulkan: Sort the ops
authorBenjamin Otte <otte@redhat.com>
Sun, 9 Jul 2023 21:45:20 +0000 (23:45 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 16 Jul 2023 10:13:00 +0000 (12:13 +0200)
Use the OpClass.stage to order operations:

1. Put upload ops first
   This way we can ensure they are executed first.
2. Move subpasses for offscreens in front of the pass using them.

gsk/vulkan/gskvulkanrender.c

index 98d0ac38deb307691e69553cd461a24db11f4e19..33b7068500752d00eb192a50ccfc6847133a5967 100644 (file)
@@ -395,6 +395,95 @@ gsk_vulkan_render_seal_ops (GskVulkanRender *self)
     }
 }
 
+typedef struct 
+{
+  struct {
+    GskVulkanOp *first;
+    GskVulkanOp *last;
+  } upload, command;
+} SortData;
+
+static GskVulkanOp *
+gsk_vulkan_render_sort_render_pass (GskVulkanRender *self,
+                                    GskVulkanOp     *op,
+                                    SortData        *sort_data)
+{
+  while (op)
+    {
+      switch (op->op_class->stage)
+      {
+        case GSK_VULKAN_STAGE_UPLOAD:
+          if (sort_data->upload.first == NULL)
+            sort_data->upload.first = op;
+          else
+            sort_data->upload.last->next = op;
+          sort_data->upload.last = op;
+          op = op->next;
+          break;
+
+        case GSK_VULKAN_STAGE_COMMAND:
+          if (sort_data->command.first == NULL)
+            sort_data->command.first = op;
+          else
+            sort_data->command.last->next = op;
+          sort_data->command.last = op;
+          op = op->next;
+          break;
+
+        case GSK_VULKAN_STAGE_BEGIN_PASS:
+          {
+            SortData pass_data = { { NULL, NULL }, { op, op } };
+
+            op = gsk_vulkan_render_sort_render_pass (self, op->next, &pass_data);
+
+            if (pass_data.upload.first)
+              {
+                if (sort_data->upload.last == NULL)
+                  sort_data->upload.last = pass_data.upload.last;
+                else
+                  pass_data.upload.last->next = sort_data->upload.first;
+                sort_data->upload.first = pass_data.upload.first;
+              }
+            if (sort_data->command.last == NULL)
+              sort_data->command.last = pass_data.command.last;
+            else
+              pass_data.command.last->next = sort_data->command.first;
+            sort_data->command.first = pass_data.command.first;
+          }
+          break;
+
+        case GSK_VULKAN_STAGE_END_PASS:
+          sort_data->command.last->next = op;
+          sort_data->command.last = op;
+          return op->next;
+
+        default:
+          g_assert_not_reached ();
+          break;
+      }
+    }
+
+  return op;
+}
+
+static void
+gsk_vulkan_render_sort_ops (GskVulkanRender *self)
+{
+  SortData sort_data = { { NULL, }, };
+  
+  gsk_vulkan_render_sort_render_pass (self, self->first_op, &sort_data);
+
+  if (sort_data.upload.first)
+    {
+      sort_data.upload.last->next = sort_data.command.first;
+      self->first_op = sort_data.upload.first;
+    }
+  else
+    self->first_op = sort_data.command.first;
+  if (sort_data.command.last)
+    sort_data.command.last->next = NULL;
+}
+
 static void
 gsk_vulkan_render_add_node (GskVulkanRender *self,
                             GskRenderNode   *node)
@@ -415,8 +504,9 @@ gsk_vulkan_render_add_node (GskVulkanRender *self,
   gsk_vulkan_render_pass_add (self->render_pass, self, node);
 
   gsk_vulkan_render_seal_ops (self);
-
   gsk_vulkan_render_verbose_print (self, "start of frame");
+  gsk_vulkan_render_sort_ops (self);
+  gsk_vulkan_render_verbose_print (self, "after sort");
 }
 
 void