From 4e61c71a5ae6f7a83f2188b1819dd30007e9b433 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Wed, 11 Oct 2017 17:33:55 +0200 Subject: [PATCH] gsksl: Implement subtraction --- gsk/gskslbinary.c | 239 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 232 insertions(+), 7 deletions(-) diff --git a/gsk/gskslbinary.c b/gsk/gskslbinary.c index 1b11a76d8f..445723ab37 100644 --- a/gsk/gskslbinary.c +++ b/gsk/gskslbinary.c @@ -964,6 +964,238 @@ static const GskSlBinary GSK_SL_BINARY_ADDITION = { gsk_sl_addition_write_spv }; +GSK_SL_BINARY_FUNC_SCALAR(gsk_sl_expression_subtraction_int, gint32, x -= y;) +GSK_SL_BINARY_FUNC_SCALAR(gsk_sl_expression_subtraction_uint, guint32, x -= y;) +GSK_SL_BINARY_FUNC_SCALAR(gsk_sl_expression_subtraction_float, float, x -= y;) +GSK_SL_BINARY_FUNC_SCALAR(gsk_sl_expression_subtraction_double, double, x -= y;) +GSK_SL_BINARY_FUNC_SCALAR(gsk_sl_expression_subtraction_int_inv, gint32, x = y - x;) +GSK_SL_BINARY_FUNC_SCALAR(gsk_sl_expression_subtraction_uint_inv, guint32, x = y - x;) +GSK_SL_BINARY_FUNC_SCALAR(gsk_sl_expression_subtraction_float_inv, float, x = y - x;) +GSK_SL_BINARY_FUNC_SCALAR(gsk_sl_expression_subtraction_double_inv, double, x = y - x;) +static void (* subtraction_funcs[]) (gpointer, gpointer) = { + [GSK_SL_INT] = gsk_sl_expression_subtraction_int, + [GSK_SL_UINT] = gsk_sl_expression_subtraction_uint, + [GSK_SL_FLOAT] = gsk_sl_expression_subtraction_float, + [GSK_SL_DOUBLE] = gsk_sl_expression_subtraction_double, +}; +static void (* subtraction_inv_funcs[]) (gpointer, gpointer) = { + [GSK_SL_INT] = gsk_sl_expression_subtraction_int_inv, + [GSK_SL_UINT] = gsk_sl_expression_subtraction_uint_inv, + [GSK_SL_FLOAT] = gsk_sl_expression_subtraction_float_inv, + [GSK_SL_DOUBLE] = gsk_sl_expression_subtraction_double_inv, +}; + +static GskSlValue * +gsk_sl_subtraction_get_constant (GskSlType *type, + GskSlValue *lvalue, + GskSlValue *rvalue) +{ + GskSlValue *result; + GskSlType *ltype, *rtype; + GskSlScalarType scalar; + gsize ln, rn; + + scalar = gsk_sl_type_get_scalar_type (type); + lvalue = gsk_sl_value_convert_components (lvalue, scalar); + rvalue = gsk_sl_value_convert_components (rvalue, scalar); + ltype = gsk_sl_value_get_type (lvalue); + rtype = gsk_sl_value_get_type (rvalue); + + ln = gsk_sl_type_get_n_components (ltype); + rn = gsk_sl_type_get_n_components (rtype); + if (ln == 1) + { + gsk_sl_value_componentwise (rvalue, subtraction_inv_funcs[scalar], gsk_sl_value_get_data (lvalue)); + gsk_sl_value_free (lvalue); + result = rvalue; + } + else if (rn == 1) + { + gsk_sl_value_componentwise (lvalue, subtraction_funcs[scalar], gsk_sl_value_get_data (rvalue)); + gsk_sl_value_free (rvalue); + result = lvalue; + } + else + { + guchar *ldata, *rdata; + gsize i, stride; + + stride = gsk_sl_scalar_type_get_size (scalar); + ldata = gsk_sl_value_get_data (lvalue); + rdata = gsk_sl_value_get_data (rvalue); + for (i = 0; i < ln; i++) + { + subtraction_funcs[scalar] (ldata + i * stride, rdata + i * stride); + } + gsk_sl_value_free (rvalue); + result = lvalue; + } + + return result; +} + +static guint32 +gsk_sl_subtraction_write_spv (GskSpvWriter *writer, + GskSlType *type, + GskSlType *ltype, + guint32 left_id, + GskSlType *rtype, + guint32 right_id) +{ + if (gsk_sl_type_get_scalar_type (ltype) != gsk_sl_type_get_scalar_type (type)) + { + GskSlType *new_type = gsk_sl_type_get_matching (ltype, gsk_sl_type_get_scalar_type (type)); + left_id = gsk_spv_writer_convert (writer, left_id, ltype, new_type); + ltype = new_type; + } + if (gsk_sl_type_get_scalar_type (rtype) != gsk_sl_type_get_scalar_type (type)) + { + GskSlType *new_type = gsk_sl_type_get_matching (rtype, gsk_sl_type_get_scalar_type (type)); + right_id = gsk_spv_writer_convert (writer, right_id, rtype, new_type); + rtype = new_type; + } + + if (gsk_sl_type_is_matrix (ltype)) + { + if (gsk_sl_type_is_matrix (rtype)) + { + GskSlType *col_type = gsk_sl_type_get_index_type (ltype); + gsize cols = gsk_sl_type_get_length (ltype); + gsize c; + guint32 left_part_id, right_part_id, ids[cols]; + + for (c = 0; c < cols; c++) + { + left_part_id = gsk_spv_writer_composite_extract (writer, + col_type, + left_id, + (guint32[1]) { c }, 1); + right_part_id = gsk_spv_writer_composite_extract (writer, + col_type, + right_id, + (guint32[1]) { c }, 1); + ids[c] = gsk_spv_writer_f_sub (writer, + col_type, + left_part_id, + right_part_id); + } + + return gsk_spv_writer_composite_construct (writer, + type, + ids, + cols); + } + else if (gsk_sl_type_is_scalar (rtype)) + { + GskSlType *col_type = gsk_sl_type_get_index_type (ltype); + gsize cols = gsk_sl_type_get_length (ltype); + gsize c; + guint32 left_part_id, right_part_id, ids[cols]; + + right_part_id = gsk_spv_writer_composite_construct (writer, + col_type, + (guint32[4]) { right_id, right_id, right_id, right_id }, + gsk_sl_type_get_length (col_type)); + for (c = 0; c < cols; c++) + { + left_part_id = gsk_spv_writer_composite_extract (writer, + col_type, + left_id, + (guint32[1]) { c }, 1); + ids[c] = gsk_spv_writer_f_sub (writer, + col_type, + left_part_id, + right_part_id); + } + + return gsk_spv_writer_composite_construct (writer, + type, + ids, + cols); + } + else + { + g_assert_not_reached (); + return 0; + } + } + else if (gsk_sl_type_is_matrix (rtype)) + { + GskSlType *col_type = gsk_sl_type_get_index_type (rtype); + gsize cols = gsk_sl_type_get_length (rtype); + gsize c; + guint32 left_part_id, right_part_id, ids[cols]; + + left_part_id = gsk_spv_writer_composite_construct (writer, + col_type, + (guint32[4]) { left_id, left_id, left_id, left_id }, + gsk_sl_type_get_length (col_type)); + for (c = 0; c < cols; c++) + { + right_part_id = gsk_spv_writer_composite_extract (writer, + col_type, + right_id, + (guint32[1]) { c }, 1); + ids[c] = gsk_spv_writer_f_sub (writer, + col_type, + left_part_id, + right_part_id); + } + + return gsk_spv_writer_composite_construct (writer, + type, + ids, + cols); + } + else + { + /* ltype and rtype are not matrices */ + + if (gsk_sl_type_is_scalar (ltype) && gsk_sl_type_is_vector (rtype)) + { + guint32 tmp_id = gsk_spv_writer_composite_construct (writer, + type, + (guint32[4]) { left_id, left_id, left_id, left_id }, + gsk_sl_type_get_length (rtype)); + left_id = tmp_id; + } + else if (gsk_sl_type_is_scalar (rtype) && gsk_sl_type_is_vector (ltype)) + { + guint32 tmp_id = gsk_spv_writer_composite_construct (writer, + type, + (guint32[4]) { right_id, right_id, right_id, right_id }, + gsk_sl_type_get_length (ltype)); + right_id = tmp_id; + } + + /* ltype and rtype have the same number of components now */ + + switch (gsk_sl_type_get_scalar_type (type)) + { + case GSK_SL_FLOAT: + case GSK_SL_DOUBLE: + return gsk_spv_writer_f_sub (writer, type, left_id, right_id); + + case GSK_SL_INT: + case GSK_SL_UINT: + return gsk_spv_writer_i_sub (writer, type, left_id, right_id); + + case GSK_SL_VOID: + case GSK_SL_BOOL: + default: + g_assert_not_reached (); + return 0; + } + } +} + +static const GskSlBinary GSK_SL_BINARY_SUBTRACTION = { + "-", + gsk_sl_arithmetic_check_type, + gsk_sl_subtraction_get_constant, + gsk_sl_subtraction_write_spv +}; + /* UNIMPLEMENTED */ static GskSlType * @@ -1159,13 +1391,6 @@ static const GskSlBinary GSK_SL_BINARY_MODULO = { gsk_sl_unimplemented_write_spv }; -static const GskSlBinary GSK_SL_BINARY_SUBTRACTION = { - "-", - gsk_sl_arithmetic_check_type, - gsk_sl_unimplemented_get_constant, - gsk_sl_unimplemented_write_spv -}; - static const GskSlBinary GSK_SL_BINARY_LSHIFT = { "<<", gsk_sl_shift_check_type,