gsksl: Add support for parsing members of struct variables

This includes adding the concept of members to GskSlType.
This commit is contained in:
Benjamin Otte
2017-09-28 03:38:56 +02:00
parent 8d6a332482
commit 500e6bc2bc
5 changed files with 293 additions and 31 deletions

View File

@@ -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));

View File

@@ -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)

View File

@@ -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,

View File

@@ -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)
{

View File

@@ -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);