gsksl: Implement subtraction

This commit is contained in:
Benjamin Otte
2017-10-11 17:33:55 +02:00
parent d6c2c00a0a
commit 4e61c71a5a

View File

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