diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c index eed3d28cbc..dfb6e5813a 100644 --- a/gsk/gskslnode.c +++ b/gsk/gskslnode.c @@ -26,6 +26,7 @@ #include "gskslscopeprivate.h" #include "gsksltokenizerprivate.h" #include "gsksltypeprivate.h" +#include "gskslvariableprivate.h" #include "gskspvwriterprivate.h" #include @@ -732,8 +733,7 @@ typedef struct _GskSlNodeDeclaration GskSlNodeDeclaration; struct _GskSlNodeDeclaration { GskSlNode parent; - char *name; - GskSlPointerType *type; + GskSlVariable *variable; GskSlNode *initial; guint constant :1; }; @@ -743,8 +743,7 @@ gsk_sl_node_declaration_free (GskSlNode *node) { GskSlNodeDeclaration *declaration = (GskSlNodeDeclaration *) node; - g_free (declaration->name); - gsk_sl_pointer_type_unref (declaration->type); + gsk_sl_variable_unref (declaration->variable); if (declaration->initial) gsk_sl_node_unref (declaration->initial); @@ -757,16 +756,11 @@ gsk_sl_node_declaration_print (GskSlNode *node, { GskSlNodeDeclaration *declaration = (GskSlNodeDeclaration *) node; - gsk_sl_pointer_type_print (declaration->type, string); - if (declaration->name) + gsk_sl_variable_print (declaration->variable, string); + if (declaration->initial) { - g_string_append (string, " "); - g_string_append (string, declaration->name); - if (declaration->initial) - { - g_string_append (string, " = "); - gsk_sl_node_print (declaration->initial, string); - } + g_string_append (string, " = "); + gsk_sl_node_print (declaration->initial, string); } } @@ -775,7 +769,7 @@ gsk_sl_node_declaration_get_return_type (GskSlNode *node) { GskSlNodeDeclaration *declaration = (GskSlNodeDeclaration *) node; - return gsk_sl_pointer_type_get_type (declaration->type); + return gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (declaration->variable)); } static gboolean @@ -791,28 +785,20 @@ gsk_sl_node_declaration_write_spv (const GskSlNode *node, GskSpvWriter *writer) { GskSlNodeDeclaration *declaration = (GskSlNodeDeclaration *) node; - guint32 pointer_type_id, declaration_id; + guint32 variable_id; - pointer_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, declaration->type); - declaration_id = gsk_spv_writer_next_id (writer); - gsk_spv_writer_add (writer, - GSK_SPV_WRITER_SECTION_CODE, - 4, GSK_SPV_OP_VARIABLE, - (guint32[3]) { pointer_type_id, - declaration_id, - gsk_sl_pointer_type_get_storage_class (declaration->type)}); - gsk_spv_writer_set_id_for_declaration (writer, (GskSlNode *) node, declaration_id); + variable_id = gsk_spv_writer_get_id_for_variable (writer, declaration->variable); if (declaration->initial) { gsk_spv_writer_add (writer, GSK_SPV_WRITER_SECTION_CODE, 3, GSK_SPV_OP_STORE, - (guint32[2]) { declaration_id, + (guint32[2]) { variable_id, gsk_sl_node_write_spv (declaration->initial, writer)}); } - return declaration_id; + return variable_id; } static const GskSlNodeClass GSK_SL_NODE_DECLARATION = { @@ -830,8 +816,7 @@ typedef struct _GskSlNodeReference GskSlNodeReference; struct _GskSlNodeReference { GskSlNode parent; - char *name; - GskSlNode *declaration; + GskSlVariable *variable; }; static void @@ -839,8 +824,7 @@ gsk_sl_node_reference_free (GskSlNode *node) { GskSlNodeReference *reference = (GskSlNodeReference *) node; - g_free (reference->name); - gsk_sl_node_unref (reference->declaration); + gsk_sl_variable_unref (reference->variable); g_slice_free (GskSlNodeReference, reference); } @@ -851,7 +835,7 @@ gsk_sl_node_reference_print (GskSlNode *node, { GskSlNodeReference *reference = (GskSlNodeReference *) node; - g_string_append (string, reference->name); + g_string_append (string, gsk_sl_variable_get_name (reference->variable)); } static GskSlType * @@ -859,15 +843,13 @@ gsk_sl_node_reference_get_return_type (GskSlNode *node) { GskSlNodeReference *reference = (GskSlNodeReference *) node; - return gsk_sl_node_get_return_type (reference->declaration); + return gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (reference->variable)); } static gboolean gsk_sl_node_reference_is_constant (GskSlNode *node) { - GskSlNodeReference *reference = (GskSlNodeReference *) node; - - return gsk_sl_node_is_constant (reference->declaration); + return FALSE; } static guint32 @@ -877,8 +859,8 @@ gsk_sl_node_reference_write_spv (const GskSlNode *node, GskSlNodeReference *reference = (GskSlNodeReference *) node; guint32 declaration_id, result_id, type_id; - type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_node_get_return_type (reference->declaration)); - declaration_id = gsk_spv_writer_get_id_for_declaration (writer, reference->declaration); + type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_pointer_type_get_type (gsk_sl_variable_get_type (reference->variable))); + declaration_id = gsk_spv_writer_get_id_for_variable (writer, reference->variable); result_id = gsk_spv_writer_next_id (writer); gsk_spv_writer_add (writer, GSK_SPV_WRITER_SECTION_CODE, @@ -1357,10 +1339,10 @@ gsk_sl_node_parse_primary_expression (GskSlScope *scope, case GSK_SL_TOKEN_IDENTIFIER: { GskSlNodeReference *reference; - GskSlNode *decl; + GskSlVariable *variable; - decl = gsk_sl_scope_lookup_variable (scope, token->str); - if (decl == NULL) + variable = gsk_sl_scope_lookup_variable (scope, token->str); + if (variable == NULL) { gsk_sl_preprocessor_error (stream, "No variable named \"%s\".", token->str); gsk_sl_preprocessor_consume (stream, NULL); @@ -1368,8 +1350,7 @@ gsk_sl_node_parse_primary_expression (GskSlScope *scope, } reference = gsk_sl_node_new (GskSlNodeReference, &GSK_SL_NODE_REFERENCE); - reference->name = g_strdup (token->str); - reference->declaration = gsk_sl_node_ref (decl); + reference->variable = gsk_sl_variable_ref (variable); gsk_sl_preprocessor_consume (stream, (GskSlNode *) reference); return (GskSlNode *) reference; } @@ -2114,13 +2095,15 @@ gsk_sl_node_parse_declaration (GskSlScope *scope, const GskSlToken *token; declaration = gsk_sl_node_new (GskSlNodeDeclaration, &GSK_SL_NODE_DECLARATION); - declaration->type = gsk_sl_pointer_type_ref (type); token = gsk_sl_preprocessor_get (stream); if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER)) - return (GskSlNode *) declaration; + { + declaration->variable = gsk_sl_variable_new (type, NULL); + return (GskSlNode *) declaration; + } - declaration->name = g_strdup (token->str); + declaration->variable = gsk_sl_variable_new (type, token->str); gsk_sl_preprocessor_consume (stream, (GskSlNode *) declaration); token = gsk_sl_preprocessor_get (stream); @@ -2130,7 +2113,7 @@ gsk_sl_node_parse_declaration (GskSlScope *scope, declaration->initial = gsk_sl_node_parse_assignment_expression (scope, stream); } - gsk_sl_scope_add_variable (scope, declaration->name, (GskSlNode *) declaration); + gsk_sl_scope_add_variable (scope, declaration->variable); return (GskSlNode *) declaration; } diff --git a/gsk/gskslscope.c b/gsk/gskslscope.c index 5f8af556e8..27a3c3195e 100644 --- a/gsk/gskslscope.c +++ b/gsk/gskslscope.c @@ -20,7 +20,7 @@ #include "gskslscopeprivate.h" -#include "gskslnodeprivate.h" +#include "gskslvariableprivate.h" #include @@ -47,7 +47,7 @@ gsk_sl_scope_new (GskSlScope *parent) scope->parent = parent; parent->children = g_slist_prepend (parent->children, scope); } - scope->variables = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gsk_sl_node_unref); + scope->variables = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gsk_sl_variable_unref); return scope; } @@ -86,18 +86,17 @@ gsk_sl_scope_unref (GskSlScope *scope) } void -gsk_sl_scope_add_variable (GskSlScope *scope, - const char *name, - GskSlNode *declaration) +gsk_sl_scope_add_variable (GskSlScope *scope, + GskSlVariable *variable) { - g_hash_table_replace (scope->variables, (gpointer) name, gsk_sl_node_ref (declaration)); + g_hash_table_replace (scope->variables, (gpointer) gsk_sl_variable_get_name (variable), gsk_sl_variable_ref (variable)); } -GskSlNode * +GskSlVariable * gsk_sl_scope_lookup_variable (GskSlScope *scope, const char *name) { - GskSlNode *result; + GskSlVariable *result; for (; scope != NULL; diff --git a/gsk/gskslscopeprivate.h b/gsk/gskslscopeprivate.h index 1c69848534..11060753f5 100644 --- a/gsk/gskslscopeprivate.h +++ b/gsk/gskslscopeprivate.h @@ -31,9 +31,8 @@ GskSlScope * gsk_sl_scope_ref (GskSlScope void gsk_sl_scope_unref (GskSlScope *scope); void gsk_sl_scope_add_variable (GskSlScope *scope, - const char *name, - GskSlNode *declaration); -GskSlNode * gsk_sl_scope_lookup_variable (GskSlScope *scope, + GskSlVariable *variable); +GskSlVariable * gsk_sl_scope_lookup_variable (GskSlScope *scope, const char *name); G_END_DECLS diff --git a/gsk/gsksltypesprivate.h b/gsk/gsksltypesprivate.h index f9d82eac1f..f02703beeb 100644 --- a/gsk/gsksltypesprivate.h +++ b/gsk/gsksltypesprivate.h @@ -28,6 +28,7 @@ typedef struct _GskSlPointerType GskSlPointerType; typedef struct _GskSlScope GskSlScope; typedef struct _GskSlToken GskSlToken; typedef struct _GskSlType GskSlType; +typedef struct _GskSlVariable GskSlVariable; typedef struct _GskSpvWriter GskSpvWriter; diff --git a/gsk/gskslvariable.c b/gsk/gskslvariable.c new file mode 100644 index 0000000000..faa3521594 --- /dev/null +++ b/gsk/gskslvariable.c @@ -0,0 +1,114 @@ +/* GTK - The GIMP Toolkit + * + * Copyright © 2017 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gskslvariableprivate.h" + +#include "gskslpointertypeprivate.h" +#include "gskspvwriterprivate.h" + +struct _GskSlVariable { + guint ref_count; + + GskSlPointerType *type; + char *name; +}; + +GskSlVariable * +gsk_sl_variable_new (GskSlPointerType *type, + const char *name) +{ + GskSlVariable *variable; + + variable = g_slice_new0 (GskSlVariable); + + variable->ref_count = 1; + variable->type = gsk_sl_pointer_type_ref (type); + variable->name = g_strdup (name); + + return variable; +} + +GskSlVariable * +gsk_sl_variable_ref (GskSlVariable *variable) +{ + g_return_val_if_fail (variable != NULL, NULL); + + variable->ref_count += 1; + + return variable; +} + +void +gsk_sl_variable_unref (GskSlVariable *variable) +{ + if (variable == NULL) + return; + + variable->ref_count -= 1; + if (variable->ref_count > 0) + return; + + gsk_sl_pointer_type_unref (variable->type); + g_free (variable->name); + + g_slice_free (GskSlVariable, variable); +} + +void +gsk_sl_variable_print (const GskSlVariable *variable, + GString *string) +{ + gsk_sl_pointer_type_print (variable->type, string); + if (variable->name) + { + g_string_append (string, " "); + g_string_append (string, variable->name); + } +} + +GskSlPointerType * +gsk_sl_variable_get_type (const GskSlVariable *variable) +{ + return variable->type; +} + +const char * +gsk_sl_variable_get_name (const GskSlVariable *variable) +{ + return variable->name; +} + +guint32 +gsk_sl_variable_write_spv (const GskSlVariable *variable, + GskSpvWriter *writer) +{ + guint32 pointer_type_id, variable_id; + + pointer_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, variable->type); + variable_id = gsk_spv_writer_next_id (writer); + gsk_spv_writer_add (writer, + GSK_SPV_WRITER_SECTION_CODE, + 4, GSK_SPV_OP_VARIABLE, + (guint32[3]) { pointer_type_id, + variable_id, + gsk_sl_pointer_type_get_storage_class (variable->type)}); + + return variable_id; +} diff --git a/gsk/gskslvariableprivate.h b/gsk/gskslvariableprivate.h new file mode 100644 index 0000000000..bfb7be9db1 --- /dev/null +++ b/gsk/gskslvariableprivate.h @@ -0,0 +1,45 @@ +/* GTK - The GIMP Toolkit + * + * Copyright © 2017 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GSK_SL_VARIABLE_PRIVATE_H__ +#define __GSK_SL_VARIABLE_PRIVATE_H__ + +#include + +#include "gsk/gsksltypesprivate.h" + +G_BEGIN_DECLS + +GskSlVariable * gsk_sl_variable_new (GskSlPointerType *type, + const char *name); + +GskSlVariable * gsk_sl_variable_ref (GskSlVariable *variable); +void gsk_sl_variable_unref (GskSlVariable *variable); + +void gsk_sl_variable_print (const GskSlVariable *variable, + GString *string); + +GskSlPointerType * gsk_sl_variable_get_type (const GskSlVariable *variable); +const char * gsk_sl_variable_get_name (const GskSlVariable *variable); + +guint32 gsk_sl_variable_write_spv (const GskSlVariable *variable, + GskSpvWriter *writer); + +G_END_DECLS + +#endif /* __GSK_SL_VARIABLE_PRIVATE_H__ */ diff --git a/gsk/gskspvwriter.c b/gsk/gskspvwriter.c index dda6402183..a514b156a6 100644 --- a/gsk/gskspvwriter.c +++ b/gsk/gskspvwriter.c @@ -23,6 +23,7 @@ #include "gskslnodeprivate.h" #include "gskslpointertypeprivate.h" #include "gsksltypeprivate.h" +#include "gskslvariableprivate.h" struct _GskSpvWriter { @@ -34,7 +35,7 @@ struct _GskSpvWriter guint32 entry_point; GHashTable *types; GHashTable *pointer_types; - GHashTable *declarations; + GHashTable *variables; }; GskSpvWriter * @@ -55,8 +56,8 @@ gsk_spv_writer_new (void) (GDestroyNotify) gsk_sl_type_unref, NULL); writer->pointer_types = g_hash_table_new_full (gsk_sl_pointer_type_hash, gsk_sl_pointer_type_equal, (GDestroyNotify) gsk_sl_pointer_type_unref, NULL); - writer->declarations = g_hash_table_new_full (g_direct_hash, g_direct_equal, - (GDestroyNotify) gsk_sl_node_unref, NULL); + writer->variables = g_hash_table_new_full (g_direct_hash, g_direct_equal, + (GDestroyNotify) gsk_sl_variable_unref, NULL); /* the ID 1 is reserved for the GLSL instruction set (for now) */ writer->last_id = 1; @@ -92,7 +93,7 @@ gsk_spv_writer_unref (GskSpvWriter *writer) g_hash_table_destroy (writer->pointer_types); g_hash_table_destroy (writer->types); - g_hash_table_destroy (writer->declarations); + g_hash_table_destroy (writer->variables); g_slice_free (GskSpvWriter, writer); } @@ -196,18 +197,18 @@ gsk_spv_writer_get_id_for_pointer_type (GskSpvWriter *writer, } guint32 -gsk_spv_writer_get_id_for_declaration (GskSpvWriter *writer, - GskSlNode *node) +gsk_spv_writer_get_id_for_variable (GskSpvWriter *writer, + GskSlVariable *variable) { - return GPOINTER_TO_UINT (g_hash_table_lookup (writer->declarations, node)); -} + guint32 result; -void -gsk_spv_writer_set_id_for_declaration (GskSpvWriter *writer, - GskSlNode *node, - guint32 id) -{ - g_hash_table_insert (writer->declarations, gsk_sl_node_ref (node), GUINT_TO_POINTER (id)); + result = GPOINTER_TO_UINT (g_hash_table_lookup (writer->variables, variable)); + if (result != 0) + return result; + + result = gsk_sl_variable_write_spv (variable, writer); + g_hash_table_insert (writer->variables, gsk_sl_variable_ref (variable), GUINT_TO_POINTER (result)); + return result; } guint32 diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h index 39d561aef2..8c699f3c4a 100644 --- a/gsk/gskspvwriterprivate.h +++ b/gsk/gskspvwriterprivate.h @@ -182,11 +182,8 @@ guint32 gsk_spv_writer_get_id_for_type (GskSpvWriter GskSlType *type); guint32 gsk_spv_writer_get_id_for_pointer_type (GskSpvWriter *writer, GskSlPointerType *type); -guint32 gsk_spv_writer_get_id_for_declaration (GskSpvWriter *writer, - GskSlNode *node); -void gsk_spv_writer_set_id_for_declaration (GskSpvWriter *writer, - GskSlNode *node, - guint32 id); +guint32 gsk_spv_writer_get_id_for_variable (GskSpvWriter *writer, + GskSlVariable *variable); guint32 gsk_spv_writer_next_id (GskSpvWriter *writer); void gsk_spv_writer_add (GskSpvWriter *writer, diff --git a/gsk/meson.build b/gsk/meson.build index 292b67f4a9..cda34e5867 100644 --- a/gsk/meson.build +++ b/gsk/meson.build @@ -42,6 +42,7 @@ gsk_private_sources = files([ 'gskslscope.c', 'gsksltokenizer.c', 'gsksltype.c', + 'gskslvariable.c', 'gskspvwriter.c' ])