From: Nikolay Sivov nsivov@codeweavers.com
--- Makefile.am | 1 + libs/vkd3d-shader/hlsl.y | 44 ++++++++++++++++++++++++++++++++++++++++ tests/fmod.shader_test | 13 ++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 tests/fmod.shader_test
diff --git a/Makefile.am b/Makefile.am index e3d52ac5..81805cac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -70,6 +70,7 @@ vkd3d_shader_tests = \ tests/exp.shader_test \ tests/expr-indexing.shader_test \ tests/floor.shader_test \ + tests/fmod.shader_test \ tests/frac.shader_test \ tests/function-return.shader_test \ tests/hlsl-array-dimension.shader_test \ diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index ab0b3f65..b3f1a1e2 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2740,6 +2740,49 @@ static bool intrinsic_floor(struct hlsl_ctx *ctx, return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_FLOOR, arg, loc); }
+static bool intrinsic_fmod(struct hlsl_ctx *ctx, const struct parse_initializer *params, + const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *x, *y, *div, *abs, *frac, *neg_frac, *ge; + struct hlsl_ir_constant *zero; + struct hlsl_ir_load *select; + unsigned int count, i; + + if (!(x = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) + return false; + + if (!(y = intrinsic_float_convert_arg(ctx, params, params->args[1], loc))) + return false; + + if (!(div = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_DIV, x, y, loc))) + return false; + + if (!(zero = hlsl_new_constant(ctx, div->data_type, loc))) + return false; + list_add_tail(params->instrs, &zero->node.entry); + + count = hlsl_type_element_count(div->data_type); + for (i = 0; i < count; ++i) + zero->value.u[i].f = 0.0f; + + if (!(abs = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_ABS, div, loc))) + return false; + + if (!(frac = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_FRACT, abs, loc))) + return false; + + if (!(neg_frac = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_NEG, frac, loc))) + return false; + + if (!(ge = add_binary_comparison_expr(ctx, params->instrs, HLSL_OP2_GEQUAL, div, &zero->node, loc))) + return false; + + if (!(select = hlsl_add_conditional(ctx, params->instrs, ge, frac, neg_frac))) + return false; + + return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, &select->node, y, loc); +} + static bool intrinsic_frac(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -3499,6 +3542,7 @@ intrinsic_functions[] = {"exp", 1, true, intrinsic_exp}, {"exp2", 1, true, intrinsic_exp2}, {"floor", 1, true, intrinsic_floor}, + {"fmod", 2, true, intrinsic_fmod}, {"frac", 1, true, intrinsic_frac}, {"ldexp", 2, true, intrinsic_ldexp}, {"length", 1, true, intrinsic_length}, diff --git a/tests/fmod.shader_test b/tests/fmod.shader_test new file mode 100644 index 00000000..4c9ff988 --- /dev/null +++ b/tests/fmod.shader_test @@ -0,0 +1,13 @@ +[pixel shader] +float4 main(uniform float4 u) : sv_target +{ + return float4(fmod(u.x, u.y), 0, 0, 0); +} + +[test] +uniform 0 float4 -0.5 6.5 0.0 0.0 +draw quad +probe all rgba (-0.5, 0.0, 0.0, 0.0) 4 +uniform 0 float4 1.1 0.3 0.0 0.0 +draw quad +probe all rgba (0.2, 0.0, 0.0, 0.0) 4
This merge request was approved by Zebediah Figura.
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/hlsl.y:
- if (!(x = intrinsic_float_convert_arg(ctx, params, params->args[0], loc)))
return false;
- if (!(y = intrinsic_float_convert_arg(ctx, params, params->args[1], loc)))
return false;
- if (!(div = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_DIV, x, y, loc)))
return false;
- if (!(zero = hlsl_new_constant(ctx, div->data_type, loc)))
return false;
- list_add_tail(params->instrs, &zero->node.entry);
- count = hlsl_type_element_count(div->data_type);
- for (i = 0; i < count; ++i)
zero->value.u[i].f = 0.0f;
I think we can take for granted that it's part of the contract of `hlsl_new_constant()` that the returned constant is zero for all numerical data types. Not that this code is wrong, but it can be dropped.
This merge request was approved by Giovanni Mascellani.
This merge request was approved by Henri Verbeet.