diff --git a/gsk/gskslexpression.c b/gsk/gskslexpression.c index b8f23f01ea..9ea7cdb7e5 100644 --- a/gsk/gskslexpression.c +++ b/gsk/gskslexpression.c @@ -794,6 +794,95 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_FUNCTION_CALL = { gsk_sl_expression_function_call_write_spv }; +/* MEMBER */ + +typedef struct _GskSlExpressionMember GskSlExpressionMember; + +struct _GskSlExpressionMember { + GskSlExpression parent; + + GskSlExpression *expr; + guint id; +}; + +static void +gsk_sl_expression_member_free (GskSlExpression *expression) +{ + GskSlExpressionMember *member = (GskSlExpressionMember *) expression; + + gsk_sl_expression_unref (member->expr); + + g_slice_free (GskSlExpressionMember, member); +} + +static void +gsk_sl_expression_member_print (const GskSlExpression *expression, + GString *string) +{ + const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression; + + gsk_sl_expression_print (member->expr, string); + g_string_append (string, "."); + g_string_append (string, gsk_sl_type_get_member_name (gsk_sl_expression_get_return_type (member->expr), member->id)); +} + +static GskSlType * +gsk_sl_expression_member_get_return_type (const GskSlExpression *expression) +{ + const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression; + + return gsk_sl_type_get_member_type (gsk_sl_expression_get_return_type (member->expr), member->id); +} + +static GskSlValue * +gsk_sl_expression_member_get_constant (const GskSlExpression *expression) +{ + const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression; + GskSlValue *result, *value; + + value = gsk_sl_expression_get_constant (member->expr); + if (value == NULL) + return NULL; + + result = gsk_sl_value_new_member (value, member->id); + + gsk_sl_value_free (value); + + return result; +} + +static guint32 +gsk_sl_expression_member_write_spv (const GskSlExpression *expression, + GskSpvWriter *writer) +{ + const GskSlExpressionMember *member = (const GskSlExpressionMember *) expression; + GskSlType *type; + guint32 expr_id, type_id, result_id; + + type = gsk_sl_expression_get_return_type (member->expr); + type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_member_type (type, member->id)); + expr_id = gsk_sl_expression_write_spv (member->expr, writer); + result_id = gsk_spv_writer_next_id (writer); + + gsk_spv_writer_add (writer, + GSK_SPV_WRITER_SECTION_CODE, + 5, GSK_SPV_OP_ACCESS_CHAIN, + (guint32[4]) { type_id, + result_id, + expr_id, + member->id }); + + return result_id; +} + +static const GskSlExpressionClass GSK_SL_EXPRESSION_MEMBER = { + gsk_sl_expression_member_free, + gsk_sl_expression_member_print, + gsk_sl_expression_member_get_return_type, + gsk_sl_expression_member_get_constant, + gsk_sl_expression_member_write_spv +}; + /* SWIZZLE */ typedef enum { @@ -1268,6 +1357,7 @@ gsk_sl_expression_parse_field_selection (GskSlScope *scope, const char *name) { GskSlType *type; + guint n; if (g_str_equal (name, "length")) { @@ -1327,6 +1417,16 @@ gsk_sl_expression_parse_field_selection (GskSlScope *scope, return (GskSlExpression *) swizzle; } + else if (gsk_sl_type_find_member (type, name, &n, NULL, NULL)) + { + GskSlExpressionMember *member; + + member = gsk_sl_expression_new (GskSlExpressionMember, &GSK_SL_EXPRESSION_MEMBER); + member->expr = expr; + member->id = n; + + return (GskSlExpression *) member; + } else { gsk_sl_preprocessor_error (stream, TYPE_MISMATCH, "Type %s has no fields to select.", gsk_sl_type_get_name (type)); diff --git a/gsk/gsksltype.c b/gsk/gsksltype.c index 94dfdf55a3..b4b616cca3 100644 --- a/gsk/gsksltype.c +++ b/gsk/gsksltype.c @@ -31,8 +31,16 @@ #define N_SCALAR_TYPES 6 +typedef struct _GskSlTypeMember GskSlTypeMember; typedef struct _GskSlTypeClass GskSlTypeClass; +struct _GskSlTypeMember { + GskSlType *type; + char *name; + gsize offset; +}; + + struct _GskSlType { const GskSlTypeClass *class; @@ -42,13 +50,15 @@ struct _GskSlType struct _GskSlTypeClass { void (* free) (GskSlType *type); - const char * (* get_name) (const GskSlType *type); GskSlScalarType (* get_scalar_type) (const GskSlType *type); GskSlType * (* get_index_type) (const GskSlType *type); gsize (* get_index_stride) (const GskSlType *type); guint (* get_length) (const GskSlType *type); gsize (* get_size) (const GskSlType *type); + guint (* get_n_members) (const GskSlType *type); + const GskSlTypeMember * (* get_member) (const GskSlType *type, + guint i); gboolean (* can_convert) (const GskSlType *target, const GskSlType *source); guint32 (* write_spv) (GskSlType *type, @@ -387,6 +397,19 @@ gsk_sl_type_scalar_get_size (const GskSlType *type) return scalar_infos[scalar->scalar].size; } +static guint +gsk_sl_type_scalar_get_n_members (const GskSlType *type) +{ + return 0; +} + +static const GskSlTypeMember * +gsk_sl_type_scalar_get_member (const GskSlType *type, + guint n) +{ + return NULL; +} + static gboolean gsk_sl_type_scalar_can_convert (const GskSlType *target, const GskSlType *source) @@ -499,6 +522,8 @@ static const GskSlTypeClass GSK_SL_TYPE_SCALAR = { gsk_sl_type_scalar_get_index_stride, gsk_sl_type_scalar_get_length, gsk_sl_type_scalar_get_size, + gsk_sl_type_scalar_get_n_members, + gsk_sl_type_scalar_get_member, gsk_sl_type_scalar_can_convert, gsk_sl_type_scalar_write_spv, gsk_sl_type_scalar_print_value, @@ -571,6 +596,19 @@ gsk_sl_type_vector_get_size (const GskSlType *type) return vector->length * scalar_infos[vector->scalar].size; } +static guint +gsk_sl_type_vector_get_n_members (const GskSlType *type) +{ + return 0; +} + +static const GskSlTypeMember * +gsk_sl_type_vector_get_member (const GskSlType *type, + guint n) +{ + return NULL; +} + static gboolean gsk_sl_type_vector_can_convert (const GskSlType *target, const GskSlType *source) @@ -672,6 +710,8 @@ static const GskSlTypeClass GSK_SL_TYPE_VECTOR = { gsk_sl_type_vector_get_index_stride, gsk_sl_type_vector_get_length, gsk_sl_type_vector_get_size, + gsk_sl_type_vector_get_n_members, + gsk_sl_type_vector_get_member, gsk_sl_type_vector_can_convert, gsk_sl_type_vector_write_spv, gsk_sl_type_vector_print_value, @@ -745,6 +785,19 @@ gsk_sl_type_matrix_get_size (const GskSlType *type) return matrix->columns * matrix->rows * scalar_infos[matrix->scalar].size; } +static guint +gsk_sl_type_matrix_get_n_members (const GskSlType *type) +{ + return 0; +} + +static const GskSlTypeMember * +gsk_sl_type_matrix_get_member (const GskSlType *type, + guint n) +{ + return NULL; +} + static gboolean gsk_sl_type_matrix_can_convert (const GskSlType *target, const GskSlType *source) @@ -847,6 +900,8 @@ static const GskSlTypeClass GSK_SL_TYPE_MATRIX = { gsk_sl_type_matrix_get_index_stride, gsk_sl_type_matrix_get_length, gsk_sl_type_matrix_get_size, + gsk_sl_type_matrix_get_n_members, + gsk_sl_type_matrix_get_member, gsk_sl_type_matrix_can_convert, gsk_sl_type_matrix_write_spv, gsk_sl_type_matrix_print_value, @@ -855,15 +910,8 @@ static const GskSlTypeClass GSK_SL_TYPE_MATRIX = { /* STRUCT */ -typedef struct _GskSlTypeMember GskSlTypeMember; typedef struct _GskSlTypeStruct GskSlTypeStruct; -struct _GskSlTypeMember { - GskSlType *type; - char *name; - gsize offset; -}; - struct _GskSlTypeStruct { GskSlType parent; @@ -893,55 +941,72 @@ gsk_sl_type_struct_free (GskSlType *type) } static const char * -gsk_sl_type_struct_get_name (GskSlType *type) +gsk_sl_type_struct_get_name (const GskSlType *type) { - GskSlTypeStruct *struc = (GskSlTypeStruct *) type; + const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type; return struc->name; } static GskSlScalarType -gsk_sl_type_struct_get_scalar_type (GskSlType *type) +gsk_sl_type_struct_get_scalar_type (const GskSlType *type) { return GSK_SL_VOID; } static GskSlType * -gsk_sl_type_struct_get_index_type (GskSlType *type) +gsk_sl_type_struct_get_index_type (const GskSlType *type) { return NULL; } static gsize -gsk_sl_type_struct_get_index_stride (GskSlType *type) +gsk_sl_type_struct_get_index_stride (const GskSlType *type) { return 0; } static guint -gsk_sl_type_struct_get_length (GskSlType *type) +gsk_sl_type_struct_get_length (const GskSlType *type) { return 0; } static gsize -gsk_sl_type_struct_get_size (GskSlType *type) +gsk_sl_type_struct_get_size (const GskSlType *type) { - GskSlTypeStruct *struc = (GskSlTypeStruct *) type; + const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type; return struc->size; } +static guint +gsk_sl_type_struct_get_n_members (const GskSlType *type) +{ + const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type; + + return struc->n_members; +} + +static const GskSlTypeMember * +gsk_sl_type_struct_get_member (const GskSlType *type, + guint n) +{ + const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type; + + return &struc->members[n]; +} + static gboolean -gsk_sl_type_struct_can_convert (GskSlType *target, - GskSlType *source) +gsk_sl_type_struct_can_convert (const GskSlType *target, + const GskSlType *source) { return gsk_sl_type_equal (target, source); } static guint32 -gsk_sl_type_struct_write_spv (const GskSlType *type, - GskSpvWriter *writer) +gsk_sl_type_struct_write_spv (GskSlType *type, + GskSpvWriter *writer) { GskSlTypeStruct *struc = (GskSlTypeStruct *) type; guint32 ids[struc->n_members + 1]; @@ -965,9 +1030,9 @@ gsk_sl_type_struct_write_spv (const GskSlType *type, static void gsk_sl_type_struct_print_value (const GskSlType *type, GString *string, - gpointer value) + gconstpointer value) { - GskSlTypeStruct *struc = (GskSlTypeStruct *) type; + const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type; guint i; g_string_append (string, struc->name); @@ -986,20 +1051,15 @@ gsk_sl_type_struct_print_value (const GskSlType *type, } static guint32 -gsk_sl_type_struct_write_value_spv (GskSlType *type, - GskSpvWriter *writer, - gpointer value) +gsk_sl_type_struct_write_value_spv (GskSlType *type, + GskSpvWriter *writer, + gconstpointer value) { GskSlTypeStruct *struc = (GskSlTypeStruct *) type; guint32 ids[struc->n_members + 2]; - GskSlType *vector_type; GskSlValue *v; - guchar *data; guint i; - data = value; - vector_type = gsk_sl_type_get_index_type (type); - ids[0] = gsk_spv_writer_get_id_for_type (writer, type); for (i = 0; i < struc->n_members; i++) { @@ -1008,7 +1068,6 @@ gsk_sl_type_struct_write_value_spv (GskSlType *type, NULL, NULL); ids[2 + i] = gsk_spv_writer_get_id_for_value (writer, v); gsk_sl_value_free (v); - data += gsk_sl_type_get_size (vector_type); } ids[1] = gsk_spv_writer_next_id (writer); @@ -1030,6 +1089,8 @@ static const GskSlTypeClass GSK_SL_TYPE_STRUCT = { gsk_sl_type_struct_get_index_stride, gsk_sl_type_struct_get_length, gsk_sl_type_struct_get_size, + gsk_sl_type_struct_get_n_members, + gsk_sl_type_struct_get_member, gsk_sl_type_struct_can_convert, gsk_sl_type_struct_write_spv, gsk_sl_type_struct_print_value, @@ -1482,6 +1543,81 @@ gsk_sl_type_get_size (const GskSlType *type) return type->class->get_size (type); } +guint +gsk_sl_type_get_n_members (const GskSlType *type) +{ + return type->class->get_n_members (type); +} + +static const GskSlTypeMember * +gsk_sl_type_get_member (const GskSlType *type, + guint n) +{ + return type->class->get_member (type, n); +} + +GskSlType * +gsk_sl_type_get_member_type (const GskSlType *type, + guint n) +{ + const GskSlTypeMember *member; + + member = gsk_sl_type_get_member (type, n); + + return member->type; +} + +const char * +gsk_sl_type_get_member_name (const GskSlType *type, + guint n) +{ + const GskSlTypeMember *member; + + member = gsk_sl_type_get_member (type, n); + + return member->name; +} + +gsize +gsk_sl_type_get_member_offset (const GskSlType *type, + guint n) +{ + const GskSlTypeMember *member; + + member = gsk_sl_type_get_member (type, n); + + return member->offset; +} + +gboolean +gsk_sl_type_find_member (const GskSlType *type, + const char *name, + guint *out_index, + GskSlType **out_type, + gsize *out_offset) +{ + const GskSlTypeMember *member; + guint i, n; + + n = gsk_sl_type_get_n_members (type); + for (i = 0; i < n; i++) + { + member = gsk_sl_type_get_member (type, i); + if (g_str_equal (member->name, name)) + { + if (out_index) + *out_index = i; + if (out_type) + *out_type = member->type; + if (out_offset) + *out_offset = member->offset; + return TRUE; + } + } + + return FALSE; +} + gboolean gsk_sl_scalar_type_can_convert (GskSlScalarType target, GskSlScalarType source) diff --git a/gsk/gsksltypeprivate.h b/gsk/gsksltypeprivate.h index c07d8d61c3..592d5246cf 100644 --- a/gsk/gsksltypeprivate.h +++ b/gsk/gsksltypeprivate.h @@ -59,6 +59,18 @@ GskSlType * gsk_sl_type_get_index_type (const GskSlType gsize gsk_sl_type_get_index_stride (const GskSlType *type); guint gsk_sl_type_get_length (const GskSlType *type); gsize gsk_sl_type_get_size (const GskSlType *type); +guint gsk_sl_type_get_n_members (const GskSlType *type); +GskSlType * gsk_sl_type_get_member_type (const GskSlType *type, + guint n); +const char * gsk_sl_type_get_member_name (const GskSlType *type, + guint n); +gsize gsk_sl_type_get_member_offset (const GskSlType *type, + guint n); +gboolean gsk_sl_type_find_member (const GskSlType *type, + const char *name, + guint *out_index, + GskSlType **out_type, + gsize *out_offset); gboolean gsk_sl_scalar_type_can_convert (GskSlScalarType target, GskSlScalarType source); gboolean gsk_sl_type_can_convert (const GskSlType *target, diff --git a/gsk/gskslvalue.c b/gsk/gskslvalue.c index 4049730d05..6972ff7c72 100644 --- a/gsk/gskslvalue.c +++ b/gsk/gskslvalue.c @@ -158,6 +158,18 @@ gsk_sl_value_new_convert (GskSlValue *source, } } +GskSlValue * +gsk_sl_value_new_member (GskSlValue *value, + guint n) +{ + gpointer data; + + data = g_memdup ((guchar *) value->data + gsk_sl_type_get_member_offset (value->type, n), + gsk_sl_type_get_size (gsk_sl_type_get_member_type (value->type, n))); + + return gsk_sl_value_new_for_data (value->type, data, g_free, data); +} + GskSlValue * gsk_sl_value_copy (const GskSlValue *source) { diff --git a/gsk/gskslvalueprivate.h b/gsk/gskslvalueprivate.h index afd81b5a52..c4e7c595ec 100644 --- a/gsk/gskslvalueprivate.h +++ b/gsk/gskslvalueprivate.h @@ -30,6 +30,8 @@ GskSlValue * gsk_sl_value_new_for_data (GskSlType gpointer user_data); GskSlValue * gsk_sl_value_new_convert (GskSlValue *source, GskSlType *new_type); +GskSlValue * gsk_sl_value_new_member (GskSlValue *value, + guint n); GskSlValue * gsk_sl_value_copy (const GskSlValue *source); void gsk_sl_value_free (GskSlValue *value);