Files
gtk/gsk/gsksltype.c
Benjamin Otte d33881e0ec gsksltype: Implement arrays
This is incomplete as we can only declare variables using array types
but not as arrays of static types yet.
2017-10-30 02:58:03 +01:00

3096 lines
89 KiB
C

/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gsksltypeprivate.h"
#include "gskslexpressionprivate.h"
#include "gskslfunctionprivate.h"
#include "gskslimagetypeprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslprinterprivate.h"
#include "gskslscopeprivate.h"
#include "gsksltokenizerprivate.h"
#include "gskslvalueprivate.h"
#include "gskspvwriterprivate.h"
#include <string.h>
#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;
int ref_count;
};
struct _GskSlTypeClass {
void (* free) (GskSlType *type);
const char * (* get_name) (const GskSlType *type);
GskSlScalarType (* get_scalar_type) (const GskSlType *type);
const GskSlImageType *(* get_image_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);
gsize (* get_n_components) (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,
GskSpvWriter *writer);
void (* print_value) (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value);
gboolean (* value_equal) (const GskSlType *type,
gconstpointer a,
gconstpointer b);
guint32 (* write_value_spv) (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value);
};
static void
print_void (GskSlPrinter *printer,
gconstpointer value)
{
g_assert_not_reached ();
}
static guint32
write_void_spv (GskSpvWriter *writer,
gconstpointer value)
{
g_assert_not_reached ();
}
static void
print_float (GskSlPrinter *printer,
gconstpointer value)
{
const gfloat *f = value;
gsk_sl_printer_append_float (printer, *f);
}
static guint32
write_float_spv (GskSpvWriter *writer,
gconstpointer value)
{
return gsk_spv_writer_constant (writer,
gsk_sl_type_get_scalar (GSK_SL_FLOAT),
(guint32 *) value,
1);
}
static void
print_double (GskSlPrinter *printer,
gconstpointer value)
{
const gdouble *d = value;
gsk_sl_printer_append_double (printer, *d);
}
static guint32
write_double_spv (GskSpvWriter *writer,
gconstpointer value)
{
return gsk_spv_writer_constant (writer,
gsk_sl_type_get_scalar (GSK_SL_DOUBLE),
(guint32 *) value,
2);
}
static void
print_int (GskSlPrinter *printer,
gconstpointer value)
{
const gint32 *i = value;
gsk_sl_printer_append_int (printer, *i);
}
static guint32
write_int_spv (GskSpvWriter *writer,
gconstpointer value)
{
return gsk_spv_writer_constant (writer,
gsk_sl_type_get_scalar (GSK_SL_INT),
(guint32 *) value,
1);
}
static void
print_uint (GskSlPrinter *printer,
gconstpointer value)
{
const guint32 *u = value;
gsk_sl_printer_append_uint (printer, *u);
gsk_sl_printer_append_c (printer, 'u');
}
static guint32
write_uint_spv (GskSpvWriter *writer,
gconstpointer value)
{
return gsk_spv_writer_constant (writer,
gsk_sl_type_get_scalar (GSK_SL_UINT),
(guint32 *) value,
1);
}
static void
print_bool (GskSlPrinter *printer,
gconstpointer value)
{
const guint32 *u = value;
gsk_sl_printer_append (printer, *u ? "true" : "false");
}
static guint32
write_bool_spv (GskSpvWriter *writer,
gconstpointer value)
{
if (*(const guint32 *) value)
return gsk_spv_writer_constant_true (writer,
gsk_sl_type_get_scalar (GSK_SL_BOOL));
else
return gsk_spv_writer_constant_false (writer,
gsk_sl_type_get_scalar (GSK_SL_BOOL));
}
#define SIMPLE_CONVERSION(source_name, target_name, source_type, target_type) \
static void \
source_name ## _to_ ## target_name (gpointer target, gconstpointer source) \
{ \
*(target_type *) target = *(const source_type *) source; \
}
SIMPLE_CONVERSION(float, float, float, float);
SIMPLE_CONVERSION(float, double, float, double);
SIMPLE_CONVERSION(float, int, float, gint32);
SIMPLE_CONVERSION(float, uint, float, guint32);
static void
float_to_bool (gpointer target, gconstpointer source)
{
*(guint32 *) target = *(const float *) source ? TRUE : FALSE;
}
SIMPLE_CONVERSION(double, float, double, float);
SIMPLE_CONVERSION(double, double, double, double);
SIMPLE_CONVERSION(double, int, double, gint32);
SIMPLE_CONVERSION(double, uint, double, guint32);
static void
double_to_bool (gpointer target, gconstpointer source)
{
*(guint32 *) target = *(const double *) source ? TRUE : FALSE;
}
SIMPLE_CONVERSION(int, float, gint32, float);
SIMPLE_CONVERSION(int, double, gint32, double);
SIMPLE_CONVERSION(int, int, gint32, gint32);
SIMPLE_CONVERSION(int, uint, gint32, guint32);
static void
int_to_bool (gpointer target, gconstpointer source)
{
*(guint32 *) target = *(const gint32 *) source ? TRUE : FALSE;
}
SIMPLE_CONVERSION(uint, float, guint32, float);
SIMPLE_CONVERSION(uint, double, guint32, double);
SIMPLE_CONVERSION(uint, int, guint32, gint32);
SIMPLE_CONVERSION(uint, uint, guint32, guint32);
static void
uint_to_bool (gpointer target, gconstpointer source)
{
*(guint32 *) target = *(const guint32 *) source ? TRUE : FALSE;
}
static void
bool_to_float (gpointer target, gconstpointer source)
{
*(float *) target = *(const guint32 *) source ? 1.0 : 0.0;
}
static void
bool_to_double (gpointer target, gconstpointer source)
{
*(double *) target = *(const guint32 *) source ? 1.0 : 0.0;
}
static void
bool_to_int (gpointer target, gconstpointer source)
{
*(gint32 *) target = *(const guint32 *) source ? 1 : 0;
}
static void
bool_to_uint (gpointer target, gconstpointer source)
{
*(guint32 *) target = *(const guint32 *) source ? 1 : 0;
}
static void
bool_to_bool (gpointer target, gconstpointer source)
{
*(guint32 *) target = *(const guint32 *) source;
}
static gboolean
void_equal (gconstpointer a, gconstpointer b)
{
return FALSE;
}
static gboolean
int_equal (gconstpointer a, gconstpointer b)
{
return *(const gint32 *) a == *(const gint32 *) b;
}
static gboolean
uint_equal (gconstpointer a, gconstpointer b)
{
return *(const guint32 *) a == *(const guint32 *) b;
}
static gboolean
float_equal (gconstpointer a, gconstpointer b)
{
return *(const float *) a == *(const float *) b;
}
static gboolean
double_equal (gconstpointer a, gconstpointer b)
{
return *(const double *) a == *(const double *) b;
}
static gboolean
bool_equal (gconstpointer a, gconstpointer b)
{
return !*(const guint32 *) a == !*(const guint32 *) b;
}
#define CONVERSIONS(name) { NULL, name ## _to_float, name ## _to_double, name ## _to_int, name ## _to_uint, name ## _to_bool }
struct {
const char *name;
gsize size;
void (* print_value) (GskSlPrinter *printer, gconstpointer value);
gboolean (* value_equal) (gconstpointer a, gconstpointer b);
void (* convert_value[N_SCALAR_TYPES]) (gpointer target, gconstpointer source);
guint32 (* write_value_spv) (GskSpvWriter *writer, gconstpointer value);
} scalar_infos[] = {
[GSK_SL_VOID] = { "void", 0, print_void, void_equal, { NULL, }, write_void_spv, },
[GSK_SL_FLOAT] = { "float", 4, print_float, float_equal, CONVERSIONS (float), write_float_spv },
[GSK_SL_DOUBLE] = { "double", 8, print_double, double_equal, CONVERSIONS (double), write_double_spv },
[GSK_SL_INT] = { "int", 4, print_int, int_equal, CONVERSIONS (int), write_int_spv },
[GSK_SL_UINT] = { "uint", 4, print_uint, uint_equal, CONVERSIONS (uint), write_uint_spv },
[GSK_SL_BOOL] = { "bool", 4, print_bool, bool_equal, CONVERSIONS (bool), write_bool_spv }
};
#undef SIMPLE_CONVERSION
#undef CONVERSIONS
static GskSlType *
gsk_sl_type_alloc (const GskSlTypeClass *klass,
gsize size)
{
GskSlType *type;
type = g_slice_alloc0 (size);
type->class = klass;
type->ref_count = 1;
return type;
}
#define gsk_sl_type_new(_name, _klass) ((_name *) gsk_sl_type_alloc ((_klass), sizeof (_name)))
/* VOID */
typedef struct _GskSlTypeVoid GskSlTypeVoid;
struct _GskSlTypeVoid {
GskSlType parent;
};
static void
gsk_sl_type_void_free (GskSlType *type)
{
g_assert_not_reached ();
}
static const char *
gsk_sl_type_void_get_name (const GskSlType *type)
{
return "void";
}
static GskSlScalarType
gsk_sl_type_void_get_scalar_type (const GskSlType *type)
{
return GSK_SL_VOID;
}
static const GskSlImageType *
gsk_sl_type_void_get_image_type (const GskSlType *type)
{
return NULL;
}
static GskSlType *
gsk_sl_type_void_get_index_type (const GskSlType *type)
{
return NULL;
}
static gsize
gsk_sl_type_void_get_index_stride (const GskSlType *type)
{
return 0;
}
static guint
gsk_sl_type_void_get_length (const GskSlType *type)
{
return 0;
}
static gsize
gsk_sl_type_void_get_size (const GskSlType *type)
{
return 0;
}
static gsize
gsk_sl_type_void_get_n_components (const GskSlType *type)
{
return 0;
}
static guint
gsk_sl_type_void_get_n_members (const GskSlType *type)
{
return 0;
}
static const GskSlTypeMember *
gsk_sl_type_void_get_member (const GskSlType *type,
guint n)
{
return NULL;
}
static gboolean
gsk_sl_type_void_can_convert (const GskSlType *target,
const GskSlType *source)
{
return FALSE;
}
static guint32
gsk_sl_type_void_write_spv (GskSlType *type,
GskSpvWriter *writer)
{
return gsk_spv_writer_type_void (writer);
}
static void
gsk_sl_type_void_print_value (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value)
{
g_assert_not_reached ();
}
static gboolean
gsk_sl_type_void_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b)
{
return FALSE;
}
static guint32
gsk_sl_type_void_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value)
{
g_assert_not_reached ();
return 0;
}
static const GskSlTypeClass GSK_SL_TYPE_VOID = {
gsk_sl_type_void_free,
gsk_sl_type_void_get_name,
gsk_sl_type_void_get_scalar_type,
gsk_sl_type_void_get_image_type,
gsk_sl_type_void_get_index_type,
gsk_sl_type_void_get_index_stride,
gsk_sl_type_void_get_length,
gsk_sl_type_void_get_size,
gsk_sl_type_void_get_n_components,
gsk_sl_type_void_get_n_members,
gsk_sl_type_void_get_member,
gsk_sl_type_void_can_convert,
gsk_sl_type_void_write_spv,
gsk_sl_type_void_print_value,
gsk_sl_type_void_value_equal,
gsk_sl_type_void_write_value_spv
};
/* SCALAR */
typedef struct _GskSlTypeScalar GskSlTypeScalar;
struct _GskSlTypeScalar {
GskSlType parent;
GskSlScalarType scalar;
};
static void
gsk_sl_type_scalar_free (GskSlType *type)
{
g_assert_not_reached ();
}
static const char *
gsk_sl_type_scalar_get_name (const GskSlType *type)
{
const GskSlTypeScalar *scalar = (const GskSlTypeScalar *) type;
return scalar_infos[scalar->scalar].name;
}
static GskSlScalarType
gsk_sl_type_scalar_get_scalar_type (const GskSlType *type)
{
GskSlTypeScalar *scalar = (GskSlTypeScalar *) type;
return scalar->scalar;
}
static const GskSlImageType *
gsk_sl_type_scalar_get_image_type (const GskSlType *type)
{
return NULL;
}
static GskSlType *
gsk_sl_type_scalar_get_index_type (const GskSlType *type)
{
return NULL;
}
static gsize
gsk_sl_type_scalar_get_index_stride (const GskSlType *type)
{
return 0;
}
static guint
gsk_sl_type_scalar_get_length (const GskSlType *type)
{
return 0;
}
static gsize
gsk_sl_type_scalar_get_size (const GskSlType *type)
{
const GskSlTypeScalar *scalar = (const GskSlTypeScalar *) type;
return scalar_infos[scalar->scalar].size;
}
static gsize
gsk_sl_type_scalar_get_n_components (const GskSlType *type)
{
return 1;
}
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)
{
const GskSlTypeScalar *target_scalar = (const GskSlTypeScalar *) target;
const GskSlTypeScalar *source_scalar = (const GskSlTypeScalar *) source;
if (target->class != source->class)
return FALSE;
return gsk_sl_scalar_type_can_convert (target_scalar->scalar, source_scalar->scalar);
}
static guint32
gsk_sl_type_scalar_write_spv (GskSlType *type,
GskSpvWriter *writer)
{
GskSlTypeScalar *scalar = (GskSlTypeScalar *) type;
switch (scalar->scalar)
{
case GSK_SL_FLOAT:
return gsk_spv_writer_type_float (writer, 32);
case GSK_SL_DOUBLE:
return gsk_spv_writer_type_float (writer, 64);
case GSK_SL_INT:
return gsk_spv_writer_type_int (writer, 32, 1);
case GSK_SL_UINT:
return gsk_spv_writer_type_int (writer, 32, 0);
case GSK_SL_BOOL:
return gsk_spv_writer_type_bool (writer);
case GSK_SL_VOID:
default:
g_assert_not_reached ();
return 0;
}
}
static void
gsk_sl_type_scalar_print_value (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value)
{
const GskSlTypeScalar *scalar = (const GskSlTypeScalar *) type;
scalar_infos[scalar->scalar].print_value (printer, value);
}
static gboolean
gsk_sl_type_scalar_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b)
{
GskSlTypeScalar *scalar = (GskSlTypeScalar *) type;
return scalar_infos[scalar->scalar].value_equal (a, b);
}
static guint32
gsk_sl_type_scalar_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value)
{
GskSlTypeScalar *scalar = (GskSlTypeScalar *) type;
return scalar_infos[scalar->scalar].write_value_spv (writer, value);
}
static const GskSlTypeClass GSK_SL_TYPE_SCALAR = {
gsk_sl_type_scalar_free,
gsk_sl_type_scalar_get_name,
gsk_sl_type_scalar_get_scalar_type,
gsk_sl_type_scalar_get_image_type,
gsk_sl_type_scalar_get_index_type,
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_components,
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,
gsk_sl_type_scalar_value_equal,
gsk_sl_type_scalar_write_value_spv
};
/* VECTOR */
typedef struct _GskSlTypeVector GskSlTypeVector;
struct _GskSlTypeVector {
GskSlType parent;
const char *name;
GskSlScalarType scalar;
guint length;
};
static void
gsk_sl_type_vector_free (GskSlType *type)
{
g_assert_not_reached ();
}
static const char *
gsk_sl_type_vector_get_name (const GskSlType *type)
{
const GskSlTypeVector *vector = (const GskSlTypeVector *) type;
return vector->name;
}
static GskSlScalarType
gsk_sl_type_vector_get_scalar_type (const GskSlType *type)
{
const GskSlTypeVector *vector = (const GskSlTypeVector *) type;
return vector->scalar;
}
static const GskSlImageType *
gsk_sl_type_vector_get_image_type (const GskSlType *type)
{
return NULL;
}
static GskSlType *
gsk_sl_type_vector_get_index_type (const GskSlType *type)
{
const GskSlTypeVector *vector = (const GskSlTypeVector *) type;
return gsk_sl_type_get_scalar (vector->scalar);
}
static gsize
gsk_sl_type_vector_get_index_stride (const GskSlType *type)
{
const GskSlTypeVector *vector = (const GskSlTypeVector *) type;
return scalar_infos[vector->scalar].size;
}
static guint
gsk_sl_type_vector_get_length (const GskSlType *type)
{
GskSlTypeVector *vector = (GskSlTypeVector *) type;
return vector->length;
}
static gsize
gsk_sl_type_vector_get_size (const GskSlType *type)
{
const GskSlTypeVector *vector = (const GskSlTypeVector *) type;
return vector->length * scalar_infos[vector->scalar].size;
}
static gsize
gsk_sl_type_vector_get_n_components (const GskSlType *type)
{
const GskSlTypeVector *vector = (const GskSlTypeVector *) type;
return vector->length;
}
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)
{
const GskSlTypeVector *target_vector = (const GskSlTypeVector *) target;
const GskSlTypeVector *source_vector = (const GskSlTypeVector *) source;
if (target->class != source->class)
return FALSE;
if (target_vector->length != source_vector->length)
return FALSE;
return gsk_sl_scalar_type_can_convert (target_vector->scalar, source_vector->scalar);
}
static guint32
gsk_sl_type_vector_write_spv (GskSlType *type,
GskSpvWriter *writer)
{
GskSlTypeVector *vector = (GskSlTypeVector *) type;
return gsk_spv_writer_type_vector (writer,
gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (vector->scalar)),
vector->length);
}
static void
gsk_sl_type_vector_print_value (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value)
{
const GskSlTypeVector *vector = (const GskSlTypeVector *) type;
guint i;
const guchar *data;
data = value;
gsk_sl_printer_append (printer, vector->name);
gsk_sl_printer_append (printer, "(");
for (i = 0; i < vector->length; i++)
{
if (i > 0)
gsk_sl_printer_append (printer, ", ");
scalar_infos[vector->scalar].print_value (printer, data);
data += scalar_infos[vector->scalar].size;
}
gsk_sl_printer_append (printer, ")");
}
static gboolean
gsk_sl_type_vector_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b)
{
GskSlTypeVector *vector = (GskSlTypeVector *) type;
guint i;
const guchar *adata, *bdata;
adata = a;
bdata = b;
for (i = 0; i < vector->length; i++)
{
if (!scalar_infos[vector->scalar].value_equal (adata, bdata))
return FALSE;
adata += scalar_infos[vector->scalar].size;
bdata += scalar_infos[vector->scalar].size;
}
return TRUE;
}
static guint32
gsk_sl_type_vector_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value)
{
GskSlTypeVector *vector = (GskSlTypeVector *) type;
guint32 ids[vector->length];
GskSlType *scalar_type;
GskSlValue *v;
const guchar *data;
guint i;
data = value;
scalar_type = gsk_sl_type_get_scalar (vector->scalar);
for (i = 0; i < vector->length; i++)
{
v = gsk_sl_value_new_for_data (scalar_type, (gpointer) data, NULL, NULL);
ids[i] = gsk_spv_writer_get_id_for_value (writer, v);
gsk_sl_value_free (v);
data += scalar_infos[vector->scalar].size;
}
return gsk_spv_writer_constant_composite (writer,
type,
ids,
vector->length);
}
static const GskSlTypeClass GSK_SL_TYPE_VECTOR = {
gsk_sl_type_vector_free,
gsk_sl_type_vector_get_name,
gsk_sl_type_vector_get_scalar_type,
gsk_sl_type_vector_get_image_type,
gsk_sl_type_vector_get_index_type,
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_components,
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,
gsk_sl_type_vector_value_equal,
gsk_sl_type_vector_write_value_spv
};
/* MATRIX */
typedef struct _GskSlTypeMatrix GskSlTypeMatrix;
struct _GskSlTypeMatrix {
GskSlType parent;
const char *name;
GskSlScalarType scalar;
guint columns;
guint rows;
};
static void
gsk_sl_type_matrix_free (GskSlType *type)
{
g_assert_not_reached ();
}
static const char *
gsk_sl_type_matrix_get_name (const GskSlType *type)
{
const GskSlTypeMatrix *matrix = (const GskSlTypeMatrix *) type;
return matrix->name;
}
static GskSlScalarType
gsk_sl_type_matrix_get_scalar_type (const GskSlType *type)
{
const GskSlTypeMatrix *matrix = (const GskSlTypeMatrix *) type;
return matrix->scalar;
}
static const GskSlImageType *
gsk_sl_type_matrix_get_image_type (const GskSlType *type)
{
return NULL;
}
static GskSlType *
gsk_sl_type_matrix_get_index_type (const GskSlType *type)
{
const GskSlTypeMatrix *matrix = (const GskSlTypeMatrix *) type;
return gsk_sl_type_get_vector (matrix->scalar, matrix->rows);
}
static gsize
gsk_sl_type_matrix_get_index_stride (const GskSlType *type)
{
const GskSlTypeMatrix *matrix = (const GskSlTypeMatrix *) type;
return scalar_infos[matrix->scalar].size * matrix->rows;
}
static guint
gsk_sl_type_matrix_get_length (const GskSlType *type)
{
GskSlTypeMatrix *matrix = (GskSlTypeMatrix *) type;
return matrix->columns;
}
static gsize
gsk_sl_type_matrix_get_size (const GskSlType *type)
{
const GskSlTypeMatrix *matrix = (const GskSlTypeMatrix *) type;
return matrix->columns * matrix->rows * scalar_infos[matrix->scalar].size;
}
static gsize
gsk_sl_type_matrix_get_n_components (const GskSlType *type)
{
const GskSlTypeMatrix *matrix = (const GskSlTypeMatrix *) type;
return matrix->columns * matrix->rows;
}
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)
{
const GskSlTypeMatrix *target_matrix = (const GskSlTypeMatrix *) target;
const GskSlTypeMatrix *source_matrix = (const GskSlTypeMatrix *) source;
if (target->class != source->class)
return FALSE;
if (target_matrix->rows != source_matrix->rows ||
target_matrix->columns != source_matrix->columns)
return FALSE;
return gsk_sl_scalar_type_can_convert (target_matrix->scalar, source_matrix->scalar);
}
static guint32
gsk_sl_type_matrix_write_spv (GskSlType *type,
GskSpvWriter *writer)
{
GskSlTypeMatrix *matrix = (GskSlTypeMatrix *) type;
return gsk_spv_writer_type_matrix (writer,
gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_index_type (type)),
matrix->columns);
}
static void
gsk_sl_type_matrix_print_value (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value)
{
const GskSlTypeMatrix *matrix = (const GskSlTypeMatrix *) type;
guint i;
const guchar *data;
data = value;
gsk_sl_printer_append (printer, matrix->name);
gsk_sl_printer_append (printer, "(");
for (i = 0; i < matrix->rows * matrix->columns; i++)
{
if (i > 0)
gsk_sl_printer_append (printer, ", ");
scalar_infos[matrix->scalar].print_value (printer, data);
data += scalar_infos[matrix->scalar].size;
}
gsk_sl_printer_append (printer, ")");
}
static gboolean
gsk_sl_type_matrix_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b)
{
GskSlTypeMatrix *matrix = (GskSlTypeMatrix *) type;
guint i;
const guchar *adata, *bdata;
adata = a;
bdata = b;
for (i = 0; i < matrix->rows * matrix->columns; i++)
{
if (!scalar_infos[matrix->scalar].value_equal (adata, bdata))
return FALSE;
adata += scalar_infos[matrix->scalar].size;
bdata += scalar_infos[matrix->scalar].size;
}
return TRUE;
}
static guint32
gsk_sl_type_matrix_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value)
{
GskSlTypeMatrix *matrix = (GskSlTypeMatrix *) type;
guint32 ids[matrix->rows];
GskSlType *vector_type;
GskSlValue *v;
const guchar *data;
guint i;
data = value;
vector_type = gsk_sl_type_get_index_type (type);
for (i = 0; i < matrix->columns; i++)
{
v = gsk_sl_value_new_for_data (vector_type, (gpointer) data, NULL, NULL);
ids[i] = gsk_spv_writer_get_id_for_value (writer, v);
gsk_sl_value_free (v);
data += gsk_sl_type_get_size (vector_type);
}
return gsk_spv_writer_constant_composite (writer,
type,
ids,
matrix->columns);
}
static const GskSlTypeClass GSK_SL_TYPE_MATRIX = {
gsk_sl_type_matrix_free,
gsk_sl_type_matrix_get_name,
gsk_sl_type_matrix_get_scalar_type,
gsk_sl_type_matrix_get_image_type,
gsk_sl_type_matrix_get_index_type,
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_components,
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,
gsk_sl_type_matrix_value_equal,
gsk_sl_type_matrix_write_value_spv
};
/* ARRAY */
typedef struct _GskSlTypeArray GskSlTypeArray;
struct _GskSlTypeArray {
GskSlType parent;
char *name;
GskSlType *type;
gsize length;
};
static void
gsk_sl_type_array_free (GskSlType *type)
{
GskSlTypeArray *array = (GskSlTypeArray *) type;
gsk_sl_type_unref (array->type);
g_free (array->name);
g_slice_free (GskSlTypeArray, array);
}
static const char *
gsk_sl_type_array_get_name (const GskSlType *type)
{
const GskSlTypeArray *array = (const GskSlTypeArray *) type;
return array->name;
}
static GskSlScalarType
gsk_sl_type_array_get_scalar_type (const GskSlType *type)
{
const GskSlTypeArray *array = (const GskSlTypeArray *) type;
return gsk_sl_type_get_scalar_type (array->type);
}
static const GskSlImageType *
gsk_sl_type_array_get_image_type (const GskSlType *type)
{
return NULL;
}
static GskSlType *
gsk_sl_type_array_get_index_type (const GskSlType *type)
{
const GskSlTypeArray *array = (const GskSlTypeArray *) type;
return array->type;
}
static gsize
gsk_sl_type_array_get_index_stride (const GskSlType *type)
{
const GskSlTypeArray *array = (const GskSlTypeArray *) type;
return gsk_sl_type_get_size (array->type);
}
static guint
gsk_sl_type_array_get_length (const GskSlType *type)
{
const GskSlTypeArray *array = (const GskSlTypeArray *) type;
return array->length;
}
static gsize
gsk_sl_type_array_get_size (const GskSlType *type)
{
const GskSlTypeArray *array = (const GskSlTypeArray *) type;
return array->length * gsk_sl_type_get_size (array->type);
}
static gsize
gsk_sl_type_array_get_n_components (const GskSlType *type)
{
const GskSlTypeArray *array = (const GskSlTypeArray *) type;
return gsk_sl_type_array_get_n_components (array->type) * array->length;
}
static guint
gsk_sl_type_array_get_n_members (const GskSlType *type)
{
return 0;
}
static const GskSlTypeMember *
gsk_sl_type_array_get_member (const GskSlType *type,
guint n)
{
return NULL;
}
static gboolean
gsk_sl_type_array_can_convert (const GskSlType *target,
const GskSlType *source)
{
return gsk_sl_type_equal (target, source);
}
static guint32
gsk_sl_type_array_write_spv (GskSlType *type,
GskSpvWriter *writer)
{
GskSlTypeArray *array = (GskSlTypeArray *) type;
GskSlValue *value;
guint32 type_id, length_id;
type_id = gsk_spv_writer_get_id_for_type (writer, array->type);
value = gsk_sl_value_new (gsk_sl_type_get_scalar (GSK_SL_INT));
*(gint32 *) gsk_sl_value_get_data (value) = array->length;
length_id = gsk_spv_writer_get_id_for_value (writer, value);
gsk_sl_value_free (value);
return gsk_spv_writer_type_array (writer,
type_id,
length_id);
}
static void
gsk_sl_type_array_print_value (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value)
{
GskSlTypeArray *array = (GskSlTypeArray *) type;
gsize i, stride;
const guchar *data;
data = value;
stride = gsk_sl_type_array_get_index_stride (type);
gsk_sl_printer_append (printer, array->name);
gsk_sl_printer_append (printer, " (");
for (i = 0; i < array->length; i++)
{
if (i > 0)
gsk_sl_printer_append (printer, ", ");
gsk_sl_type_print_value (array->type, printer, data + i * stride);
}
gsk_sl_printer_append (printer, ")");
}
static gboolean
gsk_sl_type_array_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b)
{
GskSlTypeArray *array = (GskSlTypeArray *) type;
gsize i, stride;
const guchar *adata;
const guchar *bdata;
adata = a;
bdata = b;
stride = gsk_sl_type_array_get_index_stride (type);
for (i = 0; i < array->length; i++)
{
if (!gsk_sl_type_value_equal (array->type, adata + i * stride, bdata + i * stride))
return FALSE;
}
return TRUE;
}
static guint32
gsk_sl_type_array_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value)
{
GskSlTypeArray *array = (GskSlTypeArray *) type;
guint32 value_ids[array->length];
gsize i, stride;
const guchar *data;
data = value;
stride = gsk_sl_type_array_get_index_stride (type);
for (i = 0; i < array->length; i++)
{
value_ids[i] = gsk_sl_type_write_value_spv (array->type, writer, data + i * stride);
}
return gsk_spv_writer_constant_composite (writer,
type,
value_ids,
array->length);
}
static const GskSlTypeClass GSK_SL_TYPE_ARRAY = {
gsk_sl_type_array_free,
gsk_sl_type_array_get_name,
gsk_sl_type_array_get_scalar_type,
gsk_sl_type_array_get_image_type,
gsk_sl_type_array_get_index_type,
gsk_sl_type_array_get_index_stride,
gsk_sl_type_array_get_length,
gsk_sl_type_array_get_size,
gsk_sl_type_array_get_n_components,
gsk_sl_type_array_get_n_members,
gsk_sl_type_array_get_member,
gsk_sl_type_array_can_convert,
gsk_sl_type_array_write_spv,
gsk_sl_type_array_print_value,
gsk_sl_type_array_value_equal,
gsk_sl_type_array_write_value_spv
};
/* SAMPLER */
typedef struct _GskSlTypeSampler GskSlTypeSampler;
struct _GskSlTypeSampler {
GskSlType parent;
const char *name;
GskSlSamplerType sampler;
GskSlImageType image_type;
};
static void
gsk_sl_type_sampler_free (GskSlType *type)
{
g_assert_not_reached ();
}
static const char *
gsk_sl_type_sampler_get_name (const GskSlType *type)
{
const GskSlTypeSampler *sampler = (const GskSlTypeSampler *) type;
return sampler->name;
}
static GskSlScalarType
gsk_sl_type_sampler_get_scalar_type (const GskSlType *type)
{
return GSK_SL_VOID;
}
static const GskSlImageType *
gsk_sl_type_sampler_get_image_type (const GskSlType *type)
{
const GskSlTypeSampler *sampler = (const GskSlTypeSampler *) type;
return &sampler->image_type;
}
static GskSlType *
gsk_sl_type_sampler_get_index_type (const GskSlType *type)
{
return NULL;
}
static gsize
gsk_sl_type_sampler_get_index_stride (const GskSlType *type)
{
return 0;
}
static guint
gsk_sl_type_sampler_get_length (const GskSlType *type)
{
return 0;
}
static gsize
gsk_sl_type_sampler_get_size (const GskSlType *type)
{
/* XXX: setting this to 0 would make it not work in GskSlValue */
return sizeof (gpointer);
}
static gsize
gsk_sl_type_sampler_get_n_components (const GskSlType *type)
{
return 1;
}
static guint
gsk_sl_type_sampler_get_n_members (const GskSlType *type)
{
return 0;
}
static const GskSlTypeMember *
gsk_sl_type_sampler_get_member (const GskSlType *type,
guint n)
{
return NULL;
}
static gboolean
gsk_sl_type_sampler_can_convert (const GskSlType *target,
const GskSlType *source)
{
return gsk_sl_type_equal (target, source);
}
static guint32
gsk_sl_type_sampler_write_spv (GskSlType *type,
GskSpvWriter *writer)
{
GskSlTypeSampler *sampler = (GskSlTypeSampler *) type;
guint32 image_id;
image_id = gsk_spv_writer_get_id_for_image_type (writer, &sampler->image_type);
return gsk_spv_writer_type_sampled_image (writer, image_id);
}
static void
gsk_sl_type_sampler_print_value (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value)
{
g_assert_not_reached ();
}
static gboolean
gsk_sl_type_sampler_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b)
{
return *(gconstpointer *) a == *(gconstpointer *) b;
}
static guint32
gsk_sl_type_sampler_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value)
{
g_assert_not_reached ();
}
static const GskSlTypeClass GSK_SL_TYPE_SAMPLER = {
gsk_sl_type_sampler_free,
gsk_sl_type_sampler_get_name,
gsk_sl_type_sampler_get_scalar_type,
gsk_sl_type_sampler_get_image_type,
gsk_sl_type_sampler_get_index_type,
gsk_sl_type_sampler_get_index_stride,
gsk_sl_type_sampler_get_length,
gsk_sl_type_sampler_get_size,
gsk_sl_type_sampler_get_n_components,
gsk_sl_type_sampler_get_n_members,
gsk_sl_type_sampler_get_member,
gsk_sl_type_sampler_can_convert,
gsk_sl_type_sampler_write_spv,
gsk_sl_type_sampler_print_value,
gsk_sl_type_sampler_value_equal,
gsk_sl_type_sampler_write_value_spv
};
/* STRUCT */
typedef struct _GskSlTypeStruct GskSlTypeStruct;
struct _GskSlTypeStruct {
GskSlType parent;
char *name;
gsize size;
GskSlTypeMember *members;
guint n_members;
};
static void
gsk_sl_type_struct_free (GskSlType *type)
{
GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
guint i;
for (i = 0; i < struc->n_members; i++)
{
gsk_sl_type_unref (struc->members[i].type);
g_free (struc->members[i].name);
}
g_free (struc->members);
g_free (struc->name);
g_slice_free (GskSlTypeStruct, struc);
}
static const char *
gsk_sl_type_struct_get_name (const GskSlType *type)
{
const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type;
return struc->name;
}
static GskSlScalarType
gsk_sl_type_struct_get_scalar_type (const GskSlType *type)
{
return GSK_SL_VOID;
}
static const GskSlImageType *
gsk_sl_type_struct_get_image_type (const GskSlType *type)
{
return NULL;
}
static GskSlType *
gsk_sl_type_struct_get_index_type (const GskSlType *type)
{
return NULL;
}
static gsize
gsk_sl_type_struct_get_index_stride (const GskSlType *type)
{
return 0;
}
static guint
gsk_sl_type_struct_get_length (const GskSlType *type)
{
return 0;
}
static gsize
gsk_sl_type_struct_get_size (const GskSlType *type)
{
const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type;
return struc->size;
}
static gsize
gsk_sl_type_struct_get_n_components (const GskSlType *type)
{
return 0;
}
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 (const GskSlType *target,
const GskSlType *source)
{
return gsk_sl_type_equal (target, source);
}
static gboolean
gsk_sl_type_struct_has_name (const GskSlTypeStruct *struc)
{
return !g_str_has_prefix (struc->name, "struct { ");
}
static void
gsk_sl_type_write_member_decoration (GskSpvWriter *writer,
guint32 type_id,
gsize index,
GskSlType *member_type,
const char *member_name,
gsize member_offset)
{
gsk_spv_writer_member_name (writer, type_id, index, member_name);
gsk_spv_writer_member_decorate (writer, type_id, index,
GSK_SPV_DECORATION_OFFSET,
(guint32[1]) { member_offset }, 1);
if (gsk_sl_type_is_matrix (member_type))
{
gsk_spv_writer_member_decorate (writer, type_id, index,
GSK_SPV_DECORATION_COL_MAJOR,
NULL, 0);
gsk_spv_writer_member_decorate (writer, type_id, index,
GSK_SPV_DECORATION_MATRIX_STRIDE,
(guint32[1]) { gsk_sl_type_get_size (gsk_sl_type_get_index_type (member_type)) }, 1);
}
}
static guint32
gsk_sl_type_struct_write_spv (GskSlType *type,
GskSpvWriter *writer)
{
GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
guint32 ids[struc->n_members];
guint32 result_id;
guint i;
for (i = 0; i < struc->n_members; i++)
{
ids[i] = gsk_spv_writer_get_id_for_type (writer, struc->members[i].type);
}
result_id = gsk_spv_writer_type_struct (writer,
ids,
struc->n_members);
if (gsk_sl_type_struct_has_name (struc))
gsk_spv_writer_name (writer, result_id, struc->name);
else
gsk_spv_writer_name (writer, result_id, "");
for (i = 0; i < struc->n_members; i++)
{
gsk_sl_type_write_member_decoration (writer, result_id, i, struc->members[i].type,
struc->members[i].name, struc->members[i].offset);
}
return result_id;
}
static void
gsk_sl_type_struct_print_value (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value)
{
const GskSlTypeStruct *struc = (const GskSlTypeStruct *) type;
guint i;
gsk_sl_printer_append (printer, struc->name);
gsk_sl_printer_append (printer, "(");
for (i = 0; i < struc->n_members; i++)
{
if (i > 0)
gsk_sl_printer_append (printer, ", ");
gsk_sl_type_print_value (struc->members[i].type,
printer,
(guchar *) value + struc->members[i].offset);
}
gsk_sl_printer_append (printer, ")");
}
static gboolean
gsk_sl_type_struct_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b)
{
GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
guint i;
const guchar *adata, *bdata;
adata = a;
bdata = b;
for (i = 0; i < struc->n_members; i++)
{
if (!gsk_sl_type_value_equal (struc->members[i].type,
adata + struc->members[i].offset,
bdata + struc->members[i].offset))
return FALSE;
}
return TRUE;
}
static guint32
gsk_sl_type_struct_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value)
{
GskSlTypeStruct *struc = (GskSlTypeStruct *) type;
guint32 ids[struc->n_members];
GskSlValue *v;
guint i;
for (i = 0; i < struc->n_members; i++)
{
v = gsk_sl_value_new_for_data (struc->members[i].type,
(guchar *) value + struc->members[i].offset,
NULL, NULL);
ids[i] = gsk_spv_writer_get_id_for_value (writer, v);
gsk_sl_value_free (v);
}
return gsk_spv_writer_constant_composite (writer,
type,
ids,
struc->n_members);
}
static const GskSlTypeClass GSK_SL_TYPE_STRUCT = {
gsk_sl_type_struct_free,
gsk_sl_type_struct_get_name,
gsk_sl_type_struct_get_scalar_type,
gsk_sl_type_struct_get_image_type,
gsk_sl_type_struct_get_index_type,
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_components,
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,
gsk_sl_type_struct_value_equal,
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 const GskSlImageType *
gsk_sl_type_block_get_image_type (const GskSlType *type)
{
return NULL;
}
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 gsize
gsk_sl_type_block_get_n_components (const GskSlType *type)
{
return 0;
}
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], result_id;
guint i;
for (i = 0; i < block->n_members; i++)
{
ids[i] = gsk_spv_writer_get_id_for_type (writer, block->members[i].type);
}
result_id = gsk_spv_writer_type_struct (writer,
ids,
block->n_members);
gsk_spv_writer_decorate (writer, result_id, GSK_SPV_DECORATION_BLOCK, NULL, 0);
for (i = 0; i < block->n_members; i++)
{
gsk_sl_type_write_member_decoration (writer, result_id, i, block->members[i].type,
block->members[i].name, block->members[i].offset);
}
return result_id;
}
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 gboolean
gsk_sl_type_block_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b)
{
GskSlTypeBlock *block = (GskSlTypeBlock *) type;
guint i;
const guchar *adata, *bdata;
adata = a;
bdata = b;
for (i = 0; i < block->n_members; i++)
{
if (!gsk_sl_type_value_equal (block->members[i].type,
adata + block->members[i].offset,
bdata + block->members[i].offset))
return FALSE;
}
return TRUE;
}
static guint32
gsk_sl_type_block_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value)
{
GskSlTypeBlock *block = (GskSlTypeBlock *) type;
guint32 ids[block->n_members];
GskSlValue *v;
guint i;
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[i] = gsk_spv_writer_get_id_for_value (writer, v);
gsk_sl_value_free (v);
}
return gsk_spv_writer_constant_composite (writer,
type,
ids,
block->n_members);
}
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_image_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_components,
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_value_equal,
gsk_sl_type_block_write_value_spv
};
/* API */
gsize
gsk_sl_scalar_type_get_size (GskSlScalarType type)
{
return scalar_infos[type].size;
}
static GskSlType *
gsk_sl_type_parse_struct (GskSlScope *scope,
GskSlPreprocessor *preproc)
{
GskSlType *type;
const GskSlToken *token;
GskSlTypeBuilder *builder;
gboolean add_type = FALSE;
/* the struct token */
gsk_sl_preprocessor_consume (preproc, NULL);
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
if (gsk_sl_scope_is_global (scope))
{
add_type = TRUE;
builder = gsk_sl_type_builder_new_struct (token->str);
}
else
{
builder = gsk_sl_type_builder_new_struct (NULL);
}
gsk_sl_preprocessor_consume (preproc, NULL);
}
else
{
builder = gsk_sl_type_builder_new_struct (NULL);
}
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 struct 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 struct 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 struct declaration.");
else
gsk_sl_preprocessor_consume (preproc, NULL);
out:
type = gsk_sl_type_builder_free (builder);
if (add_type)
{
if (gsk_sl_scope_lookup_type (scope, gsk_sl_type_get_name (type)))
gsk_sl_preprocessor_error (preproc, DECLARATION, "Redefinition of struct \"%s\".", gsk_sl_type_get_name (type));
else
{
GskSlFunctionMatcher matcher;
gsk_sl_scope_match_function (scope, &matcher, gsk_sl_type_get_name (type));
if (gsk_sl_function_matcher_has_matches (&matcher))
gsk_sl_preprocessor_error (preproc, DECLARATION, "Constructor name \"%s\" would override function of same name.", gsk_sl_type_get_name (type));
else
gsk_sl_scope_add_type (scope, type);
gsk_sl_function_matcher_finish (&matcher);
}
}
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_matching (GskSlType *type,
GskSlScalarType scalar)
{
if (gsk_sl_type_is_scalar (type))
return gsk_sl_type_get_scalar (scalar);
else if (gsk_sl_type_is_vector (type))
return gsk_sl_type_get_vector (scalar, gsk_sl_type_get_length (type));
else if (gsk_sl_type_is_matrix (type))
return gsk_sl_type_get_matrix (scalar,
gsk_sl_type_get_length (type),
gsk_sl_type_get_length (gsk_sl_type_get_index_type (type)));
else
{
g_return_val_if_reached (gsk_sl_type_get_void ());
}
}
static char *
gsk_sl_array_type_generate_name (GskSlType *type)
{
GString *string = g_string_new (NULL);
for (; gsk_sl_type_is_array (type); type = gsk_sl_type_get_index_type (type))
{
g_string_append_printf (string, "[%u]", gsk_sl_type_get_length (type));
}
g_string_prepend (string, gsk_sl_type_get_name (type));
return g_string_free (string, FALSE);
}
GskSlType *
gsk_sl_type_new_array (GskSlType *type,
gsize length)
{
GskSlTypeArray *result;
result = gsk_sl_type_new (GskSlTypeArray, &GSK_SL_TYPE_ARRAY);
result->type = gsk_sl_type_ref (type);
result->length = length;
result->name = gsk_sl_array_type_generate_name (&result->parent);
return &result->parent;
}
GskSlType *
gsk_sl_type_parse_array (GskSlType *type,
GskSlScope *scope,
GskSlPreprocessor *preproc)
{
GskSlType *array;
const GskSlToken *token;
gsize length;
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACKET))
return type;
gsk_sl_preprocessor_consume (preproc, NULL);
length = gsk_sl_expression_parse_integral_constant (scope, preproc, 1, G_MAXINT);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACKET))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected closing \"]\"");
return type;
}
gsk_sl_preprocessor_consume (preproc, NULL);
type = gsk_sl_type_parse_array (type, scope, preproc);
array = gsk_sl_type_new_array (type, length);
gsk_sl_type_unref (type);
return array;
}
GskSlType *
gsk_sl_type_new_parse (GskSlScope *scope,
GskSlPreprocessor *preproc)
{
GskSlType *type;
const GskSlToken *token;
token = gsk_sl_preprocessor_get (preproc);
switch ((guint) token->type)
{
case GSK_SL_TOKEN_VOID:
type = gsk_sl_type_ref (gsk_sl_type_get_void ());
break;
case GSK_SL_TOKEN_FLOAT:
type = gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
break;
case GSK_SL_TOKEN_DOUBLE:
type = gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_DOUBLE));
break;
case GSK_SL_TOKEN_INT:
type = gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_INT));
break;
case GSK_SL_TOKEN_UINT:
type = gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_UINT));
break;
case GSK_SL_TOKEN_BOOL:
type = gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_BOOL));
break;
case GSK_SL_TOKEN_BVEC2:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_BOOL, 2));
break;
case GSK_SL_TOKEN_BVEC3:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_BOOL, 3));
break;
case GSK_SL_TOKEN_BVEC4:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_BOOL, 4));
break;
case GSK_SL_TOKEN_IVEC2:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_INT, 2));
break;
case GSK_SL_TOKEN_IVEC3:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_INT, 3));
break;
case GSK_SL_TOKEN_IVEC4:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_INT, 4));
break;
case GSK_SL_TOKEN_UVEC2:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_UINT, 2));
break;
case GSK_SL_TOKEN_UVEC3:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_UINT, 3));
break;
case GSK_SL_TOKEN_UVEC4:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_UINT, 4));
break;
case GSK_SL_TOKEN_VEC2:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_FLOAT, 2));
break;
case GSK_SL_TOKEN_VEC3:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_FLOAT, 3));
break;
case GSK_SL_TOKEN_VEC4:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_FLOAT, 4));
break;
case GSK_SL_TOKEN_DVEC2:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_DOUBLE, 2));
break;
case GSK_SL_TOKEN_DVEC3:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_DOUBLE, 3));
break;
case GSK_SL_TOKEN_DVEC4:
type = gsk_sl_type_ref (gsk_sl_type_get_vector (GSK_SL_DOUBLE, 4));
break;
case GSK_SL_TOKEN_MAT2:
case GSK_SL_TOKEN_MAT2X2:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 2, 2));
break;
case GSK_SL_TOKEN_MAT2X3:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 2, 3));
break;
case GSK_SL_TOKEN_MAT2X4:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 2, 4));
break;
case GSK_SL_TOKEN_MAT3X2:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 3, 2));
break;
case GSK_SL_TOKEN_MAT3:
case GSK_SL_TOKEN_MAT3X3:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 3, 3));
break;
case GSK_SL_TOKEN_MAT3X4:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 3, 4));
break;
case GSK_SL_TOKEN_MAT4X2:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 4, 2));
break;
case GSK_SL_TOKEN_MAT4X3:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 4, 3));
break;
case GSK_SL_TOKEN_MAT4:
case GSK_SL_TOKEN_MAT4X4:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_FLOAT, 4, 4));
break;
case GSK_SL_TOKEN_DMAT2:
case GSK_SL_TOKEN_DMAT2X2:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 2, 2));
break;
case GSK_SL_TOKEN_DMAT2X3:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 2, 3));
break;
case GSK_SL_TOKEN_DMAT2X4:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 2, 4));
break;
case GSK_SL_TOKEN_DMAT3X2:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 3, 2));
break;
case GSK_SL_TOKEN_DMAT3:
case GSK_SL_TOKEN_DMAT3X3:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 3, 3));
break;
case GSK_SL_TOKEN_DMAT3X4:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 3, 4));
break;
case GSK_SL_TOKEN_DMAT4X2:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 4, 2));
break;
case GSK_SL_TOKEN_DMAT4X3:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 4, 3));
break;
case GSK_SL_TOKEN_DMAT4:
case GSK_SL_TOKEN_DMAT4X4:
type = gsk_sl_type_ref (gsk_sl_type_get_matrix (GSK_SL_DOUBLE, 4, 4));
break;
case GSK_SL_TOKEN_SAMPLER1D:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_1D));
break;
case GSK_SL_TOKEN_SAMPLER2D:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D));
break;
case GSK_SL_TOKEN_SAMPLER3D:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_3D));
break;
case GSK_SL_TOKEN_SAMPLERCUBE:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_CUBE));
break;
case GSK_SL_TOKEN_SAMPLER1DSHADOW:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_1D_SHADOW));
break;
case GSK_SL_TOKEN_SAMPLER2DSHADOW:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_SHADOW));
break;
case GSK_SL_TOKEN_SAMPLERCUBESHADOW:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_CUBE_SHADOW));
break;
case GSK_SL_TOKEN_SAMPLER1DARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_1D_ARRAY));
break;
case GSK_SL_TOKEN_SAMPLER2DARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_ARRAY));
break;
case GSK_SL_TOKEN_SAMPLER1DARRAYSHADOW:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_1D_ARRAY_SHADOW));
break;
case GSK_SL_TOKEN_SAMPLER2DARRAYSHADOW:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_ARRAY_SHADOW));
break;
case GSK_SL_TOKEN_ISAMPLER1D:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_1D_INT));
break;
case GSK_SL_TOKEN_ISAMPLER2D:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_INT));
break;
case GSK_SL_TOKEN_ISAMPLER3D:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_3D_INT));
break;
case GSK_SL_TOKEN_ISAMPLERCUBE:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_CUBE_INT));
break;
case GSK_SL_TOKEN_ISAMPLER1DARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_1D_ARRAY_INT));
break;
case GSK_SL_TOKEN_ISAMPLER2DARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_ARRAY_INT));
break;
case GSK_SL_TOKEN_USAMPLER1D:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_1D_UINT));
break;
case GSK_SL_TOKEN_USAMPLER2D:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_UINT));
break;
case GSK_SL_TOKEN_USAMPLER3D:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_3D_UINT));
break;
case GSK_SL_TOKEN_USAMPLERCUBE:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_CUBE_UINT));
break;
case GSK_SL_TOKEN_USAMPLER1DARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_1D_ARRAY_UINT));
break;
case GSK_SL_TOKEN_USAMPLER2DARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_ARRAY_UINT));
break;
case GSK_SL_TOKEN_SAMPLER2DRECT:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_RECT));
break;
case GSK_SL_TOKEN_SAMPLER2DRECTSHADOW:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_RECT_SHADOW));
break;
case GSK_SL_TOKEN_ISAMPLER2DRECT:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_RECT_INT));
break;
case GSK_SL_TOKEN_USAMPLER2DRECT:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2D_RECT_UINT));
break;
case GSK_SL_TOKEN_SAMPLERBUFFER:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_BUFFER));
break;
case GSK_SL_TOKEN_ISAMPLERBUFFER:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_BUFFER_INT));
break;
case GSK_SL_TOKEN_USAMPLERBUFFER:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_BUFFER_UINT));
break;
case GSK_SL_TOKEN_SAMPLERCUBEARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_CUBE_ARRAY));
break;
case GSK_SL_TOKEN_SAMPLERCUBEARRAYSHADOW:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_CUBE_ARRAY_SHADOW));
break;
case GSK_SL_TOKEN_ISAMPLERCUBEARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_CUBE_ARRAY_INT));
break;
case GSK_SL_TOKEN_USAMPLERCUBEARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_CUBE_ARRAY_UINT));
break;
case GSK_SL_TOKEN_SAMPLER2DMS:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2DMS));
break;
case GSK_SL_TOKEN_ISAMPLER2DMS:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2DMS_INT));
break;
case GSK_SL_TOKEN_USAMPLER2DMS:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2DMS_UINT));
break;
case GSK_SL_TOKEN_SAMPLER2DMSARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2DMS_ARRAY));
break;
case GSK_SL_TOKEN_ISAMPLER2DMSARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2DMS_ARRAY_INT));
break;
case GSK_SL_TOKEN_USAMPLER2DMSARRAY:
type = gsk_sl_type_ref (gsk_sl_type_get_sampler (GSK_SL_SAMPLER_2DMS_ARRAY_UINT));
break;
case GSK_SL_TOKEN_STRUCT:
return gsk_sl_type_parse_struct (scope, preproc);
case GSK_SL_TOKEN_IDENTIFIER:
{
type = gsk_sl_scope_lookup_type (scope, token->str);
if (type)
{
type = gsk_sl_type_ref (type);
break;
}
return gsk_sl_type_parse_block (scope, preproc);
}
default:
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected type specifier");
return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
}
gsk_sl_preprocessor_consume (preproc, NULL);
type = gsk_sl_type_parse_array (type, scope, preproc);
return type;
}
static GskSlTypeVoid void_type = { { &GSK_SL_TYPE_VOID, 1 } };
GskSlType *
gsk_sl_type_get_void (void)
{
return &void_type.parent;
}
static GskSlTypeScalar
builtin_scalar_types[N_SCALAR_TYPES] = {
[GSK_SL_FLOAT] = { { &GSK_SL_TYPE_SCALAR, 1 }, GSK_SL_FLOAT },
[GSK_SL_DOUBLE] = { { &GSK_SL_TYPE_SCALAR, 1 }, GSK_SL_DOUBLE },
[GSK_SL_INT] = { { &GSK_SL_TYPE_SCALAR, 1 }, GSK_SL_INT },
[GSK_SL_UINT] = { { &GSK_SL_TYPE_SCALAR, 1 }, GSK_SL_UINT },
[GSK_SL_BOOL] = { { &GSK_SL_TYPE_SCALAR, 1 }, GSK_SL_BOOL },
};
GskSlType *
gsk_sl_type_get_scalar (GskSlScalarType scalar)
{
g_assert (scalar < N_SCALAR_TYPES);
g_return_val_if_fail (scalar != GSK_SL_VOID, &void_type.parent);
return &builtin_scalar_types[scalar].parent;
}
static GskSlTypeVector
builtin_vector_types[3][N_SCALAR_TYPES] = {
{
[GSK_SL_FLOAT] = { { &GSK_SL_TYPE_VECTOR, 1 }, "vec2", GSK_SL_FLOAT, 2 },
[GSK_SL_DOUBLE] = { { &GSK_SL_TYPE_VECTOR, 1 }, "dvec2", GSK_SL_DOUBLE, 2 },
[GSK_SL_INT] = { { &GSK_SL_TYPE_VECTOR, 1 }, "ivec2", GSK_SL_INT, 2 },
[GSK_SL_UINT] = { { &GSK_SL_TYPE_VECTOR, 1 }, "uvec2", GSK_SL_UINT, 2 },
[GSK_SL_BOOL] = { { &GSK_SL_TYPE_VECTOR, 1 }, "bvec2", GSK_SL_BOOL, 2 },
},
{
[GSK_SL_FLOAT] = { { &GSK_SL_TYPE_VECTOR, 1 }, "vec3", GSK_SL_FLOAT, 3 },
[GSK_SL_DOUBLE] = { { &GSK_SL_TYPE_VECTOR, 1 }, "dvec3", GSK_SL_DOUBLE, 3 },
[GSK_SL_INT] = { { &GSK_SL_TYPE_VECTOR, 1 }, "ivec3", GSK_SL_INT, 3 },
[GSK_SL_UINT] = { { &GSK_SL_TYPE_VECTOR, 1 }, "uvec3", GSK_SL_UINT, 3 },
[GSK_SL_BOOL] = { { &GSK_SL_TYPE_VECTOR, 1 }, "bvec3", GSK_SL_BOOL, 3 },
},
{
[GSK_SL_FLOAT] = { { &GSK_SL_TYPE_VECTOR, 1 }, "vec4", GSK_SL_FLOAT, 4 },
[GSK_SL_DOUBLE] = { { &GSK_SL_TYPE_VECTOR, 1 }, "dvec4", GSK_SL_DOUBLE, 4 },
[GSK_SL_INT] = { { &GSK_SL_TYPE_VECTOR, 1 }, "ivec4", GSK_SL_INT, 4 },
[GSK_SL_UINT] = { { &GSK_SL_TYPE_VECTOR, 1 }, "uvec4", GSK_SL_UINT, 4 },
[GSK_SL_BOOL] = { { &GSK_SL_TYPE_VECTOR, 1 }, "bvec4", GSK_SL_BOOL, 4 },
}
};
GskSlType *
gsk_sl_type_get_vector (GskSlScalarType scalar,
guint length)
{
g_assert (scalar < N_SCALAR_TYPES);
g_assert (scalar != GSK_SL_VOID);
g_assert (length >= 2 && length <= 4);
return &builtin_vector_types[length - 2][scalar].parent;
}
static GskSlTypeMatrix
builtin_matrix_types[3][3][2] = {
{
{
{ { &GSK_SL_TYPE_MATRIX, 1 }, "mat2", GSK_SL_FLOAT, 2, 2 },
{ { &GSK_SL_TYPE_MATRIX, 1 }, "dmat2", GSK_SL_DOUBLE, 2, 2 }
},
{
{ { &GSK_SL_TYPE_MATRIX, 1 }, "mat2x3", GSK_SL_FLOAT, 2, 3 },
{ { &GSK_SL_TYPE_MATRIX, 1 }, "dmat2x3", GSK_SL_DOUBLE, 2, 3 }
},
{
{ { &GSK_SL_TYPE_MATRIX, 1 }, "mat2x4", GSK_SL_FLOAT, 2, 4 },
{ { &GSK_SL_TYPE_MATRIX, 1 }, "dmat2x4", GSK_SL_DOUBLE, 2, 4 }
},
},
{
{
{ { &GSK_SL_TYPE_MATRIX, 1 }, "mat3x2", GSK_SL_FLOAT, 3, 2 },
{ { &GSK_SL_TYPE_MATRIX, 1 }, "dmat3x2", GSK_SL_DOUBLE, 3, 2 }
},
{
{ { &GSK_SL_TYPE_MATRIX, 1 }, "mat3", GSK_SL_FLOAT, 3, 3 },
{ { &GSK_SL_TYPE_MATRIX, 1 }, "dmat3", GSK_SL_DOUBLE, 3, 3 }
},
{
{ { &GSK_SL_TYPE_MATRIX, 1 }, "mat3x4", GSK_SL_FLOAT, 3, 4 },
{ { &GSK_SL_TYPE_MATRIX, 1 }, "dmat3x4", GSK_SL_DOUBLE, 3, 4 }
},
},
{
{
{ { &GSK_SL_TYPE_MATRIX, 1 }, "mat4x2", GSK_SL_FLOAT, 4, 2 },
{ { &GSK_SL_TYPE_MATRIX, 1 }, "dmat4x2", GSK_SL_DOUBLE, 4, 2 }
},
{
{ { &GSK_SL_TYPE_MATRIX, 1 }, "mat4x3", GSK_SL_FLOAT, 4, 3 },
{ { &GSK_SL_TYPE_MATRIX, 1 }, "dmat4x3", GSK_SL_DOUBLE, 4, 3 }
},
{
{ { &GSK_SL_TYPE_MATRIX, 1 }, "mat4", GSK_SL_FLOAT, 4, 4 },
{ { &GSK_SL_TYPE_MATRIX, 1 }, "dmat4", GSK_SL_DOUBLE, 4, 4 }
},
},
};
GskSlType *
gsk_sl_type_get_matrix (GskSlScalarType scalar,
guint columns,
guint rows)
{
g_assert (scalar == GSK_SL_FLOAT || scalar == GSK_SL_DOUBLE);
g_assert (columns >= 2 && columns <= 4);
g_assert (rows >= 2 && rows <= 4);
return &builtin_matrix_types[columns - 2][rows - 2][scalar == GSK_SL_FLOAT ? 0 : 1].parent;
}
static GskSlTypeSampler
builtin_sampler_types[] = {
[GSK_SL_SAMPLER_1D] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler1D", GSK_SL_SAMPLER_1D, { GSK_SL_FLOAT, GSK_SPV_DIM_1_D, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_1D_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isampler1D", GSK_SL_SAMPLER_1D_INT, { GSK_SL_INT, GSK_SPV_DIM_1_D, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_1D_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usampler1D", GSK_SL_SAMPLER_1D_UINT, { GSK_SL_UINT, GSK_SPV_DIM_1_D, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_1D_SHADOW] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler1DShadow", GSK_SL_SAMPLER_1D_SHADOW, { GSK_SL_FLOAT, GSK_SPV_DIM_1_D, 1, 0, 0, 1 } },
[GSK_SL_SAMPLER_2D] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler2D", GSK_SL_SAMPLER_2D, { GSK_SL_FLOAT, GSK_SPV_DIM_2_D, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_2D_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isampler2D", GSK_SL_SAMPLER_2D_INT, { GSK_SL_INT, GSK_SPV_DIM_2_D, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_2D_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usampler2D", GSK_SL_SAMPLER_2D_UINT, { GSK_SL_UINT, GSK_SPV_DIM_2_D, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_2D_SHADOW] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler2DShadow", GSK_SL_SAMPLER_2D_SHADOW, { GSK_SL_FLOAT, GSK_SPV_DIM_2_D, 1, 0, 0, 1 } },
[GSK_SL_SAMPLER_3D] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler3D", GSK_SL_SAMPLER_3D, { GSK_SL_FLOAT, GSK_SPV_DIM_3_D, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_3D_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isampler3D", GSK_SL_SAMPLER_3D_INT, { GSK_SL_INT, GSK_SPV_DIM_3_D, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_3D_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usampler3D", GSK_SL_SAMPLER_3D_UINT, { GSK_SL_UINT, GSK_SPV_DIM_3_D, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_CUBE] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "samplerCube", GSK_SL_SAMPLER_CUBE, { GSK_SL_FLOAT, GSK_SPV_DIM_CUBE, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_CUBE_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isamplerCube", GSK_SL_SAMPLER_CUBE_INT, { GSK_SL_INT, GSK_SPV_DIM_CUBE, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_CUBE_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usamplerCube", GSK_SL_SAMPLER_CUBE_UINT, { GSK_SL_UINT, GSK_SPV_DIM_CUBE, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_CUBE_SHADOW] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "samplerCubeShadow", GSK_SL_SAMPLER_CUBE_SHADOW, { GSK_SL_FLOAT, GSK_SPV_DIM_CUBE, 1, 0, 0, 1 } },
[GSK_SL_SAMPLER_2D_RECT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler2DRect", GSK_SL_SAMPLER_2D_RECT, { GSK_SL_FLOAT, GSK_SPV_DIM_RECT, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_2D_RECT_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isampler2DRect", GSK_SL_SAMPLER_2D_RECT_INT, { GSK_SL_INT, GSK_SPV_DIM_RECT, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_2D_RECT_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usampler2DRect", GSK_SL_SAMPLER_2D_RECT_UINT, { GSK_SL_UINT, GSK_SPV_DIM_RECT, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_2D_RECT_SHADOW] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler2DRectShadow", GSK_SL_SAMPLER_2D_RECT_SHADOW, { GSK_SL_FLOAT, GSK_SPV_DIM_RECT, 1, 0, 0, 1 } },
[GSK_SL_SAMPLER_1D_ARRAY] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler1DArray", GSK_SL_SAMPLER_1D_ARRAY, { GSK_SL_FLOAT, GSK_SPV_DIM_1_D, 0, 1, 0, 1 } },
[GSK_SL_SAMPLER_1D_ARRAY_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isampler1DArray", GSK_SL_SAMPLER_1D_ARRAY_INT, { GSK_SL_INT, GSK_SPV_DIM_1_D, 0, 1, 0, 1 } },
[GSK_SL_SAMPLER_1D_ARRAY_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usampler1DArray", GSK_SL_SAMPLER_1D_ARRAY_UINT, { GSK_SL_UINT, GSK_SPV_DIM_1_D, 0, 1, 0, 1 } },
[GSK_SL_SAMPLER_1D_ARRAY_SHADOW] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler1DArrayShadow", GSK_SL_SAMPLER_1D_ARRAY_SHADOW, { GSK_SL_FLOAT, GSK_SPV_DIM_1_D, 1, 1, 0, 1 } },
[GSK_SL_SAMPLER_2D_ARRAY] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler2DArray", GSK_SL_SAMPLER_2D_ARRAY, { GSK_SL_FLOAT, GSK_SPV_DIM_2_D, 0, 1, 0, 1 } },
[GSK_SL_SAMPLER_2D_ARRAY_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isampler2DArray", GSK_SL_SAMPLER_2D_ARRAY_INT, { GSK_SL_INT, GSK_SPV_DIM_2_D, 0, 1, 0, 1 } },
[GSK_SL_SAMPLER_2D_ARRAY_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usampler2DArray", GSK_SL_SAMPLER_2D_ARRAY_UINT, { GSK_SL_UINT, GSK_SPV_DIM_2_D, 0, 1, 0, 1 } },
[GSK_SL_SAMPLER_2D_ARRAY_SHADOW] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler2DArrayShadow", GSK_SL_SAMPLER_2D_ARRAY_SHADOW, { GSK_SL_FLOAT, GSK_SPV_DIM_2_D, 1, 1, 0, 1 } },
[GSK_SL_SAMPLER_CUBE_ARRAY] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "samplerCubeArray", GSK_SL_SAMPLER_CUBE_ARRAY, { GSK_SL_FLOAT, GSK_SPV_DIM_CUBE, 0, 1, 0, 1 } },
[GSK_SL_SAMPLER_CUBE_ARRAY_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isamplerCubeArray", GSK_SL_SAMPLER_CUBE_ARRAY_INT, { GSK_SL_INT, GSK_SPV_DIM_CUBE, 0, 1, 0, 1 } },
[GSK_SL_SAMPLER_CUBE_ARRAY_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usamplerCubeArray", GSK_SL_SAMPLER_CUBE_ARRAY_UINT, { GSK_SL_UINT, GSK_SPV_DIM_CUBE, 0, 1, 0, 1 } },
[GSK_SL_SAMPLER_CUBE_ARRAY_SHADOW] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "samplerCubeArrayShadow", GSK_SL_SAMPLER_CUBE_ARRAY_SHADOW, { GSK_SL_FLOAT, GSK_SPV_DIM_CUBE, 1, 1, 0, 1 } },
[GSK_SL_SAMPLER_BUFFER] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "samplerBuffer", GSK_SL_SAMPLER_BUFFER, { GSK_SL_FLOAT, GSK_SPV_DIM_BUFFER, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_BUFFER_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isamplerBuffer", GSK_SL_SAMPLER_BUFFER_INT, { GSK_SL_INT, GSK_SPV_DIM_BUFFER, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_BUFFER_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usamplerBuffer", GSK_SL_SAMPLER_BUFFER_UINT, { GSK_SL_UINT, GSK_SPV_DIM_BUFFER, 0, 0, 0, 1 } },
[GSK_SL_SAMPLER_2DMS] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler2DMS", GSK_SL_SAMPLER_2DMS, { GSK_SL_FLOAT, GSK_SPV_DIM_2_D, 0, 0, 1, 1 } },
[GSK_SL_SAMPLER_2DMS_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isampler2DMS", GSK_SL_SAMPLER_2DMS_INT, { GSK_SL_INT, GSK_SPV_DIM_2_D, 0, 0, 1, 1 } },
[GSK_SL_SAMPLER_2DMS_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usampler2DMS", GSK_SL_SAMPLER_2DMS_UINT, { GSK_SL_UINT, GSK_SPV_DIM_2_D, 0, 0, 1, 1 } },
[GSK_SL_SAMPLER_2DMS_ARRAY] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "sampler2DMSArray", GSK_SL_SAMPLER_2DMS_ARRAY, { GSK_SL_FLOAT, GSK_SPV_DIM_2_D, 0, 1, 1, 1 } },
[GSK_SL_SAMPLER_2DMS_ARRAY_INT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "isampler2DMSArray", GSK_SL_SAMPLER_2DMS_ARRAY_INT, { GSK_SL_INT, GSK_SPV_DIM_2_D, 0, 1, 1, 1 } },
[GSK_SL_SAMPLER_2DMS_ARRAY_UINT] = { { &GSK_SL_TYPE_SAMPLER, 1 }, "usampler2DMSArray", GSK_SL_SAMPLER_2DMS_ARRAY_UINT, { GSK_SL_UINT, GSK_SPV_DIM_2_D, 0, 1, 1, 1 } }
};
GskSlType *
gsk_sl_type_get_sampler (GskSlSamplerType sampler)
{
return &builtin_sampler_types[sampler].parent;
}
GskSlType *
gsk_sl_type_ref (GskSlType *type)
{
g_return_val_if_fail (type != NULL, NULL);
type->ref_count += 1;
return type;
}
void
gsk_sl_type_unref (GskSlType *type)
{
if (type == NULL)
return;
type->ref_count -= 1;
if (type->ref_count > 0)
return;
type->class->free (type);
}
const char *
gsk_sl_type_get_name (const GskSlType *type)
{
return type->class->get_name (type);
}
gboolean
gsk_sl_type_is_void (const GskSlType *type)
{
return type->class == &GSK_SL_TYPE_VOID;
}
gboolean
gsk_sl_type_is_scalar (const GskSlType *type)
{
return type->class == &GSK_SL_TYPE_SCALAR;
}
gboolean
gsk_sl_type_is_vector (const GskSlType *type)
{
return type->class == &GSK_SL_TYPE_VECTOR;
}
gboolean
gsk_sl_type_is_matrix (const GskSlType *type)
{
return type->class == &GSK_SL_TYPE_MATRIX;
}
gboolean
gsk_sl_type_is_basic (const GskSlType *type)
{
return gsk_sl_type_is_scalar (type)
|| gsk_sl_type_is_vector (type)
|| gsk_sl_type_is_matrix (type);
}
gboolean
gsk_sl_type_is_array (const GskSlType *type)
{
return type->class == &GSK_SL_TYPE_ARRAY;
}
gboolean
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;
}
gboolean
gsk_sl_type_is_sampler (const GskSlType *type)
{
return type->class == &GSK_SL_TYPE_SAMPLER;
}
gboolean
gsk_sl_type_is_opaque (const GskSlType *type)
{
return gsk_sl_type_is_sampler (type);
}
gboolean
gsk_sl_type_contains_opaque (const GskSlType *type)
{
gsize i;
if (gsk_sl_type_is_opaque (type))
return TRUE;
for (i = 0; i < gsk_sl_type_get_n_members (type); i++)
{
if (gsk_sl_type_contains_opaque (gsk_sl_type_get_member_type (type, i)))
return TRUE;
}
return FALSE;
}
GskSlScalarType
gsk_sl_type_get_scalar_type (const GskSlType *type)
{
return type->class->get_scalar_type (type);
}
const GskSlImageType *
gsk_sl_type_get_image_type (const GskSlType *type)
{
return type->class->get_image_type (type);
}
GskSlType *
gsk_sl_type_get_index_type (const GskSlType *type)
{
return type->class->get_index_type (type);
}
gsize
gsk_sl_type_get_index_stride (const GskSlType *type)
{
return type->class->get_index_stride (type);
}
guint
gsk_sl_type_get_length (const GskSlType *type)
{
return type->class->get_length (type);
}
gsize
gsk_sl_type_get_size (const GskSlType *type)
{
return type->class->get_size (type);
}
gsize
gsk_sl_type_get_n_components (const GskSlType *type)
{
return type->class->get_n_components (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)
{
if (target == source)
return TRUE;
switch (source)
{
case GSK_SL_INT:
return target == GSK_SL_UINT
|| target == GSK_SL_FLOAT
|| target == GSK_SL_DOUBLE;
case GSK_SL_UINT:
return target == GSK_SL_FLOAT
|| target == GSK_SL_DOUBLE;
case GSK_SL_FLOAT:
return target == GSK_SL_DOUBLE;
case GSK_SL_DOUBLE:
case GSK_SL_BOOL:
case GSK_SL_VOID:
default:
return FALSE;
}
}
void
gsk_sl_scalar_type_convert_value (GskSlScalarType target_type,
gpointer target_value,
GskSlScalarType source_type,
gconstpointer source_value)
{
scalar_infos[source_type].convert_value[target_type] (target_value, source_value);
}
gboolean
gsk_sl_type_can_convert (const GskSlType *target,
const GskSlType *source)
{
return target->class->can_convert (target, source);
}
gboolean
gsk_sl_type_equal (gconstpointer a,
gconstpointer b)
{
return a == b;
}
guint
gsk_sl_type_hash (gconstpointer type)
{
return GPOINTER_TO_UINT (type);
}
guint32
gsk_sl_type_write_spv (GskSlType *type,
GskSpvWriter *writer)
{
return type->class->write_spv (type, writer);
}
void
gsk_sl_type_print_value (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value)
{
type->class->print_value (type, printer, value);
}
gboolean
gsk_sl_type_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b)
{
return type->class->value_equal (type, a, b);
}
guint32
gsk_sl_type_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value)
{
return type->class->write_value_spv (type, writer, value);
}
struct _GskSlTypeBuilder {
char *name;
gsize size;
GArray *members;
guint is_block :1;
};
GskSlTypeBuilder *
gsk_sl_type_builder_new_struct (const char *name)
{
GskSlTypeBuilder *builder;
builder = g_slice_new0 (GskSlTypeBuilder);
builder->name = g_strdup (name);
builder->members = g_array_new (FALSE, FALSE, sizeof (GskSlTypeMember));
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)
{
GString *string = g_string_new ("struct { ");
guint i, j;
for (i = 0; i < builder->members->len; i++)
{
GskSlTypeMember *m = &g_array_index (builder->members, GskSlTypeMember, i);
g_string_append (string, gsk_sl_type_get_name (m->type));
g_string_append (string, " ");
g_string_append (string, m->name);
for (j = i + 1; j < builder->members->len; j++)
{
GskSlTypeMember *n = &g_array_index (builder->members, GskSlTypeMember, j);
if (!gsk_sl_type_equal (m->type, n->type))
break;
g_string_append (string, ", ");
g_string_append (string, n->name);
}
i = j - 1;
g_string_append (string, "; ");
}
g_string_append (string, "}");
return g_string_free (string, FALSE);
}
static GskSlType *
gsk_sl_type_builder_free_to_struct (GskSlTypeBuilder *builder)
{
GskSlTypeStruct *result;
result = gsk_sl_type_new (GskSlTypeStruct, &GSK_SL_TYPE_STRUCT);
if (builder->name)
result->name = builder->name;
else
result->name = gsk_sl_type_builder_generate_name (builder);
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;
}
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,
const char *name)
{
g_array_append_vals (builder->members,
&(GskSlTypeMember) {
gsk_sl_type_ref (type),
g_strdup (name),
builder->size }, 1);
builder->size += gsk_sl_type_get_size (type);
}
gboolean
gsk_sl_type_builder_has_member (GskSlTypeBuilder *builder,
const char *name)
{
guint i;
for (i = 0; i < builder->members->len; i++)
{
if (g_str_equal (g_array_index (builder->members, GskSlTypeMember, i).name, name))
return TRUE;
}
return FALSE;
}