[gtk+/wip/otte/shader: 14/23] gskspv: Add GskSpvAccessChain
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 14/23] gskspv: Add GskSpvAccessChain
- Date: Tue, 10 Oct 2017 02:12:04 +0000 (UTC)
commit f4682dceef20cd15b1deb53e6f766857dca7fd3d
Author: Benjamin Otte <otte redhat com>
Date: Mon Oct 9 05:37:41 2017 +0200
gskspv: Add GskSpvAccessChain
And use it to implement assignments.
And because I rock, this is all assignments, including member variables
swizzles and *= assignments. So this works:
foo.member.rgba.rgb *= vec3(0);
gsk/gskslexpression.c | 128 ++++++++++++++++++++++++++++---
gsk/gsksltypesprivate.h | 1 +
gsk/gskslvariable.c | 6 ++
gsk/gskslvariableprivate.h | 1 +
gsk/gskspvwriter.c | 181 ++++++++++++++++++++++++++++++++++++++++++++
gsk/gskspvwriterprivate.h | 13 +++
6 files changed, 317 insertions(+), 13 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 76b6f5d..db7b4a2 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -51,6 +51,8 @@ struct _GskSlExpressionClass {
GskSlValue * (* get_constant) (const GskSlExpression *expression);
guint32 (* write_spv) (const GskSlExpression *expression,
GskSpvWriter *writer);
+ GskSpvAccessChain * (* get_spv_access_chain) (const GskSlExpression *expression,
+ GskSpvWriter *writer);
};
static GskSlExpression *
@@ -68,6 +70,13 @@ gsk_sl_expression_alloc (const GskSlExpressionClass *klass,
}
#define gsk_sl_expression_new(_name, _klass) ((_name *) gsk_sl_expression_alloc ((_klass), sizeof (_name)))
+static GskSpvAccessChain *
+gsk_sl_expression_get_spv_access_chain (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ return expression->class->get_spv_access_chain (expression, writer);
+}
+
static gboolean
gsk_sl_expression_default_is_assignable (const GskSlExpression *expression,
GError **error)
@@ -80,6 +89,13 @@ gsk_sl_expression_default_is_assignable (const GskSlExpression *expression,
return FALSE;
}
+static GskSpvAccessChain *
+gsk_sl_expression_default_get_spv_access_chain (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ return NULL;
+}
+
/* ASSIGNMENT */
typedef struct _GskSlExpressionAssignment GskSlExpressionAssignment;
@@ -88,6 +104,7 @@ struct _GskSlExpressionAssignment {
GskSlExpression parent;
const GskSlBinary *binary;
+ GskSlType *type;
GskSlExpression *lvalue;
GskSlExpression *rvalue;
};
@@ -99,6 +116,7 @@ gsk_sl_expression_assignment_free (GskSlExpression *expression)
gsk_sl_expression_unref (assignment->lvalue);
gsk_sl_expression_unref (assignment->rvalue);
+ gsk_sl_type_unref (assignment->type);
g_slice_free (GskSlExpressionAssignment, assignment);
}
@@ -135,9 +153,34 @@ static guint32
gsk_sl_expression_assignment_write_spv (const GskSlExpression *expression,
GskSpvWriter *writer)
{
- g_assert_not_reached ();
+ const GskSlExpressionAssignment *assignment = (const GskSlExpressionAssignment *) expression;
+ GskSpvAccessChain *chain;
+ GskSlType *rtype, *ltype;
+ guint32 rvalue;
- return 0;
+ chain = gsk_sl_expression_get_spv_access_chain (assignment->lvalue, writer);
+ g_assert (chain);
+ ltype = gsk_sl_expression_get_return_type (assignment->lvalue),
+ rtype = gsk_sl_expression_get_return_type (assignment->rvalue),
+ rvalue = gsk_sl_expression_write_spv (assignment->rvalue, writer);
+
+ if (assignment->binary)
+ {
+ rvalue = gsk_sl_binary_write_spv (assignment->binary,
+ writer,
+ assignment->type,
+ ltype,
+ gsk_spv_access_chain_load (chain),
+ rtype,
+ rvalue);
+ rtype = assignment->type;
+ }
+
+ rvalue = gsk_spv_writer_convert (writer, rvalue, ltype, rtype);
+ gsk_spv_access_chain_store (chain, rvalue);
+ gsk_spv_access_chain_free (chain);
+
+ return rvalue;
}
static const GskSlExpressionClass GSK_SL_EXPRESSION_ASSIGNMENT = {
@@ -146,7 +189,8 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_ASSIGNMENT = {
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_assignment_get_return_type,
gsk_sl_expression_assignment_get_constant,
- gsk_sl_expression_assignment_write_spv
+ gsk_sl_expression_assignment_write_spv,
+ gsk_sl_expression_default_get_spv_access_chain
};
/* BINARY */
@@ -219,7 +263,7 @@ gsk_sl_expression_binary_get_constant (const GskSlExpression *expression)
static guint32
gsk_sl_expression_binary_write_spv (const GskSlExpression *expression,
- GskSpvWriter *writer)
+ GskSpvWriter *writer)
{
const GskSlExpressionBinary *binary = (const GskSlExpressionBinary *) expression;
@@ -238,7 +282,8 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_BINARY = {
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_binary_get_return_type,
gsk_sl_expression_binary_get_constant,
- gsk_sl_expression_binary_write_spv
+ gsk_sl_expression_binary_write_spv,
+ gsk_sl_expression_default_get_spv_access_chain
};
/* REFERENCE */
@@ -324,13 +369,23 @@ gsk_sl_expression_reference_write_spv (const GskSlExpression *expression,
0);
}
+static GskSpvAccessChain *
+gsk_sl_expression_reference_get_spv_access_chain (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ GskSlExpressionReference *reference = (GskSlExpressionReference *) expression;
+
+ return gsk_spv_access_chain_new (writer, reference->variable);
+}
+
static const GskSlExpressionClass GSK_SL_EXPRESSION_REFERENCE = {
gsk_sl_expression_reference_free,
gsk_sl_expression_reference_print,
gsk_sl_expression_reference_is_assignable,
gsk_sl_expression_reference_get_return_type,
gsk_sl_expression_reference_get_constant,
- gsk_sl_expression_reference_write_spv
+ gsk_sl_expression_reference_write_spv,
+ gsk_sl_expression_reference_get_spv_access_chain
};
/* CONSTRUCTOR CALL */
@@ -707,7 +762,8 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_CONSTRUCTOR = {
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_constructor_get_return_type,
gsk_sl_expression_constructor_get_constant,
- gsk_sl_expression_constructor_write_spv
+ gsk_sl_expression_constructor_write_spv,
+ gsk_sl_expression_default_get_spv_access_chain
};
/* FUNCTION_CALL */
@@ -822,7 +878,8 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_FUNCTION_CALL = {
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_function_call_get_return_type,
gsk_sl_expression_function_call_get_constant,
- gsk_sl_expression_function_call_write_spv
+ gsk_sl_expression_function_call_write_spv,
+ gsk_sl_expression_default_get_spv_access_chain
};
/* MEMBER */
@@ -907,13 +964,37 @@ gsk_sl_expression_member_write_spv (const GskSlExpression *expression,
1);
}
+static GskSpvAccessChain *
+gsk_sl_expression_member_get_spv_access_chain (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression;
+ GskSpvAccessChain *chain;
+ GskSlValue *value;
+ GskSlType *type;
+
+ chain = gsk_sl_expression_get_spv_access_chain (member->expr, writer);
+ if (chain == NULL)
+ return NULL;
+
+ value = gsk_sl_value_new_for_data (gsk_sl_type_get_scalar (GSK_SL_INT), &(gint32) { member->id }, NULL,
NULL);
+ type = gsk_sl_expression_get_return_type (member->expr);
+ gsk_spv_access_chain_add_index (chain,
+ gsk_sl_type_get_member_type (type, member->id),
+ gsk_spv_writer_get_id_for_value (writer, value));
+ gsk_sl_value_free (value);
+
+ return chain;
+}
+
static const GskSlExpressionClass GSK_SL_EXPRESSION_MEMBER = {
gsk_sl_expression_member_free,
gsk_sl_expression_member_print,
gsk_sl_expression_member_is_assignable,
gsk_sl_expression_member_get_return_type,
gsk_sl_expression_member_get_constant,
- gsk_sl_expression_member_write_spv
+ gsk_sl_expression_member_write_spv,
+ gsk_sl_expression_member_get_spv_access_chain
};
/* SWIZZLE */
@@ -1096,13 +1177,32 @@ gsk_sl_expression_swizzle_write_spv (const GskSlExpression *expression,
}
}
+static GskSpvAccessChain *
+gsk_sl_expression_swizzle_get_spv_access_chain (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+ GskSpvAccessChain *chain;
+
+ chain = gsk_sl_expression_get_spv_access_chain (swizzle->expr, writer);
+ if (chain == NULL)
+ return NULL;
+
+ gsk_spv_access_chain_swizzle (chain,
+ swizzle->indexes,
+ swizzle->length);
+
+ return chain;
+}
+
static const GskSlExpressionClass GSK_SL_EXPRESSION_SWIZZLE = {
gsk_sl_expression_swizzle_free,
gsk_sl_expression_swizzle_print,
gsk_sl_expression_swizzle_is_assignable,
gsk_sl_expression_swizzle_get_return_type,
gsk_sl_expression_swizzle_get_constant,
- gsk_sl_expression_swizzle_write_spv
+ gsk_sl_expression_swizzle_write_spv,
+ gsk_sl_expression_swizzle_get_spv_access_chain
};
/* NEGATION */
@@ -1225,7 +1325,8 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_NEGATION = {
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_negation_get_return_type,
gsk_sl_expression_negation_get_constant,
- gsk_sl_expression_negation_write_spv
+ gsk_sl_expression_negation_write_spv,
+ gsk_sl_expression_default_get_spv_access_chain
};
/* CONSTANT */
@@ -1288,7 +1389,8 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_CONSTANT = {
gsk_sl_expression_default_is_assignable,
gsk_sl_expression_constant_get_return_type,
gsk_sl_expression_constant_get_constant,
- gsk_sl_expression_constant_write_spv
+ gsk_sl_expression_constant_write_spv,
+ gsk_sl_expression_default_get_spv_access_chain
};
/* If parsing fails completely, just assume 1.0 */
@@ -2483,6 +2585,7 @@ gsk_sl_expression_parse_assignment (GskSlScope *scope,
assign = gsk_sl_expression_new (GskSlExpressionAssignment, &GSK_SL_EXPRESSION_ASSIGNMENT);
assign->binary = binary;
+ assign->type = gsk_sl_type_ref (result_type);
assign->lvalue = lvalue;
assign->rvalue = rvalue;
@@ -2552,4 +2655,3 @@ gsk_sl_expression_write_spv (const GskSlExpression *expression,
{
return expression->class->write_spv (expression, writer);
}
-
diff --git a/gsk/gsksltypesprivate.h b/gsk/gsksltypesprivate.h
index c1f34b9..478dc27 100644
--- a/gsk/gsksltypesprivate.h
+++ b/gsk/gsksltypesprivate.h
@@ -36,6 +36,7 @@ typedef struct _GskSlType GskSlType;
typedef struct _GskSlValue GskSlValue;
typedef struct _GskSlVariable GskSlVariable;
+typedef struct _GskSpvAccessChain GskSpvAccessChain;
typedef struct _GskSpvWriter GskSpvWriter;
typedef void (* GskSpvWriterFunc) (GskSpvWriter *, gpointer);
diff --git a/gsk/gskslvariable.c b/gsk/gskslvariable.c
index aed2d21..ee81141 100644
--- a/gsk/gskslvariable.c
+++ b/gsk/gskslvariable.c
@@ -122,6 +122,12 @@ gsk_sl_variable_get_type (const GskSlVariable *variable)
return variable->type;
}
+const GskSlQualifier *
+gsk_sl_variable_get_qualifier (const GskSlVariable *variable)
+{
+ return &variable->qualifier;
+}
+
const char *
gsk_sl_variable_get_name (const GskSlVariable *variable)
{
diff --git a/gsk/gskslvariableprivate.h b/gsk/gskslvariableprivate.h
index 0c55aaa..f60b3c5 100644
--- a/gsk/gskslvariableprivate.h
+++ b/gsk/gskslvariableprivate.h
@@ -37,6 +37,7 @@ void gsk_sl_variable_print (const GskSlVari
GskSlPrinter *printer);
GskSlType * gsk_sl_variable_get_type (const GskSlVariable *variable);
+const GskSlQualifier * gsk_sl_variable_get_qualifier (const GskSlVariable *variable);
const char * gsk_sl_variable_get_name (const GskSlVariable *variable);
const GskSlValue * gsk_sl_variable_get_initial_value (const GskSlVariable *variable);
gboolean gsk_sl_variable_is_constant (const GskSlVariable *variable);
diff --git a/gsk/gskspvwriter.c b/gsk/gskspvwriter.c
index 37b7f86..ff70c27 100644
--- a/gsk/gskspvwriter.c
+++ b/gsk/gskspvwriter.c
@@ -21,6 +21,7 @@
#include "gskspvwriterprivate.h"
#include "gskslfunctionprivate.h"
+#include "gskslqualifierprivate.h"
#include "gsksltypeprivate.h"
#include "gskslvalueprivate.h"
#include "gskslvariableprivate.h"
@@ -656,3 +657,183 @@ gsk_spv_writer_convert (GskSpvWriter *writer,
g_return_val_if_reached (id);
}
}
+
+struct _GskSpvAccessChain
+{
+ GskSpvWriter *writer;
+ GskSlVariable *variable;
+ GskSlType *type;
+ GArray *chain;
+ guint32 swizzle[4];
+ guint swizzle_length;
+};
+
+GskSpvAccessChain *
+gsk_spv_access_chain_new (GskSpvWriter *writer,
+ GskSlVariable *variable)
+{
+ GskSpvAccessChain *chain;
+
+ chain = g_slice_new0 (GskSpvAccessChain);
+
+ chain->writer = gsk_spv_writer_ref (writer);
+ chain->variable = gsk_sl_variable_ref (variable);
+ chain->type = gsk_sl_type_ref (gsk_sl_variable_get_type (variable));
+
+ return chain;
+}
+
+void
+gsk_spv_access_chain_free (GskSpvAccessChain *chain)
+{
+ if (chain->chain)
+ g_array_free (chain->chain, TRUE);
+ gsk_sl_type_unref (chain->type);
+ gsk_sl_variable_unref (chain->variable);
+ gsk_spv_writer_unref (chain->writer);
+
+ g_slice_free (GskSpvAccessChain, chain);
+}
+
+void
+gsk_spv_access_chain_add_index (GskSpvAccessChain *chain,
+ GskSlType *type,
+ guint32 index_id)
+{
+ if (chain->chain == NULL)
+ chain->chain = g_array_new (FALSE, FALSE, sizeof (guint32));
+ gsk_sl_type_unref (chain->type);
+ chain->type = gsk_sl_type_ref (type);
+
+ g_array_append_val (chain->chain, index_id);
+}
+
+void
+gsk_spv_access_chain_swizzle (GskSpvAccessChain *chain,
+ const guint *indexes,
+ guint length)
+{
+ guint tmp[4];
+ guint i;
+
+ if (chain->swizzle_length != 0)
+ {
+ g_assert (length <= chain->swizzle_length);
+
+ for (i = 0; i < length; i++)
+ {
+ tmp[i] = chain->swizzle[indexes[i]];
+ }
+ indexes = tmp;
+ }
+
+ /* Mean trick to do optimization: We only assign a swizzle_length
+ * If something is actually swizzled. If we're doing an identity
+ * swizzle, ignore it.
+ */
+ if (length < gsk_sl_type_get_n_components (chain->type))
+ chain->swizzle_length = length;
+ else
+ chain->swizzle_length = 0;
+
+ for (i = 0; i < length; i++)
+ {
+ chain->swizzle[i] = indexes[i];
+ if (indexes[i] != i)
+ chain->swizzle_length = length;
+ }
+}
+
+static guint32
+gsk_spv_access_get_variable (GskSpvAccessChain *chain)
+{
+ guint32 variable_id;
+
+ variable_id = gsk_spv_writer_get_id_for_variable (chain->writer,
+ chain->variable);
+
+ if (chain->chain)
+ variable_id = gsk_spv_writer_access_chain (chain->writer,
+ chain->type,
+ gsk_sl_qualifier_get_storage_class
(gsk_sl_variable_get_qualifier (chain->variable)),
+ variable_id,
+ (guint32 *) chain->chain->data,
+ chain->chain->len);
+
+ return variable_id;
+}
+
+static GskSlType *
+gsk_spv_access_chain_get_swizzle_type (GskSpvAccessChain *chain)
+{
+ g_assert (chain->swizzle_length != 0);
+
+ if (chain->swizzle_length == 1)
+ return gsk_sl_type_get_scalar (gsk_sl_type_get_scalar_type (chain->type));
+ else
+ return gsk_sl_type_get_vector (gsk_sl_type_get_scalar_type (chain->type), chain->swizzle_length);
+}
+
+guint32
+gsk_spv_access_chain_load (GskSpvAccessChain *chain)
+{
+ guint result_id;
+
+ result_id = gsk_spv_writer_load (chain->writer,
+ chain->type,
+ gsk_spv_access_get_variable (chain),
+ 0);
+
+ if (chain->swizzle_length)
+ result_id = gsk_spv_writer_vector_shuffle (chain->writer,
+ gsk_spv_access_chain_get_swizzle_type (chain),
+ result_id,
+ result_id,
+ chain->swizzle,
+ chain->swizzle_length);
+
+ return result_id;
+}
+
+void
+gsk_spv_access_chain_store (GskSpvAccessChain *chain,
+ guint32 value)
+{
+ guint32 chain_id;
+
+ chain_id = gsk_spv_access_get_variable (chain);
+
+ if (chain->swizzle_length)
+ {
+ guint32 indexes[4] = { 0, };
+ guint32 merge;
+ guint i, n;
+
+ merge = gsk_spv_writer_load (chain->writer,
+ chain->type,
+ chain_id,
+ 0);
+
+ n = gsk_sl_type_get_n_components (chain->type);
+ for (i = 0; i < n; i++)
+ {
+ if (i < chain->swizzle_length)
+ indexes[chain->swizzle[i]] = n + i;
+ if (indexes[i] == 0)
+ indexes[i] = i;
+ }
+
+ value = gsk_spv_writer_vector_shuffle (chain->writer,
+ chain->type,
+ merge,
+ value,
+ indexes,
+ n);
+ }
+
+ gsk_spv_writer_store (chain->writer,
+ chain_id,
+ value,
+ 0);
+}
+
diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h
index dedf337..48b4eb9 100644
--- a/gsk/gskspvwriterprivate.h
+++ b/gsk/gskspvwriterprivate.h
@@ -91,6 +91,19 @@ void gsk_spv_writer_commit_code_block (GskSpvWriter
guint32 gsk_spv_code_block_get_label (GskSpvCodeBlock *block);
+GskSpvAccessChain * gsk_spv_access_chain_new (GskSpvWriter *writer,
+ GskSlVariable *variable);
+void gsk_spv_access_chain_free (GskSpvAccessChain *chain);
+void gsk_spv_access_chain_add_index (GskSpvAccessChain *chain,
+ GskSlType *type,
+ guint32 index_id);
+void gsk_spv_access_chain_swizzle (GskSpvAccessChain *chain,
+ const guint *indexes,
+ guint n_indexes);
+guint32 gsk_spv_access_chain_load (GskSpvAccessChain *chain);
+void gsk_spv_access_chain_store (GskSpvAccessChain *chain,
+ guint32 value);
+
#include "gskspvwritergeneratedprivate.h"
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]