[gtk+/wip/otte/shader: 5/48] gskslexpression: Parse swizzles
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/shader: 5/48] gskslexpression: Parse swizzles
- Date: Tue, 3 Oct 2017 02:13:00 +0000 (UTC)
commit 5c5fa381876a66c519f8035b48c0e82e8aae9a64
Author: Benjamin Otte <otte redhat com>
Date: Wed Sep 27 03:14:53 2017 +0200
gskslexpression: Parse swizzles
gsk/gskslexpression.c | 288 ++++++++++++++++++++++++++++++++++++++++++++-
gsk/gskspvwriterprivate.h | 24 ++++
2 files changed, 311 insertions(+), 1 deletions(-)
---
diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c
index 4fa07a5..2e9f765 100644
--- a/gsk/gskslexpression.c
+++ b/gsk/gskslexpression.c
@@ -785,6 +785,177 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_FUNCTION_CALL = {
gsk_sl_expression_function_call_write_spv
};
+/* SWIZZLE */
+
+typedef enum {
+ GSK_SL_SWIZZLE_POINT,
+ GSK_SL_SWIZZLE_COLOR,
+ GSK_SL_SWIZZLE_TEXCOORD
+} GskSlSwizzleName;
+
+static char *swizzle_options[] = { "xyzw", "rgba", "stpq" };
+
+typedef struct _GskSlExpressionSwizzle GskSlExpressionSwizzle;
+
+struct _GskSlExpressionSwizzle {
+ GskSlExpression parent;
+
+ GskSlExpression *expr;
+ GskSlSwizzleName name;
+ guint length;
+ guint indexes[4];
+};
+
+static void
+gsk_sl_expression_swizzle_free (GskSlExpression *expression)
+{
+ GskSlExpressionSwizzle *swizzle = (GskSlExpressionSwizzle *) expression;
+
+ gsk_sl_expression_unref (swizzle->expr);
+
+ g_slice_free (GskSlExpressionSwizzle, swizzle);
+}
+
+static void
+gsk_sl_expression_swizzle_print (const GskSlExpression *expression,
+ GString *string)
+{
+ const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+ guint i;
+
+ gsk_sl_expression_print (swizzle->expr, string);
+ g_string_append (string, ".");
+ for (i = 0; i < swizzle->length; i++)
+ {
+ g_string_append_c (string, swizzle_options[swizzle->name][swizzle->indexes[i]]);
+ }
+}
+
+static GskSlType *
+gsk_sl_expression_swizzle_get_return_type (const GskSlExpression *expression)
+{
+ const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+ GskSlType *type;
+
+ type = gsk_sl_expression_get_return_type (swizzle->expr);
+
+ if (swizzle->length == 1)
+ return gsk_sl_type_get_scalar (gsk_sl_type_get_scalar_type (type));
+ else
+ return gsk_sl_type_get_vector (gsk_sl_type_get_scalar_type (type), swizzle->length);
+}
+
+static GskSlValue *
+gsk_sl_expression_swizzle_get_constant (const GskSlExpression *expression)
+{
+ const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+ GskSlValue *result, *value;
+ guchar *sdata, *ddata;
+ gsize sstride, dstride;
+ GskSlScalarType scalar_type;
+ guint i;
+
+ value = gsk_sl_expression_get_constant (swizzle->expr);
+ if (value == NULL)
+ return NULL;
+
+ scalar_type = gsk_sl_type_get_scalar_type (gsk_sl_value_get_type (value));
+ sdata = gsk_sl_value_get_data (value);
+ sstride = gsk_sl_type_get_index_stride (gsk_sl_value_get_type (value));
+ result = gsk_sl_value_new (gsk_sl_expression_get_return_type (expression));
+ ddata = gsk_sl_value_get_data (result);
+ dstride = gsk_sl_type_get_index_stride (gsk_sl_value_get_type (result));
+
+ for (i = 0; i < swizzle->length; i++)
+ {
+ gsk_sl_scalar_type_convert_value (scalar_type,
+ ddata + dstride * i,
+ scalar_type,
+ sdata + sstride * swizzle->indexes[i]);
+ }
+
+ gsk_sl_value_free (value);
+
+ return result;
+}
+
+static guint32
+gsk_sl_expression_swizzle_write_spv (const GskSlExpression *expression,
+ GskSpvWriter *writer)
+{
+ const GskSlExpressionSwizzle *swizzle = (const GskSlExpressionSwizzle *) expression;
+ GskSlType *type;
+ guint32 expr_id, type_id, result_id;
+
+ type = gsk_sl_expression_get_return_type (swizzle->expr);
+ expr_id = gsk_sl_expression_write_spv (swizzle->expr, writer);
+
+ if (gsk_sl_type_is_scalar (type))
+ {
+ if (swizzle->length == 1)
+ return expr_id;
+
+ type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_expression_get_return_type (expression));
+ result_id = gsk_spv_writer_next_id (writer);
+
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 3 + swizzle->length, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
+ (guint32[6]) { type_id,
+ result_id,
+ expr_id,
+ expr_id,
+ expr_id,
+ expr_id });
+
+ return result_id;
+ }
+ else if (gsk_sl_type_is_vector (type))
+ {
+ type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_expression_get_return_type (expression));
+ result_id = gsk_spv_writer_next_id (writer);
+
+ if (swizzle->length == 1)
+ {
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 4, GSK_SPV_OP_COMPOSITE_EXTRACT,
+ (guint32[6]) { type_id,
+ result_id,
+ swizzle->indexes[0] });
+ }
+ else
+ {
+ gsk_spv_writer_add (writer,
+ GSK_SPV_WRITER_SECTION_CODE,
+ 5 + swizzle->length, GSK_SPV_OP_COMPOSITE_CONSTRUCT,
+ (guint32[8]) { type_id,
+ result_id,
+ expr_id,
+ expr_id,
+ swizzle->indexes[0],
+ swizzle->indexes[1],
+ swizzle->indexes[2],
+ swizzle->indexes[3] });
+ }
+
+ return result_id;
+ }
+ else
+ {
+ g_assert_not_reached ();
+ return 0;
+ }
+}
+
+static const GskSlExpressionClass GSK_SL_EXPRESSION_SWIZZLE = {
+ gsk_sl_expression_swizzle_free,
+ gsk_sl_expression_swizzle_print,
+ gsk_sl_expression_swizzle_get_return_type,
+ gsk_sl_expression_swizzle_get_constant,
+ gsk_sl_expression_swizzle_write_spv
+};
+
/* CONSTANT */
typedef struct _GskSlExpressionConstant GskSlExpressionConstant;
@@ -1049,10 +1220,125 @@ gsk_sl_expression_parse_primary (GskSlScope *scope,
}
static GskSlExpression *
+gsk_sl_expression_parse_field_selection (GskSlScope *scope,
+ GskSlPreprocessor *stream,
+ GskSlExpression *expr,
+ const char *name,
+ gboolean *success)
+{
+ GskSlType *type;
+
+ if (g_str_equal (name, "length"))
+ {
+ gsk_sl_preprocessor_error (stream, ".length() is not implemented yet.");
+ *success = FALSE;
+ return expr;
+ }
+
+ type = gsk_sl_expression_get_return_type (expr);
+
+ if (gsk_sl_type_is_scalar (type) || gsk_sl_type_is_vector (type))
+ {
+ GskSlExpressionSwizzle *swizzle;
+ guint type_length = MAX (1, gsk_sl_type_get_length (type));
+
+ swizzle = gsk_sl_expression_new (GskSlExpressionSwizzle, &GSK_SL_EXPRESSION_SWIZZLE);
+
+ for (swizzle->name = 0; swizzle->name < G_N_ELEMENTS(swizzle_options); swizzle->name++)
+ {
+ const char *found = strchr (swizzle_options[swizzle->name], name[0]);
+ if (found)
+ break;
+ }
+ if (swizzle->name == G_N_ELEMENTS(swizzle_options))
+ {
+ gsk_sl_preprocessor_error (stream, "Type %s has no member named \"%s\".", gsk_sl_type_get_name
(type), name);
+ gsk_sl_expression_unref ((GskSlExpression *) swizzle);
+ *success = FALSE;
+ return expr;
+ }
+ swizzle->expr = expr;
+
+ for (swizzle->length = 0; swizzle->length < 4 && name[swizzle->length]; swizzle->length++)
+ {
+ const char *found = strchr (swizzle_options[swizzle->name], name[swizzle->length]);
+ if (found == NULL)
+ {
+ gsk_sl_preprocessor_error (stream, "Character '%c' is not valid for swizzle. Must be one of
\"%s\".",
+ name[swizzle->length], swizzle_options[swizzle->name]);
+ *success = FALSE;
+ return (GskSlExpression *) swizzle;
+ }
+ swizzle->indexes[swizzle->length] = found - swizzle_options[swizzle->name];
+ if (swizzle->indexes[swizzle->length] >= type_length)
+ {
+ gsk_sl_preprocessor_error (stream, "Swizzle index '%c' not allowed for type %s",
+ name[swizzle->length], gsk_sl_type_get_name (type));
+ *success = FALSE;
+ return (GskSlExpression *) swizzle;
+ }
+ }
+ if (name[swizzle->length])
+ {
+ gsk_sl_preprocessor_error (stream, "Too many swizzle options. A maximum of 4 characters are
allowed.");
+ *success = FALSE;
+ return (GskSlExpression *) swizzle;
+ }
+
+ return (GskSlExpression *) swizzle;
+ }
+ else
+ {
+ gsk_sl_preprocessor_error (stream, "Cannot select fields of type %s.", gsk_sl_type_get_name (type));
+ *success = FALSE;
+ return expr;
+ }
+}
+
+static GskSlExpression *
gsk_sl_expression_parse_postfix (GskSlScope *scope,
GskSlPreprocessor *stream)
{
- return gsk_sl_expression_parse_primary (scope, stream);
+ GskSlExpression *expr;
+ const GskSlToken *token;
+ gboolean success = TRUE;
+
+ expr = gsk_sl_expression_parse_primary (scope, stream);
+
+ while (TRUE)
+ {
+ token = gsk_sl_preprocessor_get (stream);
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_DOT))
+ {
+ gsk_sl_preprocessor_consume (stream, NULL);
+ token = gsk_sl_preprocessor_get (stream);
+ if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
+ {
+ char *field = g_strdup (token->str);
+ gsk_sl_preprocessor_consume (stream, NULL);
+ expr = gsk_sl_expression_parse_field_selection (scope, stream, expr, field, &success);
+ g_free (field);
+ }
+ else
+ {
+ gsk_sl_preprocessor_error (stream, "Expected an identifier to select a field.");
+ success = FALSE;
+ continue;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (!success)
+ {
+ gsk_sl_expression_unref (expr);
+ return NULL;
+ }
+
+ return expr;
}
static GskSlExpression *
diff --git a/gsk/gskspvwriterprivate.h b/gsk/gskspvwriterprivate.h
index 321c138..c0f3d5c 100644
--- a/gsk/gskspvwriterprivate.h
+++ b/gsk/gskspvwriterprivate.h
@@ -95,6 +95,30 @@ 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_VECTOR_EXTRACT_DYNAMIC = 77,
+ GSK_SPV_OP_VECTOR_INSERT_DYNAMIC = 78,
+ GSK_SPV_OP_VECTOR_SHUFFLE = 79,
+ GSK_SPV_OP_COMPOSITE_CONSTRUCT = 80,
+ GSK_SPV_OP_COMPOSITE_EXTRACT = 81,
+ GSK_SPV_OP_COMPOSITE_INSERT = 82,
+ GSK_SPV_OP_COPY_OBJECT = 83,
+ GSK_SPV_OP_TRANSPOSE = 84,
+ GSK_SPV_OP_CONVERT_F_TO_U = 109,
+ GSK_SPV_OP_CONVERT_F_TO_S = 110,
+ GSK_SPV_OP_CONVERT_S_TO_F = 111,
+ GSK_SPV_OP_CONVERT_U_TO_F = 112,
+ GSK_SPV_OP_U_CONVERT = 113,
+ GSK_SPV_OP_S_CONVERT = 114,
+ GSK_SPV_OP_F_CONVERT = 115,
+ GSK_SPV_OP_QUANTIZE_TO_F16 = 116,
+ GSK_SPV_OP_CONVERT_PTR_TO_U = 117,
+ GSK_SPV_OP_SAT_CONVERT_S_TO_U = 118,
+ GSK_SPV_OP_SAT_CONVERT_U_TO_S = 119,
+ GSK_SPV_OP_CONVERT_U_TO_PTR = 120,
+ GSK_SPV_OP_PTR_CAST_TO_GENERIC = 121,
+ GSK_SPV_OP_GENERIC_CAST_TO_PTR = 122,
+ GSK_SPV_OP_GENERIC_CAST_TO_PTR_EXPLICIT = 123,
+ GSK_SPV_OP_BITCAST = 124,
GSK_SPV_OP_PHI = 245,
GSK_SPV_OP_LOOP_MERGE = 246,
GSK_SPV_OP_SELECTION_MERGE = 247,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]