gskslexpression: Implement negation

This includes adding gsk_sl_value_componentwise() which is not something
I particularly like, but it does its job - and will be useful for the
other operations.
This commit is contained in:
Benjamin Otte
2017-09-29 02:45:11 +02:00
parent 69b4834764
commit 21fe62ec66
4 changed files with 228 additions and 2 deletions

View File

@@ -1055,6 +1055,142 @@ static const GskSlExpressionClass GSK_SL_EXPRESSION_SWIZZLE = {
gsk_sl_expression_swizzle_write_spv
};
/* NEGATION */
typedef struct _GskSlExpressionNegation GskSlExpressionNegation;
struct _GskSlExpressionNegation {
GskSlExpression parent;
GskSlExpression *expr;
};
static void
gsk_sl_expression_negation_free (GskSlExpression *expression)
{
GskSlExpressionNegation *negation = (GskSlExpressionNegation *) expression;
gsk_sl_expression_unref (negation->expr);
g_slice_free (GskSlExpressionNegation, negation);
}
static void
gsk_sl_expression_negation_print (const GskSlExpression *expression,
GString *string)
{
const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
g_string_append (string, "-");
gsk_sl_expression_print (negation->expr, string);
}
static GskSlType *
gsk_sl_expression_negation_get_return_type (const GskSlExpression *expression)
{
const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
return gsk_sl_expression_get_return_type (negation->expr);
}
#define GSK_SL_OPERATION_FUNC(func,type,...) \
static void \
func (gpointer value, gpointer unused) \
{ \
type x = *(type *) value; \
__VA_ARGS__ \
*(type *) value = x; \
}
GSK_SL_OPERATION_FUNC(gsk_sl_expression_negation_int, gint32, x = -x;)
GSK_SL_OPERATION_FUNC(gsk_sl_expression_negation_uint, guint32, x = -x;)
GSK_SL_OPERATION_FUNC(gsk_sl_expression_negation_float, float, x = -x;)
GSK_SL_OPERATION_FUNC(gsk_sl_expression_negation_double, double, x = -x;)
static GskSlValue *
gsk_sl_expression_negation_get_constant (const GskSlExpression *expression)
{
const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
GskSlValue *value;
value = gsk_sl_expression_get_constant (negation->expr);
if (value == NULL)
return NULL;
switch (gsk_sl_type_get_scalar_type (gsk_sl_value_get_type (value)))
{
case GSK_SL_INT:
gsk_sl_value_componentwise (value, gsk_sl_expression_negation_int, NULL);
break;
case GSK_SL_UINT:
gsk_sl_value_componentwise (value, gsk_sl_expression_negation_uint, NULL);
break;
case GSK_SL_FLOAT:
gsk_sl_value_componentwise (value, gsk_sl_expression_negation_float, NULL);
break;
case GSK_SL_DOUBLE:
gsk_sl_value_componentwise (value, gsk_sl_expression_negation_double, NULL);
break;
case GSK_SL_VOID:
case GSK_SL_BOOL:
default:
g_assert_not_reached ();
break;
}
return value;
}
static guint32
gsk_sl_expression_negation_write_spv (const GskSlExpression *expression,
GskSpvWriter *writer)
{
const GskSlExpressionNegation *negation = (const GskSlExpressionNegation *) expression;
guint type_id, expr_id, result_id;
GskSlType *type;
type = gsk_sl_expression_get_return_type (negation->expr);
type_id = gsk_spv_writer_get_id_for_type (writer, type);
expr_id = gsk_sl_expression_write_spv (negation->expr, writer);
result_id = gsk_spv_writer_next_id (writer);
switch (gsk_sl_type_get_scalar_type (type))
{
case GSK_SL_INT:
case GSK_SL_UINT:
gsk_spv_writer_add (writer,
GSK_SPV_WRITER_SECTION_CODE,
4, GSK_SPV_OP_S_NEGATE,
(guint32[3]) { type_id,
result_id,
expr_id });
break;
case GSK_SL_FLOAT:
case GSK_SL_DOUBLE:
gsk_spv_writer_add (writer,
GSK_SPV_WRITER_SECTION_CODE,
4, GSK_SPV_OP_F_NEGATE,
(guint32[3]) { type_id,
result_id,
expr_id });
break;
case GSK_SL_VOID:
case GSK_SL_BOOL:
default:
g_assert_not_reached ();
break;
}
return result_id;
}
static const GskSlExpressionClass GSK_SL_EXPRESSION_NEGATION = {
gsk_sl_expression_negation_free,
gsk_sl_expression_negation_print,
gsk_sl_expression_negation_get_return_type,
gsk_sl_expression_negation_get_constant,
gsk_sl_expression_negation_write_spv
};
/* CONSTANT */
typedef struct _GskSlExpressionConstant GskSlExpressionConstant;
@@ -1071,6 +1207,8 @@ gsk_sl_expression_constant_free (GskSlExpression *expression)
GskSlExpressionConstant *constant = (GskSlExpressionConstant *) expression;
gsk_sl_value_free (constant->value);
g_slice_free (GskSlExpressionConstant, constant);
}
static void
@@ -1496,9 +1634,48 @@ gsk_sl_expression_parse_postfix (GskSlScope *scope,
static GskSlExpression *
gsk_sl_expression_parse_unary (GskSlScope *scope,
GskSlPreprocessor *stream)
GskSlPreprocessor *preproc)
{
return gsk_sl_expression_parse_postfix (scope, stream);
const GskSlToken *token;
GskSlType *type;
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_DASH))
{
GskSlExpressionNegation *negation = gsk_sl_expression_new (GskSlExpressionNegation, &GSK_SL_EXPRESSION_NEGATION);
GskSlExpression *expr;
gsk_sl_preprocessor_consume (preproc, negation);
negation->expr = gsk_sl_expression_parse_unary (scope, preproc);
type = gsk_sl_expression_get_return_type (negation->expr);
if (!gsk_sl_type_is_scalar (type) && !gsk_sl_type_is_vector (type) && !gsk_sl_type_is_matrix (type))
{
gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
"Negation only works on scalars, vectors and matrices, not on %s.",
gsk_sl_type_get_name (type));
expr = gsk_sl_expression_ref (negation->expr);
gsk_sl_expression_unref ((GskSlExpression *) negation);
return expr;
}
else if (gsk_sl_type_get_scalar_type (type) == GSK_SL_BOOL)
{
gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
"Negation does not work on boolean types like %s.",
gsk_sl_type_get_name (type));
expr = gsk_sl_expression_ref (negation->expr);
gsk_sl_expression_unref ((GskSlExpression *) negation);
return expr;
}
else
{
return (GskSlExpression *) negation;
}
}
else
{
return gsk_sl_expression_parse_postfix (scope, preproc);
}
}
static GskSlExpression *

View File

@@ -194,6 +194,25 @@ gsk_sl_value_free (GskSlValue *value)
g_slice_free (GskSlValue, value);
}
void
gsk_sl_value_componentwise (GskSlValue *value,
void (* func) (gpointer, gpointer),
gpointer user_data)
{
gsize stride;
gsize i, n;
g_return_if_fail (gsk_sl_type_is_scalar (value->type) || gsk_sl_type_is_vector (value->type) || gsk_sl_type_is_matrix (value->type));
stride = gsk_sl_type_get_size (gsk_sl_type_get_scalar (gsk_sl_type_get_scalar_type (value->type)));
n = gsk_sl_type_get_size (value->type) / stride;
for (i = 0; i < n; i++)
{
func ((guchar *) value->data + stride * i, user_data);
}
}
void
gsk_sl_value_print (const GskSlValue *value,
GString *string)

View File

@@ -35,6 +35,9 @@ GskSlValue * gsk_sl_value_new_member (GskSlValue
GskSlValue * gsk_sl_value_copy (const GskSlValue *source);
void gsk_sl_value_free (GskSlValue *value);
void gsk_sl_value_componentwise (GskSlValue *value,
void (* func) (gpointer, gpointer),
gpointer user_data);
void gsk_sl_value_print (const GskSlValue *value,
GString *string);

View File

@@ -119,6 +119,33 @@ typedef enum {
GSK_SPV_OP_GENERIC_CAST_TO_PTR = 122,
GSK_SPV_OP_GENERIC_CAST_TO_PTR_EXPLICIT = 123,
GSK_SPV_OP_BITCAST = 124,
GSK_SPV_OP_S_NEGATE = 126,
GSK_SPV_OP_F_NEGATE = 127,
GSK_SPV_OP_I_ADD = 128,
GSK_SPV_OP_F_ADD = 129,
GSK_SPV_OP_I_SUB = 130,
GSK_SPV_OP_F_SUB = 131,
GSK_SPV_OP_I_MUL = 132,
GSK_SPV_OP_F_MUL = 133,
GSK_SPV_OP_U_DIV = 134,
GSK_SPV_OP_S_DIV = 135,
GSK_SPV_OP_F_DIV = 136,
GSK_SPV_OP_U_MOD = 137,
GSK_SPV_OP_S_REM = 138,
GSK_SPV_OP_S_MOD = 139,
GSK_SPV_OP_F_REM = 140,
GSK_SPV_OP_F_MOD = 141,
GSK_SPV_OP_VECTOR_TIMES_SCALAR = 142,
GSK_SPV_OP_MATRIX_TIMES_SCALAR = 143,
GSK_SPV_OP_VECTOR_TIMES_MATRIX = 144,
GSK_SPV_OP_MATRIX_TIMES_VECTOR = 145,
GSK_SPV_OP_MATRIX_TIMES_MATRIX = 146,
GSK_SPV_OP_OUTER_PRODUCT = 147,
GSK_SPV_OP_DOT = 148,
GSK_SPV_OP_I_ADD_CARRY = 149,
GSK_SPV_OP_I_SUB_BORROW = 150,
GSK_SPV_OP_U_MUL_EXTENDED = 151,
GSK_SPV_OP_S_MUL_EXTENDED = 152,
GSK_SPV_OP_PHI = 245,
GSK_SPV_OP_LOOP_MERGE = 246,
GSK_SPV_OP_SELECTION_MERGE = 247,