[gtk+/wip/otte/shader: 1/12] gskslvariable: Allow storing an initializer value with a variable
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 1/12] gskslvariable: Allow storing an initializer value with a variable
- Date: Wed, 27 Sep 2017 17:14:11 +0000 (UTC)
commit e1bbfa83cf9197b2048f6227bf94f8b1fdd7a9b3
Author: Benjamin Otte <otte redhat com>
Date: Tue Sep 26 17:46:04 2017 +0200
gskslvariable: Allow storing an initializer value with a variable
This code requires the addition of gsk_sl_value_new_convert() so
constants can be converted to the right type.
gsk/gskslnode.c | 56 +++++++++++++++---------
gsk/gskslprogram.c | 6 ++-
gsk/gsksltype.c | 102 +++++++++++++++++++++++++++++++++++++++++---
gsk/gsksltypeprivate.h | 4 ++
gsk/gskslvalue.c | 90 ++++++++++++++++++++++++++++++++++++++
gsk/gskslvalueprivate.h | 2 +
gsk/gskslvariable.c | 18 +++++++-
gsk/gskslvariableprivate.h | 4 +-
8 files changed, 250 insertions(+), 32 deletions(-)
---
diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c
index fd10955..b4c56ce 100644
--- a/gsk/gskslnode.c
+++ b/gsk/gskslnode.c
@@ -27,6 +27,7 @@
#include "gskslscopeprivate.h"
#include "gsksltokenizerprivate.h"
#include "gsksltypeprivate.h"
+#include "gskslvalueprivate.h"
#include "gskslvariableprivate.h"
#include "gskspvwriterprivate.h"
@@ -253,38 +254,51 @@ gsk_sl_node_parse_declaration (GskSlScope *scope,
{
GskSlNodeDeclaration *declaration;
GskSlPointerType *pointer_type;
+ GskSlValue *value = NULL;
const GskSlToken *token;
+ char *name;
declaration = gsk_sl_node_new (GskSlNodeDeclaration, &GSK_SL_NODE_DECLARATION);
- pointer_type = gsk_sl_pointer_type_new (type, TRUE,
decoration->values[GSK_SL_DECORATION_CALLER_ACCESS].value);
- token = gsk_sl_preprocessor_get (stream);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
- {
- declaration->variable = gsk_sl_variable_new (pointer_type, NULL,
decoration->values[GSK_SL_DECORATION_CONST].set);
- gsk_sl_pointer_type_unref (pointer_type);
- return (GskSlNode *) declaration;
- }
-
- declaration->variable = gsk_sl_variable_new (pointer_type, token->str,
decoration->values[GSK_SL_DECORATION_CONST].set);
- gsk_sl_preprocessor_consume (stream, (GskSlNode *) declaration);
- gsk_sl_pointer_type_unref (pointer_type);
-
token = gsk_sl_preprocessor_get (stream);
- if (gsk_sl_token_is (token, GSK_SL_TOKEN_EQUAL))
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
+ name = g_strdup (token->str);
gsk_sl_preprocessor_consume (stream, (GskSlNode *) declaration);
- declaration->initial = gsk_sl_expression_parse_assignment (scope, stream);
- if (!gsk_sl_type_can_convert (type, gsk_sl_expression_get_return_type (declaration->initial)))
+
+ token = gsk_sl_preprocessor_get (stream);
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_EQUAL))
{
- gsk_sl_preprocessor_error (stream, "Cannot convert from initializer type %s to variable type %s",
- gsk_sl_type_get_name (gsk_sl_expression_get_return_type
(declaration->initial)),
- gsk_sl_type_get_name (type));
- gsk_sl_node_unref ((GskSlNode *) declaration);
- return NULL;
+ GskSlValue *unconverted;
+
+ gsk_sl_preprocessor_consume (stream, (GskSlNode *) declaration);
+ declaration->initial = gsk_sl_expression_parse_assignment (scope, stream);
+ if (!gsk_sl_type_can_convert (type, gsk_sl_expression_get_return_type (declaration->initial)))
+ {
+ gsk_sl_preprocessor_error (stream, "Cannot convert from initializer type %s to variable type
%s",
+ gsk_sl_type_get_name (gsk_sl_expression_get_return_type
(declaration->initial)),
+ gsk_sl_type_get_name (type));
+ gsk_sl_node_unref ((GskSlNode *) declaration);
+ return NULL;
+ }
+
+ unconverted = gsk_sl_expression_get_constant (declaration->initial);
+ if (unconverted)
+ {
+ value = gsk_sl_value_new_convert (unconverted, type);
+ gsk_sl_value_free (unconverted);
+ }
}
}
+ else
+ {
+ name = NULL;
+ value = NULL;
+ }
+ pointer_type = gsk_sl_pointer_type_new (type, TRUE,
decoration->values[GSK_SL_DECORATION_CALLER_ACCESS].value);
+ declaration->variable = gsk_sl_variable_new (pointer_type, name, value,
decoration->values[GSK_SL_DECORATION_CONST].set);
+ gsk_sl_pointer_type_unref (pointer_type);
gsk_sl_scope_add_variable (scope, declaration->variable);
return (GskSlNode *) declaration;
diff --git a/gsk/gskslprogram.c b/gsk/gskslprogram.c
index a0f405a..9845433 100644
--- a/gsk/gskslprogram.c
+++ b/gsk/gskslprogram.c
@@ -84,7 +84,7 @@ gsk_sl_program_parse_variable (GskSlProgram *program,
gsk_sl_preprocessor_consume (preproc, NULL);
pointer_type = gsk_sl_pointer_type_new (type, FALSE,
decoration->values[GSK_SL_DECORATION_CALLER_ACCESS].value);
- variable = gsk_sl_variable_new (pointer_type, name, decoration->values[GSK_SL_DECORATION_CONST].set);
+ variable = gsk_sl_variable_new (pointer_type, g_strdup (name), NULL,
decoration->values[GSK_SL_DECORATION_CONST].set);
gsk_sl_pointer_type_unref (pointer_type);
program->variables = g_slist_append (program->variables, variable);
@@ -121,7 +121,7 @@ gsk_sl_program_parse_declaration (GskSlProgram *program,
if (success)
{
GskSlPointerType *ptype = gsk_sl_pointer_type_new (type, FALSE,
decoration.values[GSK_SL_DECORATION_CALLER_ACCESS].value);
- GskSlVariable *variable = gsk_sl_variable_new (ptype, NULL,
decoration.values[GSK_SL_DECORATION_CONST].set);
+ GskSlVariable *variable = gsk_sl_variable_new (ptype, NULL, NULL,
decoration.values[GSK_SL_DECORATION_CONST].set);
gsk_sl_pointer_type_unref (ptype);
program->variables = g_slist_append (program->variables, variable);
gsk_sl_preprocessor_consume (preproc, program);
@@ -159,6 +159,8 @@ gsk_sl_program_parse_declaration (GskSlProgram *program,
success &= gsk_sl_program_parse_variable (program, scope, preproc, &decoration, type, name);
}
+ g_free (name);
+
return success;
}
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index 0de5f93..02c56e6 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -210,19 +210,100 @@ write_bool_spv (GskSpvWriter *writer, gpointer value)
return result_id;
}
+#define SIMPLE_CONVERSION(source_name, target_name, source_type, target_type) \
+static void \
+source_name ## _to_ ## target_name (gpointer target, gconstpointer source) \
+{ \
+ *(target_type *) target = *(const source_type *) source; \
+}
+
+SIMPLE_CONVERSION(float, float, float, float);
+SIMPLE_CONVERSION(float, double, float, double);
+SIMPLE_CONVERSION(float, int, float, gint32);
+SIMPLE_CONVERSION(float, uint, float, guint32);
+static void
+float_to_bool (gpointer target, gconstpointer source)
+{
+ *(guint32 *) target = *(const float *) source ? TRUE : FALSE;
+}
+
+SIMPLE_CONVERSION(double, float, double, float);
+SIMPLE_CONVERSION(double, double, double, double);
+SIMPLE_CONVERSION(double, int, double, gint32);
+SIMPLE_CONVERSION(double, uint, double, guint32);
+static void
+double_to_bool (gpointer target, gconstpointer source)
+{
+ *(guint32 *) target = *(const double *) source ? TRUE : FALSE;
+}
+
+SIMPLE_CONVERSION(int, float, gint32, float);
+SIMPLE_CONVERSION(int, double, gint32, double);
+SIMPLE_CONVERSION(int, int, gint32, gint32);
+SIMPLE_CONVERSION(int, uint, gint32, guint32);
+static void
+int_to_bool (gpointer target, gconstpointer source)
+{
+ *(guint32 *) target = *(const gint32 *) source ? TRUE : FALSE;
+}
+
+SIMPLE_CONVERSION(uint, float, guint32, float);
+SIMPLE_CONVERSION(uint, double, guint32, double);
+SIMPLE_CONVERSION(uint, int, guint32, gint32);
+SIMPLE_CONVERSION(uint, uint, guint32, guint32);
+static void
+uint_to_bool (gpointer target, gconstpointer source)
+{
+ *(guint32 *) target = *(const guint32 *) source ? TRUE : FALSE;
+}
+
+static void
+bool_to_float (gpointer target, gconstpointer source)
+{
+ *(float *) target = *(const guint32 *) source ? 1.0 : 0.0;
+}
+
+static void
+bool_to_double (gpointer target, gconstpointer source)
+{
+ *(double *) target = *(const guint32 *) source ? 1.0 : 0.0;
+}
+
+static void
+bool_to_int (gpointer target, gconstpointer source)
+{
+ *(gint32 *) target = *(const guint32 *) source ? 1 : 0;
+}
+
+static void
+bool_to_uint (gpointer target, gconstpointer source)
+{
+ *(guint32 *) target = *(const guint32 *) source ? 1 : 0;
+}
+
+static void
+bool_to_bool (gpointer target, gconstpointer source)
+{
+ *(guint32 *) target = *(const guint32 *) source;
+}
+
+#define CONVERSIONS(name) { NULL, name ## _to_float, name ## _to_double, name ## _to_int, name ## _to_uint,
name ## _to_bool }
struct {
char *name;
gsize size;
void (* print_value) (GString *string, gpointer value);
+ void (* convert_value[N_SCALAR_TYPES]) (gpointer target, gconstpointer source);
guint32 (* write_value_spv) (GskSpvWriter *writer, gpointer value);
} scalar_infos[] = {
- [GSK_SL_VOID] = { "void", 0, print_void, write_void_spv, },
- [GSK_SL_FLOAT] = { "float", 4, print_float, write_float_spv },
- [GSK_SL_DOUBLE] = { "double", 8, print_double, write_double_spv },
- [GSK_SL_INT] = { "int", 4, print_int, write_int_spv },
- [GSK_SL_UINT] = { "uint", 4, print_uint, write_uint_spv },
- [GSK_SL_BOOL] = { "bool", 4, print_bool, write_bool_spv }
+ [GSK_SL_VOID] = { "void", 0, print_void, { NULL, }, write_void_spv, },
+ [GSK_SL_FLOAT] = { "float", 4, print_float, CONVERSIONS (float), write_float_spv },
+ [GSK_SL_DOUBLE] = { "double", 8, print_double, CONVERSIONS (double), write_double_spv },
+ [GSK_SL_INT] = { "int", 4, print_int, CONVERSIONS (int), write_int_spv },
+ [GSK_SL_UINT] = { "uint", 4, print_uint, CONVERSIONS (uint), write_uint_spv },
+ [GSK_SL_BOOL] = { "bool", 4, print_bool, CONVERSIONS (bool), write_bool_spv }
};
+#undef SIMPLE_CONVERSION
+#undef CONVERSIONS
/* SCALAR */
@@ -1072,6 +1153,15 @@ gsk_sl_scalar_type_can_convert (GskSlScalarType target,
}
}
+void
+gsk_sl_scalar_type_convert_value (GskSlScalarType target_type,
+ gpointer target_value,
+ GskSlScalarType source_type,
+ gconstpointer source_value)
+{
+ scalar_infos[source_type].convert_value[target_type] (target_value, source_value);
+}
+
gboolean
gsk_sl_type_can_convert (const GskSlType *target,
const GskSlType *source)
diff --git a/gsk/gsksltypeprivate.h b/gsk/gsksltypeprivate.h
index 71ecc73..7b3a757 100644
--- a/gsk/gsksltypeprivate.h
+++ b/gsk/gsksltypeprivate.h
@@ -72,6 +72,10 @@ void gsk_sl_type_print_value (const GskSlType
guint32 gsk_sl_type_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gpointer value);
+void gsk_sl_scalar_type_convert_value (GskSlScalarType target_type,
+ gpointer target_value,
+ GskSlScalarType source_type,
+ gconstpointer source_value);
G_END_DECLS
diff --git a/gsk/gskslvalue.c b/gsk/gskslvalue.c
index b8c00bb..88f17a1 100644
--- a/gsk/gskslvalue.c
+++ b/gsk/gskslvalue.c
@@ -64,6 +64,96 @@ gsk_sl_value_new_for_data (GskSlType *type,
return value;
}
+/**
+ * gsk_sl_value_new_convert:
+ * @source: value to convert
+ * @new_type: type to convert to
+ *
+ * Converts @source into the @new_type. This function uses the extended
+ * conversion rules for constructors. If you want to restrict yourself
+ * to the usual conversion rules, call this function after checking
+ * for compatibility via gsk_sl_type_can_convert().
+ *
+ * Returns: a new value containing the converted @source or %NULL
+ * if the source cannot be converted to @type.
+ **/
+GskSlValue *
+gsk_sl_value_new_convert (GskSlValue *source,
+ GskSlType *new_type)
+{
+ GskSlValue *result;
+
+ if (gsk_sl_type_is_scalar (source->type))
+ {
+ if (!gsk_sl_type_is_scalar (new_type))
+ return NULL;
+
+ result = gsk_sl_value_new (new_type);
+ gsk_sl_scalar_type_convert_value (gsk_sl_type_get_scalar_type (new_type),
+ result->data,
+ gsk_sl_type_get_scalar_type (source->type),
+ source->data);
+ return result;
+ }
+ else if (gsk_sl_type_is_vector (source->type))
+ {
+ guchar *sdata, *ddata;
+ gsize sstride, dstride;
+ guint i, n;
+
+ if (!gsk_sl_type_is_vector (new_type) ||
+ gsk_sl_type_get_length (new_type) != gsk_sl_type_get_length (source->type))
+ return NULL;
+
+ n = gsk_sl_type_get_length (new_type);
+ result = gsk_sl_value_new (new_type);
+ sdata = source->data;
+ ddata = result->data;
+ sstride = gsk_sl_type_get_size (source->type) / n;
+ dstride = gsk_sl_type_get_size (new_type) / n;
+ for (i = 0; i < n; i++)
+ {
+ gsk_sl_scalar_type_convert_value (gsk_sl_type_get_scalar_type (new_type),
+ ddata + i * dstride,
+ gsk_sl_type_get_scalar_type (source->type),
+ sdata + i * sstride);
+ }
+
+ return result;
+ }
+ else if (gsk_sl_type_is_matrix (source->type))
+ {
+ guchar *sdata, *ddata;
+ gsize sstride, dstride;
+ guint i, n;
+
+ if (!gsk_sl_type_is_vector (new_type) ||
+ gsk_sl_type_get_length (new_type) != gsk_sl_type_get_length (source->type) ||
+ gsk_sl_type_get_length (gsk_sl_type_get_index_type (new_type)) != gsk_sl_type_get_length
(gsk_sl_type_get_index_type (source->type)))
+ return NULL;
+
+ n = gsk_sl_type_get_length (new_type) * gsk_sl_type_get_length (gsk_sl_type_get_index_type
(source->type));
+ result = gsk_sl_value_new (new_type);
+ sdata = source->data;
+ ddata = result->data;
+ sstride = gsk_sl_type_get_size (source->type) / n;
+ dstride = gsk_sl_type_get_size (new_type) / n;
+ for (i = 0; i < n; i++)
+ {
+ gsk_sl_scalar_type_convert_value (gsk_sl_type_get_scalar_type (new_type),
+ ddata + i * dstride,
+ gsk_sl_type_get_scalar_type (source->type),
+ sdata + i * sstride);
+ }
+
+ return result;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
GskSlValue *
gsk_sl_value_copy (GskSlValue *source)
{
diff --git a/gsk/gskslvalueprivate.h b/gsk/gskslvalueprivate.h
index 280b056..dec0b87 100644
--- a/gsk/gskslvalueprivate.h
+++ b/gsk/gskslvalueprivate.h
@@ -28,6 +28,8 @@ GskSlValue * gsk_sl_value_new_for_data (GskSlType
gpointer data,
GDestroyNotify free_func,
gpointer user_data);
+GskSlValue * gsk_sl_value_new_convert (GskSlValue *source,
+ GskSlType *new_type);
GskSlValue * gsk_sl_value_copy (GskSlValue *source);
void gsk_sl_value_free (GskSlValue *value);
diff --git a/gsk/gskslvariable.c b/gsk/gskslvariable.c
index b84ccc0..9cedbc3 100644
--- a/gsk/gskslvariable.c
+++ b/gsk/gskslvariable.c
@@ -21,6 +21,8 @@
#include "gskslvariableprivate.h"
#include "gskslpointertypeprivate.h"
+#include "gsksltypeprivate.h"
+#include "gskslvalueprivate.h"
#include "gskspvwriterprivate.h"
struct _GskSlVariable {
@@ -28,21 +30,25 @@ struct _GskSlVariable {
GskSlPointerType *type;
char *name;
+ GskSlValue *initial_value;
gboolean constant;
};
GskSlVariable *
gsk_sl_variable_new (GskSlPointerType *type,
- const char *name,
+ char *name,
+ GskSlValue *initial_value,
gboolean constant)
{
GskSlVariable *variable;
+ g_return_val_if_fail (initial_value == NULL || gsk_sl_type_equal (gsk_sl_pointer_type_get_type (type),
gsk_sl_value_get_type (initial_value)), NULL);
variable = g_slice_new0 (GskSlVariable);
variable->ref_count = 1;
variable->type = gsk_sl_pointer_type_ref (type);
- variable->name = g_strdup (name);
+ variable->name = name;
+ variable->initial_value = initial_value;
variable->constant = constant;
return variable;
@@ -68,6 +74,8 @@ gsk_sl_variable_unref (GskSlVariable *variable)
if (variable->ref_count > 0)
return;
+ if (variable->initial_value)
+ gsk_sl_value_free (variable->initial_value);
gsk_sl_pointer_type_unref (variable->type);
g_free (variable->name);
@@ -100,6 +108,12 @@ gsk_sl_variable_get_name (const GskSlVariable *variable)
return variable->name;
}
+const GskSlValue *
+gsk_sl_variable_get_initial_value (const GskSlVariable *variable)
+{
+ return variable->initial_value;
+}
+
gboolean
gsk_sl_variable_is_constant (const GskSlVariable *variable)
{
diff --git a/gsk/gskslvariableprivate.h b/gsk/gskslvariableprivate.h
index f909d22..92f8de0 100644
--- a/gsk/gskslvariableprivate.h
+++ b/gsk/gskslvariableprivate.h
@@ -26,7 +26,8 @@
G_BEGIN_DECLS
GskSlVariable * gsk_sl_variable_new (GskSlPointerType *type,
- const char *name,
+ char *name,
+ GskSlValue *initial_value,
gboolean constant);
GskSlVariable * gsk_sl_variable_ref (GskSlVariable *variable);
@@ -37,6 +38,7 @@ void gsk_sl_variable_print (const GskSlVari
GskSlPointerType * gsk_sl_variable_get_type (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);
guint32 gsk_sl_variable_write_spv (const GskSlVariable *variable,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]