From deb3d26ff69b4535a4174d148c2964f2bd857c34 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Sun, 1 Oct 2017 23:49:10 +0200 Subject: [PATCH] gsksl: Add support for parsing blocks --- gsk/gskslpointertype.c | 9 - gsk/gskslpointertypeprivate.h | 3 - gsk/gsksltype.c | 330 +++++++++++++++++++++++++++++++++- gsk/gsksltypeprivate.h | 2 + gsk/gskslvariable.c | 26 ++- gsk/gskspvwriterprivate.h | 31 +++- 6 files changed, 384 insertions(+), 17 deletions(-) diff --git a/gsk/gskslpointertype.c b/gsk/gskslpointertype.c index e96c88a85e..380d4a88ae 100644 --- a/gsk/gskslpointertype.c +++ b/gsk/gskslpointertype.c @@ -76,15 +76,6 @@ gsk_sl_pointer_type_unref (GskSlPointerType *type) g_slice_free (GskSlPointerType, type); } -void -gsk_sl_pointer_type_print (const GskSlPointerType *type, - GskSlPrinter *printer) -{ - if (gsk_sl_qualifier_print (&type->qualifier, printer)) - gsk_sl_printer_append (printer, " "); - gsk_sl_printer_append (printer, gsk_sl_type_get_name (type->type)); -} - GskSlType * gsk_sl_pointer_type_get_type (const GskSlPointerType *type) { diff --git a/gsk/gskslpointertypeprivate.h b/gsk/gskslpointertypeprivate.h index 444089fbf9..97042a9275 100644 --- a/gsk/gskslpointertypeprivate.h +++ b/gsk/gskslpointertypeprivate.h @@ -32,9 +32,6 @@ GskSlPointerType * gsk_sl_pointer_type_new (GskSlTy GskSlPointerType * gsk_sl_pointer_type_ref (GskSlPointerType *type); void gsk_sl_pointer_type_unref (GskSlPointerType *type); -void gsk_sl_pointer_type_print (const GskSlPointerType *type, - GskSlPrinter *printer); - GskSlType * gsk_sl_pointer_type_get_type (const GskSlPointerType *type); const GskSlQualifier * gsk_sl_pointer_type_get_qualifier (const GskSlPointerType *type); diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c index 787f0903ff..d7271e64bb 100644 --- a/gsk/gsksltype.c +++ b/gsk/gsksltype.c @@ -1210,6 +1210,201 @@ static const GskSlTypeClass GSK_SL_TYPE_STRUCT = { gsk_sl_type_struct_write_value_spv }; +/* BLOCK */ + +typedef struct _GskSlTypeBlock GskSlTypeBlock; + +struct _GskSlTypeBlock { + GskSlType parent; + + char *name; + gsize size; + + GskSlTypeMember *members; + guint n_members; +}; + +static void +gsk_sl_type_block_free (GskSlType *type) +{ + GskSlTypeBlock *block = (GskSlTypeBlock *) type; + guint i; + + for (i = 0; i < block->n_members; i++) + { + gsk_sl_type_unref (block->members[i].type); + g_free (block->members[i].name); + } + + g_free (block->members); + g_free (block->name); + + g_slice_free (GskSlTypeBlock, block); +} + +static const char * +gsk_sl_type_block_get_name (const GskSlType *type) +{ + GskSlTypeBlock *block = (GskSlTypeBlock *) type; + + return block->name; +} + +static GskSlScalarType +gsk_sl_type_block_get_scalar_type (const GskSlType *type) +{ + return GSK_SL_VOID; +} + +static GskSlType * +gsk_sl_type_block_get_index_type (const GskSlType *type) +{ + return NULL; +} + +static gsize +gsk_sl_type_block_get_index_stride (const GskSlType *type) +{ + return 0; +} + +static guint +gsk_sl_type_block_get_length (const GskSlType *type) +{ + return 0; +} + +static gsize +gsk_sl_type_block_get_size (const GskSlType *type) +{ + const GskSlTypeBlock *block = (const GskSlTypeBlock *) type; + + return block->size; +} + +static guint +gsk_sl_type_block_get_n_members (const GskSlType *type) +{ + const GskSlTypeBlock *block = (const GskSlTypeBlock *) type; + + return block->n_members; +} + +static const GskSlTypeMember * +gsk_sl_type_block_get_member (const GskSlType *type, + guint n) +{ + const GskSlTypeBlock *block = (const GskSlTypeBlock *) type; + + return &block->members[n]; +} + +static gboolean +gsk_sl_type_block_can_convert (const GskSlType *target, + const GskSlType *source) +{ + return gsk_sl_type_equal (target, source); +} + +static guint32 +gsk_sl_type_block_write_spv (GskSlType *type, + GskSpvWriter *writer) +{ + GskSlTypeBlock *block = (GskSlTypeBlock *) type; + guint32 ids[block->n_members + 1]; + guint i; + + ids[0] = gsk_spv_writer_next_id (writer); + + for (i = 0; i < block->n_members; i++) + { + ids[i + 1] = gsk_spv_writer_get_id_for_type (writer, block->members[i].type); + } + + gsk_spv_writer_add (writer, + GSK_SPV_WRITER_SECTION_DEBUG, + 3, GSK_SPV_OP_DECORATE, + (guint32[2]) { ids[0], + GSK_SPV_DECORATION_BLOCK }); + + gsk_spv_writer_add (writer, + GSK_SPV_WRITER_SECTION_DECLARE, + 2 + block->n_members, GSK_SPV_OP_TYPE_STRUCT, + ids); + + return ids[0]; +} + +static void +gsk_sl_type_block_print_value (const GskSlType *type, + GskSlPrinter *printer, + gconstpointer value) +{ + const GskSlTypeBlock *block = (const GskSlTypeBlock *) type; + guint i; + + gsk_sl_printer_append (printer, block->name); + gsk_sl_printer_append (printer, "("); + + for (i = 0; i < block->n_members; i++) + { + if (i > 0) + gsk_sl_printer_append (printer, ", "); + gsk_sl_type_print_value (block->members[i].type, + printer, + (guchar *) value + block->members[i].offset); + } + + gsk_sl_printer_append (printer, ")"); +} + +static guint32 +gsk_sl_type_block_write_value_spv (GskSlType *type, + GskSpvWriter *writer, + gconstpointer value) +{ + GskSlTypeBlock *block = (GskSlTypeBlock *) type; + guint32 ids[block->n_members + 2]; + GskSlValue *v; + guint i; + + ids[0] = gsk_spv_writer_get_id_for_type (writer, type); + for (i = 0; i < block->n_members; i++) + { + v = gsk_sl_value_new_for_data (block->members[i].type, + (guchar *) value + block->members[i].offset, + NULL, NULL); + ids[2 + i] = gsk_spv_writer_get_id_for_value (writer, v); + gsk_sl_value_free (v); + } + + ids[1] = gsk_spv_writer_next_id (writer); + + gsk_spv_writer_add (writer, + GSK_SPV_WRITER_SECTION_DECLARE, + 3 + block->n_members, + GSK_SPV_OP_CONSTANT_COMPOSITE, + ids); + + return ids[1]; +} + +static const GskSlTypeClass GSK_SL_TYPE_BLOCK = { + gsk_sl_type_block_free, + gsk_sl_type_block_get_name, + gsk_sl_type_block_get_scalar_type, + gsk_sl_type_block_get_index_type, + gsk_sl_type_block_get_index_stride, + gsk_sl_type_block_get_length, + gsk_sl_type_block_get_size, + gsk_sl_type_block_get_n_members, + gsk_sl_type_block_get_member, + gsk_sl_type_block_can_convert, + gsk_sl_type_block_write_spv, + gsk_sl_type_block_print_value, + gsk_sl_type_block_write_value_spv +}; + /* API */ static GskSlType * @@ -1311,6 +1506,85 @@ 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_builtin (GskSlBuiltinType builtin) { @@ -1545,8 +1819,9 @@ gsk_sl_type_new_parse (GskSlScope *scope, type = gsk_sl_type_ref (type); break; } + + return gsk_sl_type_parse_block (scope, preproc); } - /* fall through */ default: gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected type specifier"); return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT)); @@ -1736,6 +2011,12 @@ gsk_sl_type_is_struct (const GskSlType *type) return type->class == &GSK_SL_TYPE_STRUCT; } +gboolean +gsk_sl_type_is_block (const GskSlType *type) +{ + return type->class == &GSK_SL_TYPE_BLOCK; +} + GskSlScalarType gsk_sl_type_get_scalar_type (const GskSlType *type) { @@ -1923,6 +2204,7 @@ struct _GskSlTypeBuilder { char *name; gsize size; GArray *members; + guint is_block :1; }; GskSlTypeBuilder * @@ -1938,6 +2220,22 @@ gsk_sl_type_builder_new_struct (const char *name) return builder; } +GskSlTypeBuilder * +gsk_sl_type_builder_new_block (const char *name) +{ + GskSlTypeBuilder *builder; + + g_assert (name != NULL); + + builder = g_slice_new0 (GskSlTypeBuilder); + + builder->name = g_strdup (name); + builder->members = g_array_new (FALSE, FALSE, sizeof (GskSlTypeMember)); + builder->is_block = TRUE; + + return builder; +} + static char * gsk_sl_type_builder_generate_name (GskSlTypeBuilder *builder) { @@ -1966,8 +2264,8 @@ gsk_sl_type_builder_generate_name (GskSlTypeBuilder *builder) return g_string_free (string, FALSE); } -GskSlType * -gsk_sl_type_builder_free (GskSlTypeBuilder *builder) +static GskSlType * +gsk_sl_type_builder_free_to_struct (GskSlTypeBuilder *builder) { GskSlTypeStruct *result; @@ -1986,6 +2284,32 @@ gsk_sl_type_builder_free (GskSlTypeBuilder *builder) return &result->parent; } +static GskSlType * +gsk_sl_type_builder_free_to_block (GskSlTypeBuilder *builder) +{ + GskSlTypeBlock *result; + + result = gsk_sl_type_new (GskSlTypeBlock, &GSK_SL_TYPE_BLOCK); + + result->name = builder->name; + result->size = builder->size; + result->n_members = builder->members->len; + result->members = (GskSlTypeMember *) g_array_free (builder->members, FALSE); + + g_slice_free (GskSlTypeBuilder, builder); + + return &result->parent; +} + +GskSlType * +gsk_sl_type_builder_free (GskSlTypeBuilder *builder) +{ + if (builder->is_block) + return gsk_sl_type_builder_free_to_block (builder); + else + return gsk_sl_type_builder_free_to_struct (builder); +} + void gsk_sl_type_builder_add_member (GskSlTypeBuilder *builder, GskSlType *type, diff --git a/gsk/gsksltypeprivate.h b/gsk/gsksltypeprivate.h index 6e4f1f7777..dcf10191dc 100644 --- a/gsk/gsksltypeprivate.h +++ b/gsk/gsksltypeprivate.h @@ -46,6 +46,7 @@ gboolean gsk_sl_type_is_scalar (const GskSlType gboolean gsk_sl_type_is_vector (const GskSlType *type); gboolean gsk_sl_type_is_matrix (const GskSlType *type); gboolean gsk_sl_type_is_struct (const GskSlType *type); +gboolean gsk_sl_type_is_block (const GskSlType *type); const char * gsk_sl_type_get_name (const GskSlType *type); GskSlScalarType gsk_sl_type_get_scalar_type (const GskSlType *type); @@ -89,6 +90,7 @@ void gsk_sl_scalar_type_convert_value (GskSlScalarType gconstpointer source_value); GskSlTypeBuilder * gsk_sl_type_builder_new_struct (const char *name); +GskSlTypeBuilder * gsk_sl_type_builder_new_block (const char *name); GskSlType * gsk_sl_type_builder_free (GskSlTypeBuilder *builder); void gsk_sl_type_builder_add_member (GskSlTypeBuilder *builder, GskSlType *type, diff --git a/gsk/gskslvariable.c b/gsk/gskslvariable.c index fa7ca24e52..439aa80efd 100644 --- a/gsk/gskslvariable.c +++ b/gsk/gskslvariable.c @@ -85,7 +85,31 @@ void gsk_sl_variable_print (const GskSlVariable *variable, GskSlPrinter *printer) { - gsk_sl_pointer_type_print (variable->type, printer); + GskSlType *type; + + if (gsk_sl_qualifier_print (gsk_sl_pointer_type_get_qualifier (variable->type), printer)) + gsk_sl_printer_append (printer, " "); + type = gsk_sl_pointer_type_get_type (variable->type); + gsk_sl_printer_append (printer, gsk_sl_type_get_name (type)); + if (gsk_sl_type_is_block (type)) + { + guint i, n; + + gsk_sl_printer_append (printer, " {"); + gsk_sl_printer_push_indentation (printer); + n = gsk_sl_type_get_n_members (type); + for (i = 0; i < n; i++) + { + gsk_sl_printer_newline (printer); + gsk_sl_printer_append (printer, gsk_sl_type_get_name (gsk_sl_type_get_member_type (type, i))); + gsk_sl_printer_append (printer, " "); + gsk_sl_printer_append (printer, gsk_sl_type_get_member_name (type, i)); + gsk_sl_printer_append (printer, ";"); + } + gsk_sl_printer_pop_indentation (printer); + gsk_sl_printer_newline (printer); + gsk_sl_printer_append (printer, "}"); + } if (variable->name) { gsk_sl_printer_append (printer, " "); diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h index 81b2af1df7..9a9aceb34a 100644 --- a/gsk/gskspvwriterprivate.h +++ b/gsk/gskspvwriterprivate.h @@ -95,6 +95,11 @@ typedef enum { GSK_SPV_OP_ARRAY_LENGTH = 68, GSK_SPV_OP_GENERIC_PTR_MEM_SEMANTICS = 69, GSK_SPV_OP_IN_BOUNDS_PTR_ACCESS_CHAIN = 70, + GSK_SPV_OP_DECORATE = 71, + GSK_SPV_OP_MEMBER_DECORATE = 72, + GSK_SPV_OP_DECORATION_GROUP = 73, + GSK_SPV_OP_GROUP_DECORATE = 74, + GSK_SPV_OP_GROUP_MEMBER_DECORATE = 75, GSK_SPV_OP_VECTOR_EXTRACT_DYNAMIC = 77, GSK_SPV_OP_VECTOR_INSERT_DYNAMIC = 78, GSK_SPV_OP_VECTOR_SHUFFLE = 79, @@ -161,7 +166,8 @@ typedef enum { GSK_SPV_OP_LIFETIME_STOP = 257, GSK_SPV_OP_SIZE_OF = 321, GSK_SPV_OP_TYPE_PIPE_STORAGE = 322, - GSK_SPV_OP_TYPE_NAMED_BARRIER = 327 + GSK_SPV_OP_TYPE_NAMED_BARRIER = 327, + GSK_SPV_OP_DECORATE_ID = 332 } GskSpvOpcode; typedef enum { @@ -211,6 +217,29 @@ typedef enum { GSK_SPV_STORAGE_CLASS_STORAGE_BUFFER = 12 } GskSpvStorageClass; +typedef enum { + GSK_SPV_DECORATION_RELAXED_PRECISION = 0, + GSK_SPV_DECORATION_SPEC_ID = 1, + GSK_SPV_DECORATION_BLOCK = 2, + GSK_SPV_DECORATION_BUFFER_BLOCK = 3, + GSK_SPV_DECORATION_ROW_MAJOR = 4, + GSK_SPV_DECORATION_COLUMN_MAJOR = 5, + GSK_SPV_DECORATION_ARRAY_STRIDE = 6, + GSK_SPV_DECORATION_MATRIX_STRIDE = 7, + GSK_SPV_DECORATION_GLSL_SHARED = 8, + GSK_SPV_DECORATION_GLSL_PACKED = 9, + GSK_SPV_DECORATION_C_PACKED = 10, + GSK_SPV_DECORATION_BUILTIN = 11, + GSK_SPV_DECORATION_NO_PERSPECTIVE = 13, + GSK_SPV_DECORATION_FLAT = 14, + GSK_SPV_DECORATION_PATCH = 15, + GSK_SPV_DECORATION_CENTROID = 16, + GSK_SPV_DECORATION_SAMPLE = 17, + GSK_SPV_DECORATION_INVARIANT = 18, + GSK_SPV_DECORATION_RESTRICT = 19, + GSK_SPV_DECORATION_ALIASED = 20 +} GskSpvDecoration; + typedef enum { GSK_SPV_WRITER_SECTION_HEADER, GSK_SPV_WRITER_SECTION_DEBUG,