From 7e4d163f11f8ee2254487e756c96af64f102fcff Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Tue, 26 Sep 2017 18:08:05 +0200 Subject: [PATCH] gskslprogram: Allow variables to have constant initializers Technically, all intiializers should be allowed, but for now we're happy we can do const ones. Also store them properly in the SPIR-V output. --- gsk/gskslnode.c | 2 +- gsk/gskslprogram.c | 53 +++++++++++++++++++++++++++++++++++++++++++-- gsk/gskslvariable.c | 13 +++++++---- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/gsk/gskslnode.c b/gsk/gskslnode.c index 46a0150894..d0cb8701bd 100644 --- a/gsk/gskslnode.c +++ b/gsk/gskslnode.c @@ -132,7 +132,7 @@ gsk_sl_node_declaration_write_spv (const GskSlNode *node, variable_id = gsk_spv_writer_get_id_for_variable (writer, declaration->variable); - if (declaration->initial) + if (declaration->initial && ! gsk_sl_variable_get_initial_value (declaration->variable)) { gsk_spv_writer_add (writer, GSK_SPV_WRITER_SECTION_CODE, diff --git a/gsk/gskslprogram.c b/gsk/gskslprogram.c index 9845433dfa..7b070d6d39 100644 --- a/gsk/gskslprogram.c +++ b/gsk/gskslprogram.c @@ -20,6 +20,7 @@ #include "gskslprogramprivate.h" +#include "gskslexpressionprivate.h" #include "gskslfunctionprivate.h" #include "gskslnodeprivate.h" #include "gskslpointertypeprivate.h" @@ -27,6 +28,7 @@ #include "gskslscopeprivate.h" #include "gsksltokenizerprivate.h" #include "gsksltypeprivate.h" +#include "gskslvalueprivate.h" #include "gskslvariableprivate.h" #include "gskspvwriterprivate.h" @@ -76,15 +78,55 @@ gsk_sl_program_parse_variable (GskSlProgram *program, { GskSlVariable *variable; const GskSlToken *token; + GskSlValue *value = NULL; GskSlPointerType *pointer_type; token = gsk_sl_preprocessor_get (preproc); + if (gsk_sl_token_is (token, GSK_SL_TOKEN_EQUAL)) + { + GskSlValue *unconverted; + GskSlExpression *initial; + + gsk_sl_preprocessor_consume (preproc, program); + + initial = gsk_sl_expression_parse_assignment (scope, preproc); + if (initial == NULL) + return FALSE; + + if (!gsk_sl_type_can_convert (type, gsk_sl_expression_get_return_type (initial))) + { + gsk_sl_preprocessor_error (preproc, "Cannot convert from initializer type %s to variable type %s", + gsk_sl_type_get_name (gsk_sl_expression_get_return_type (initial)), + gsk_sl_type_get_name (type)); + gsk_sl_expression_unref (initial); + return FALSE; + } + + unconverted = gsk_sl_expression_get_constant (initial); + gsk_sl_expression_unref (initial); + if (unconverted) + { + value = gsk_sl_value_new_convert (unconverted, type); + gsk_sl_value_free (unconverted); + } + else + { + gsk_sl_preprocessor_error (preproc, "Initializer is not constant."); + return FALSE; + } + + token = gsk_sl_preprocessor_get (preproc); + } + if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON)) - return FALSE; + { + gsk_sl_preprocessor_error (preproc, "No semicolon at end of variable declaration."); + return FALSE; + } 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, g_strdup (name), NULL, decoration->values[GSK_SL_DECORATION_CONST].set); + variable = gsk_sl_variable_new (pointer_type, g_strdup (name), value, decoration->values[GSK_SL_DECORATION_CONST].set); gsk_sl_pointer_type_unref (pointer_type); program->variables = g_slist_append (program->variables, variable); @@ -192,7 +234,14 @@ gsk_sl_program_print (GskSlProgram *program, for (l = program->variables; l; l = l->next) { + const GskSlValue *value; gsk_sl_variable_print (l->data, string); + value = gsk_sl_variable_get_initial_value (l->data); + if (value) + { + g_string_append (string, " = "); + gsk_sl_value_print (value, string); + } g_string_append (string, ";\n"); } diff --git a/gsk/gskslvariable.c b/gsk/gskslvariable.c index 9cedbc327f..51c39f1d58 100644 --- a/gsk/gskslvariable.c +++ b/gsk/gskslvariable.c @@ -124,16 +124,21 @@ guint32 gsk_sl_variable_write_spv (const GskSlVariable *variable, GskSpvWriter *writer) { - guint32 pointer_type_id, variable_id; + guint32 pointer_type_id, variable_id, value_id; pointer_type_id = gsk_spv_writer_get_id_for_pointer_type (writer, variable->type); variable_id = gsk_spv_writer_next_id (writer); + if (variable->initial_value) + value_id = gsk_spv_writer_get_id_for_value (writer, variable->initial_value); + else + value_id = 0; gsk_spv_writer_add (writer, GSK_SPV_WRITER_SECTION_CODE, - 4, GSK_SPV_OP_VARIABLE, - (guint32[3]) { pointer_type_id, + variable->initial_value ? 5 : 4, GSK_SPV_OP_VARIABLE, + (guint32[4]) { pointer_type_id, variable_id, - gsk_sl_pointer_type_get_storage_class (variable->type)}); + gsk_sl_pointer_type_get_storage_class (variable->type), + value_id }); return variable_id; }