[gtk+/wip/matthiasc/shadertoy] Allow custom pipelines to have textures
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/matthiasc/shadertoy] Allow custom pipelines to have textures
- Date: Sun, 24 Sep 2017 18:49:50 +0000 (UTC)
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]