[gtk+/wip/otte/shader: 218/226] gsksl: Redo block parsing
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 218/226] gsksl: Redo block parsing
- Date: Mon, 30 Oct 2017 02:18:51 +0000 (UTC)
commit a7dac28a3a669eea5394e511c27a8d661944173f
Author: Benjamin Otte <otte redhat com>
Date: Wed Oct 25 02:15:43 2017 +0200
gsksl: Redo block parsing
Do not parse blocks while parsing types, instead move it to the
declaration parsing. Also, add a special variable type for the case of
unnamed blocks, so that we can access them directly.
gsk/gsksldeclaration.c | 144 +++++++++++++++++++-
gsk/gsksltype.c | 92 +------------
gsk/gskslvariable.c | 80 +++++++++++-
gsk/gskslvariableprivate.h | 2 +
.../gsksl/errors/duplicate-block-member-name.glsl | 8 +
5 files changed, 233 insertions(+), 93 deletions(-)
---
diff --git a/gsk/gsksldeclaration.c b/gsk/gsksldeclaration.c
index a8f785a..5431093 100644
--- a/gsk/gsksldeclaration.c
+++ b/gsk/gsksldeclaration.c
@@ -219,6 +219,136 @@ static const GskSlDeclarationClass GSK_SL_DECLARATION_FUNCTION = {
/* API */
+static GskSlType *
+gsk_sl_declaration_parse_block_type (GskSlScope *scope,
+ GskSlPreprocessor *preproc)
+{
+ GskSlType *type;
+ const GskSlToken *token;
+ GskSlTypeBuilder *builder;
+
+ token = gsk_sl_preprocessor_get (preproc);
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ builder = gsk_sl_type_builder_new_block (token->str);
+ gsk_sl_preprocessor_consume (preproc, NULL);
+ }
+ else
+ {
+ gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected block name.");
+ return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
+ }
+
+ token = gsk_sl_preprocessor_get (preproc);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACE))
+ {
+ gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected opening \"{\" after block declaration.");
+ goto out;
+ }
+ gsk_sl_preprocessor_consume (preproc, NULL);
+
+ for (token = gsk_sl_preprocessor_get (preproc);
+ !gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE) && !gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
+ token = gsk_sl_preprocessor_get (preproc))
+ {
+ type = gsk_sl_type_new_parse (scope, preproc);
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (preproc);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected identifier for type name.");
+ break;
+ }
+ if (gsk_sl_type_builder_has_member (builder, token->str))
+ gsk_sl_preprocessor_error (preproc, DECLARATION, "Duplicate block member name \"%s\".",
token->str);
+ else
+ gsk_sl_type_builder_add_member (builder, type, token->str);
+ gsk_sl_preprocessor_consume (preproc, NULL);
+
+ token = gsk_sl_preprocessor_get (preproc);
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
+ break;
+
+ gsk_sl_preprocessor_consume (preproc, NULL);
+ }
+ gsk_sl_type_unref (type);
+
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
+ gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected semicolon after block member declaration.");
+ else
+ gsk_sl_preprocessor_consume (preproc, NULL);
+ }
+
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE))
+ {
+ gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected closing \"}\" after block declaration.");
+ gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_BRACE);
+ }
+ gsk_sl_preprocessor_consume (preproc, NULL);
+
+out:
+ return gsk_sl_type_builder_free (builder);
+}
+
+static GskSlDeclaration *
+gsk_sl_declaration_parse_block (GskSlScope *scope,
+ GskSlPreprocessor *preproc,
+ const GskSlQualifier *qualifier)
+{
+ GskSlDeclarationVariable *variable;
+ const GskSlToken *token;
+ GskSlType *type;
+
+ type = gsk_sl_declaration_parse_block_type (scope, preproc);
+
+ token = gsk_sl_preprocessor_get (preproc);
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ char *name;
+
+ name = g_strdup (token->str);
+ gsk_sl_preprocessor_consume (preproc, NULL);
+
+ type = gsk_sl_type_parse_array (type, scope, preproc);
+ gsk_sl_qualifier_check_type (qualifier, preproc, type);
+
+ variable = gsk_sl_declaration_new (&GSK_SL_DECLARATION_VARIABLE);
+ variable->variable = gsk_sl_variable_new (name, type, qualifier, NULL);
+ gsk_sl_scope_add_variable (scope, variable->variable);
+
+ token = gsk_sl_preprocessor_get (preproc);
+ }
+ else
+ {
+ gsize i;
+
+ gsk_sl_qualifier_check_type (qualifier, preproc, type);
+
+ variable = gsk_sl_declaration_new (&GSK_SL_DECLARATION_VARIABLE);
+ variable->variable = gsk_sl_variable_new (NULL, type, qualifier, NULL);
+
+ for (i = 0; i < gsk_sl_type_get_n_members (type); i++)
+ {
+ GskSlVariable *sub;
+
+ sub = gsk_sl_variable_new_block_member (variable->variable, i);
+ gsk_sl_scope_add_variable (scope, sub);
+ gsk_sl_variable_unref (sub);
+ }
+ }
+
+ if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
+ {
+ gsk_sl_preprocessor_error (preproc, SYNTAX, "No semicolon at end of variable declaration.");
+ gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_SEMICOLON);
+ }
+ gsk_sl_preprocessor_consume (preproc, NULL);
+
+ return &variable->parent;
+}
+
static GskSlDeclaration *
gsk_sl_declaration_parse_variable (GskSlScope *scope,
GskSlPreprocessor *preproc,
@@ -302,7 +432,19 @@ gsk_sl_declaration_parse (GskSlScope *scope,
gsk_sl_qualifier_parse (&qualifier, scope, preproc, GSK_SL_QUALIFIER_GLOBAL);
- type = gsk_sl_type_new_parse (scope, preproc);
+ token = gsk_sl_preprocessor_get (preproc);
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ type = gsk_sl_scope_lookup_type (scope, token->str);
+ if (type == NULL)
+ return gsk_sl_declaration_parse_block (scope, preproc, &qualifier);
+ gsk_sl_type_ref (type);
+ gsk_sl_preprocessor_consume (preproc, NULL);
+ }
+ else
+ {
+ type = gsk_sl_type_new_parse (scope, preproc);
+ }
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c
index 4668d70..45d9a97 100644
--- a/gsk/gsksltype.c
+++ b/gsk/gsksltype.c
@@ -1880,6 +1880,7 @@ gsk_sl_type_block_write_spv (GskSlType *type,
ids,
block->n_members);
+ gsk_spv_writer_name (writer, result_id, block->name);
gsk_spv_writer_decorate (writer, result_id, GSK_SPV_DECORATION_BLOCK, NULL, 0);
for (i = 0; i < block->n_members; i++)
@@ -2090,85 +2091,6 @@ out:
return type;
}
-static GskSlType *
-gsk_sl_type_parse_block (GskSlScope *scope,
- GskSlPreprocessor *preproc)
-{
- GskSlType *type;
- const GskSlToken *token;
- GskSlTypeBuilder *builder;
-
- if (!gsk_sl_scope_is_global (scope))
- {
- gsk_sl_preprocessor_error (preproc, SYNTAX, "Blocks are only allowed in global scope.");
- return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
- }
-
- token = gsk_sl_preprocessor_get (preproc);
- if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
- {
- builder = gsk_sl_type_builder_new_block (token->str);
- gsk_sl_preprocessor_consume (preproc, NULL);
- }
- else
- {
- gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected block name.");
- return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
- }
-
- token = gsk_sl_preprocessor_get (preproc);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACE))
- {
- gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected opening \"{\" after block declaration.");
- goto out;
- }
- gsk_sl_preprocessor_consume (preproc, NULL);
-
- for (token = gsk_sl_preprocessor_get (preproc);
- !gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE) && !gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
- token = gsk_sl_preprocessor_get (preproc))
- {
- type = gsk_sl_type_new_parse (scope, preproc);
-
- while (TRUE)
- {
- token = gsk_sl_preprocessor_get (preproc);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
- {
- gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected identifier for type name.");
- break;
- }
- if (gsk_sl_type_builder_has_member (builder, token->str))
- gsk_sl_preprocessor_error (preproc, DECLARATION, "struct already has a member named \"%s\".",
token->str);
- else
- gsk_sl_type_builder_add_member (builder, type, token->str);
- gsk_sl_preprocessor_consume (preproc, NULL);
-
- token = gsk_sl_preprocessor_get (preproc);
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
- break;
-
- gsk_sl_preprocessor_consume (preproc, NULL);
- }
- gsk_sl_type_unref (type);
-
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
- gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected semicolon after block member declaration.");
- else
- gsk_sl_preprocessor_consume (preproc, NULL);
- }
-
- if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE))
- {
- gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected closing \"}\" after block declaration.");
- gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_BRACE);
- }
- gsk_sl_preprocessor_consume (preproc, NULL);
-
-out:
- return gsk_sl_type_builder_free (builder);
-}
-
GskSlType *
gsk_sl_type_get_matching (GskSlType *type,
GskSlScalarType scalar)
@@ -2510,18 +2432,6 @@ gsk_sl_type_new_parse (GskSlScope *scope,
break;
case GSK_SL_TOKEN_STRUCT:
return gsk_sl_type_parse_struct (scope, preproc);
- case GSK_SL_TOKEN_IDENTIFIER:
- {
- type = gsk_sl_scope_lookup_type (scope, token->str);
-
- if (type)
- {
- type = gsk_sl_type_ref (type);
- break;
- }
-
- return gsk_sl_type_parse_block (scope, preproc);
- }
default:
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected type specifier");
return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
diff --git a/gsk/gskslvariable.c b/gsk/gskslvariable.c
index 3a91757..56a3ca7 100644
--- a/gsk/gskslvariable.c
+++ b/gsk/gskslvariable.c
@@ -171,7 +171,8 @@ gsk_sl_variable_standard_write_spv (const GskSlVariable *variable,
storage_class,
value_id);
- gsk_spv_writer_name (writer, result_id, variable->name);
+ if (variable->name)
+ gsk_spv_writer_name (writer, result_id, variable->name);
gsk_sl_qualifier_write_spv_decorations (&variable->qualifier, writer, result_id);
@@ -344,6 +345,63 @@ static const GskSlVariableClass GSK_SL_VARIABLE_CONST_PARAMETER = {
gsk_sl_variable_const_parameter_load_spv
};
+/* MEMBER */
+
+typedef struct _GskSlVariableMember GskSlVariableMember;
+
+struct _GskSlVariableMember {
+ GskSlVariable parent;
+
+ GskSlVariable *block;
+ gsize member_id;
+};
+
+static void
+gsk_sl_variable_member_free (GskSlVariable *variable)
+{
+ const GskSlVariableMember *member = (const GskSlVariableMember *) variable;
+
+ gsk_sl_variable_unref (member->block);
+
+ gsk_sl_variable_free (variable);
+}
+
+static GskSpvAccessChain *
+gsk_sl_variable_member_get_access_chain (GskSlVariable *variable,
+ GskSpvWriter *writer)
+{
+ const GskSlVariableMember *member = (const GskSlVariableMember *) variable;
+ GskSpvAccessChain *chain;
+ GskSlValue *value;
+
+ chain = gsk_sl_variable_get_access_chain (member->block, writer);
+ value = gsk_sl_value_new_for_data (gsk_sl_type_get_scalar (GSK_SL_INT), &(gint32) { member->member_id },
NULL, NULL);
+ gsk_spv_access_chain_add_index (chain,
+ variable->type,
+ gsk_spv_writer_get_id_for_value (writer, value));
+ gsk_sl_value_free (value);
+
+ return chain;
+}
+
+static guint32
+gsk_sl_variable_member_write_spv (const GskSlVariable *variable,
+ GskSpvWriter *writer)
+{
+ const GskSlVariableMember *member = (const GskSlVariableMember *) variable;
+
+ return gsk_spv_writer_get_id_for_variable (writer, member->block);
+}
+
+static const GskSlVariableClass GSK_SL_VARIABLE_MEMBER = {
+ sizeof (GskSlVariableMember),
+ gsk_sl_variable_member_free,
+ gsk_sl_variable_default_get_initial_value,
+ gsk_sl_variable_member_get_access_chain,
+ gsk_sl_variable_member_write_spv,
+ gsk_sl_variable_default_load_spv
+};
+
/* API */
GskSlVariable *
@@ -394,6 +452,26 @@ gsk_sl_variable_new (const char *name,
}
GskSlVariable *
+gsk_sl_variable_new_block_member (GskSlVariable *block,
+ guint member_id)
+{
+ GskSlVariableMember *member;
+
+ g_return_val_if_fail (block != NULL, NULL);
+ g_return_val_if_fail (gsk_sl_type_is_block (block->type), NULL);
+ g_return_val_if_fail (member_id < gsk_sl_type_get_n_members (block->type), NULL);
+
+ member = gsk_sl_variable_alloc (&GSK_SL_VARIABLE_MEMBER,
+ gsk_sl_type_get_member_name (block->type, member_id),
+ &block->qualifier,
+ gsk_sl_type_get_member_type (block->type, member_id));
+ member->block = gsk_sl_variable_ref (block);
+ member->member_id = member_id;
+
+ return &member->parent;
+}
+
+GskSlVariable *
gsk_sl_variable_new_builtin (const char *name,
GskSlType *type,
const GskSlQualifier *qualifier,
diff --git a/gsk/gskslvariableprivate.h b/gsk/gskslvariableprivate.h
index da3592c..50ccece 100644
--- a/gsk/gskslvariableprivate.h
+++ b/gsk/gskslvariableprivate.h
@@ -30,6 +30,8 @@ GskSlVariable * gsk_sl_variable_new (const char
GskSlType *type,
const GskSlQualifier *qualifier,
GskSlValue *initial_value);
+GskSlVariable * gsk_sl_variable_new_block_member (GskSlVariable *block,
+ guint member_id);
GskSlVariable * gsk_sl_variable_new_builtin (const char *name,
GskSlType *type,
const GskSlQualifier *qualifier,
diff --git a/testsuite/gsksl/errors/duplicate-block-member-name.glsl
b/testsuite/gsksl/errors/duplicate-block-member-name.glsl
new file mode 100644
index 0000000..191c64a
--- /dev/null
+++ b/testsuite/gsksl/errors/duplicate-block-member-name.glsl
@@ -0,0 +1,8 @@
+uniform Foo {
+ int x;
+ int x;
+};
+
+void main()
+{
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]