From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 36 ++++++++++++++++++++++++++++++++++-- tests/hlsl/fmod.shader_test | 14 ++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 82dd19ebb..6866e8684 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2857,6 +2857,10 @@ static bool intrinsic_fmod(struct hlsl_ctx *ctx, const struct parse_initializer { struct hlsl_ir_node *x, *y, *div, *abs, *frac, *neg_frac, *ge, *select, *zero; static const struct hlsl_constant_value zero_value; + struct hlsl_ir_load *var_load; + struct hlsl_deref var_deref; + struct hlsl_ir_var *var; + unsigned int i, count;
if (!(x = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) return false; @@ -2883,10 +2887,38 @@ static bool intrinsic_fmod(struct hlsl_ctx *ctx, const struct parse_initializer if (!(ge = add_binary_comparison_expr(ctx, block_to_list(params->instrs), HLSL_OP2_GEQUAL, div, zero, loc))) return false;
- if (!(select = hlsl_add_conditional(ctx, block_to_list(params->instrs), ge, frac, neg_frac))) + if (!(var = hlsl_new_synthetic_var(ctx, "result", x->data_type, loc))) return false; + hlsl_init_simple_deref_from_var(&var_deref, var); + + count = hlsl_type_component_count(ge->data_type); + for (i = 0; i < count; ++i) + { + struct hlsl_ir_node *cond_comp, *frac_comp, *neg_frac_comp; + struct hlsl_block block; + + if (!(cond_comp = hlsl_add_load_component(ctx, block_to_list(params->instrs), ge, i, loc))) + return false; + + if (!(frac_comp = hlsl_add_load_component(ctx, block_to_list(params->instrs), frac, i, loc))) + return false; + + if (!(neg_frac_comp = hlsl_add_load_component(ctx, block_to_list(params->instrs), neg_frac, i, loc))) + return false; + + if (!(select = hlsl_add_conditional(ctx, block_to_list(params->instrs), cond_comp, frac_comp, neg_frac_comp))) + return false; + + if (!hlsl_new_store_component(ctx, &block, &var_deref, i, select)) + return false; + hlsl_block_add_block(params->instrs, &block); + } + + if (!(var_load = hlsl_new_var_load(ctx, var, loc))) + return NULL; + hlsl_block_add_instr(params->instrs, &var_load->node);
- return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, select, y, loc); + return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, &var_load->node, y, loc); }
static bool intrinsic_frac(struct hlsl_ctx *ctx, diff --git a/tests/hlsl/fmod.shader_test b/tests/hlsl/fmod.shader_test index 4c9ff988c..9eb69c3bb 100644 --- a/tests/hlsl/fmod.shader_test +++ b/tests/hlsl/fmod.shader_test @@ -11,3 +11,17 @@ 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 + +[pixel shader] +float4 main(uniform float4 u) : sv_target +{ + return float4(fmod(u.xy, u.z), 0, 0); +} + +[test] +uniform 0 float4 -0.5 6.5 2.0 0.0 +draw quad +probe all rgba (-0.5, 0.5, 0.0, 0.0) 4 +uniform 0 float4 1.1 0.3 3.0 0.0 +draw quad +probe all rgba (1.1, 0.3, 0.0, 0.0) 4