From: Giovanni Mascellani gmascellani@codeweavers.com
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index aa89b6a0..4118ce88 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -1637,6 +1637,11 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, write_sm4_unary_op(buffer, VKD3D_SM4_OP_ROUND_NI, &expr->node, arg1, 0); break;
+ case HLSL_OP1_FRACT: + assert(type_is_float(dst_type)); + write_sm4_unary_op(buffer, VKD3D_SM4_OP_FRC, &expr->node, arg1, 0); + break; + case HLSL_OP1_LOG2: assert(type_is_float(dst_type)); write_sm4_unary_op(buffer, VKD3D_SM4_OP_LOG, &expr->node, arg1, 0);
From: Giovanni Mascellani gmascellani@codeweavers.com
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 69 ++++++++++++++++++++++++ tests/arithmetic-int-uniform.shader_test | 2 +- 2 files changed, 70 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 656e2e93..18e35736 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1388,6 +1388,74 @@ static bool lower_int_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, return true; }
+static bool lower_int_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + struct hlsl_ir_node *arg1, *arg2, *and, *abs1, *abs2, *div, *neg; + struct hlsl_type *type = instr->data_type, *utype; + struct hlsl_ir_expr *cast1, *cast2, *cast3; + struct hlsl_ir_constant *high_bit; + struct hlsl_ir_expr *expr; + struct hlsl_ir_load *cond; + unsigned int i; + + if (instr->type != HLSL_IR_EXPR) + return false; + expr = hlsl_ir_expr(instr); + arg1 = expr->operands[0].node; + arg2 = expr->operands[1].node; + if (expr->op != HLSL_OP2_MOD) + return false; + if (type->type != HLSL_CLASS_SCALAR && type->type != HLSL_CLASS_VECTOR) + return false; + if (type->base_type != HLSL_TYPE_INT) + return false; + utype = hlsl_get_numeric_type(ctx, type->type, HLSL_TYPE_UINT, type->dimx, type->dimy); + + if (!(high_bit = hlsl_new_constant(ctx, type, &instr->loc))) + return false; + for (i = 0; i < type->dimx; ++i) + high_bit->value[i].u = 0x80000000; + list_add_before(&instr->entry, &high_bit->node.entry); + + if (!(and = hlsl_new_binary_expr(ctx, HLSL_OP2_BIT_AND, arg1, &high_bit->node))) + return false; + list_add_before(&instr->entry, &and->entry); + + if (!(abs1 = hlsl_new_unary_expr(ctx, HLSL_OP1_ABS, arg1, instr->loc))) + return false; + list_add_before(&instr->entry, &abs1->entry); + + if (!(cast1 = hlsl_new_cast(ctx, abs1, utype, &instr->loc))) + return false; + list_add_before(&instr->entry, &cast1->node.entry); + + if (!(abs2 = hlsl_new_unary_expr(ctx, HLSL_OP1_ABS, arg2, instr->loc))) + return false; + list_add_before(&instr->entry, &abs2->entry); + + if (!(cast2 = hlsl_new_cast(ctx, abs2, utype, &instr->loc))) + return false; + list_add_before(&instr->entry, &cast2->node.entry); + + if (!(div = hlsl_new_binary_expr(ctx, HLSL_OP2_MOD, &cast1->node, &cast2->node))) + return false; + list_add_before(&instr->entry, &div->entry); + + if (!(cast3 = hlsl_new_cast(ctx, div, type, &instr->loc))) + return false; + list_add_before(&instr->entry, &cast3->node.entry); + + if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, &cast3->node, instr->loc))) + return false; + list_add_before(&instr->entry, &neg->entry); + + if (!(cond = add_conditional(ctx, &instr->entry, and, neg, &cast3->node))) + return false; + hlsl_replace_node(instr, &cond->node); + + return true; +} + static bool lower_int_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) { struct hlsl_type *type = instr->data_type; @@ -2402,6 +2470,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry transform_ir(ctx, lower_narrowing_casts, body, NULL); transform_ir(ctx, lower_casts_to_bool, body, NULL); transform_ir(ctx, lower_int_division, body, NULL); + transform_ir(ctx, lower_int_modulus, body, NULL); transform_ir(ctx, lower_int_abs, body, NULL); do { diff --git a/tests/arithmetic-int-uniform.shader_test b/tests/arithmetic-int-uniform.shader_test index 3190be00..cac2a234 100644 --- a/tests/arithmetic-int-uniform.shader_test +++ b/tests/arithmetic-int-uniform.shader_test @@ -25,7 +25,7 @@ float4 main() : SV_TARGET
[test] uniform 0 float4 5.0 16.0 0.0 0.0 -todo draw quad +draw quad probe all rgba (5.0, 5.0, -5.0, 3.0)
[pixel shader]
From: Giovanni Mascellani gmascellani@codeweavers.com
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- libs/vkd3d-shader/hlsl_codegen.c | 70 ++++++++++++++++++++++++++++++ tests/arithmetic-float.shader_test | 2 +- 2 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 18e35736..aacaa95c 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1485,6 +1485,75 @@ static bool lower_int_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void return true; }
+static bool lower_float_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + struct hlsl_ir_node *arg1, *arg2, *mul1, *neg1, *ge, *neg2, *div, *mul2, *frc; + struct hlsl_type *type = instr->data_type, *btype; + struct hlsl_ir_constant *one; + struct hlsl_ir_load *cond; + struct hlsl_ir_expr *expr; + unsigned int i; + + if (instr->type != HLSL_IR_EXPR) + return false; + expr = hlsl_ir_expr(instr); + arg1 = expr->operands[0].node; + arg2 = expr->operands[1].node; + if (expr->op != HLSL_OP2_MOD) + return false; + if (type->type != HLSL_CLASS_SCALAR && type->type != HLSL_CLASS_VECTOR) + return false; + if (type->base_type != HLSL_TYPE_FLOAT) + return false; + btype = hlsl_get_numeric_type(ctx, type->type, HLSL_TYPE_BOOL, type->dimx, type->dimy); + + if (!(mul1 = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, arg2, arg1))) + return false; + list_add_before(&instr->entry, &mul1->entry); + + if (!(neg1 = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, mul1, instr->loc))) + return false; + list_add_before(&instr->entry, &neg1->entry); + + if (!(ge = hlsl_new_binary_expr(ctx, HLSL_OP2_GEQUAL, mul1, neg1))) + return false; + ge->data_type = btype; + list_add_before(&instr->entry, &ge->entry); + + if (!(neg2 = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, arg2, instr->loc))) + return false; + list_add_before(&instr->entry, &neg2->entry); + + if (!(cond = add_conditional(ctx, &instr->entry, ge, arg2, neg2))) + return false; + + if (!(one = hlsl_new_constant(ctx, type, &instr->loc))) + return false; + for (i = 0; i < type->dimx; ++i) + one->value[i].f = 1.0f; + list_add_before(&instr->entry, &one->node.entry); + + if (!(div = hlsl_new_binary_expr(ctx, HLSL_OP2_DIV, &one->node, &cond->node))) + return false; + list_add_before(&instr->entry, &div->entry); + + if (!(mul2 = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, div, arg1))) + return false; + list_add_before(&instr->entry, &mul2->entry); + + if (!(frc = hlsl_new_unary_expr(ctx, HLSL_OP1_FRACT, mul2, instr->loc))) + return false; + list_add_before(&instr->entry, &frc->entry); + + expr->op = HLSL_OP2_MUL; + hlsl_src_remove(&expr->operands[0]); + hlsl_src_remove(&expr->operands[1]); + hlsl_src_from_node(&expr->operands[0], frc); + hlsl_src_from_node(&expr->operands[1], &cond->node); + + return true; +} + static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) { switch (instr->type) @@ -2472,6 +2541,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry transform_ir(ctx, lower_int_division, body, NULL); transform_ir(ctx, lower_int_modulus, body, NULL); transform_ir(ctx, lower_int_abs, body, NULL); + transform_ir(ctx, lower_float_modulus, body, NULL); do { progress = transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL); diff --git a/tests/arithmetic-float.shader_test b/tests/arithmetic-float.shader_test index 6824c3f1..36838d95 100644 --- a/tests/arithmetic-float.shader_test +++ b/tests/arithmetic-float.shader_test @@ -21,7 +21,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (5.0, 5.0, -5.0, 3.0)
[require]
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/arithmetic-int-uniform.shader_test | 60 ++++++++++++++++++++++++ tests/arithmetic-int.shader_test | 52 ++++++++++++++++++++ 2 files changed, 112 insertions(+)
diff --git a/tests/arithmetic-int-uniform.shader_test b/tests/arithmetic-int-uniform.shader_test index cac2a234..bd35f566 100644 --- a/tests/arithmetic-int-uniform.shader_test +++ b/tests/arithmetic-int-uniform.shader_test @@ -28,6 +28,66 @@ uniform 0 float4 5.0 16.0 0.0 0.0 draw quad probe all rgba (5.0, 5.0, -5.0, 3.0)
+[pixel shader] +uniform float2 a; + +float4 main() : SV_TARGET +{ + int x = a.x; + int y = a.y; + return float4(x / y, -x / y, x / -y, -x / -y); +} + +[test] +uniform 0 float4 42.0 5.0 0.0 0.0 +draw quad +probe all rgba (8.0, -8.0, -8.0, 8.0) + +[pixel shader] +uniform float2 a; + +float4 main() : SV_TARGET +{ + int x = a.x; + int y = a.y; + return float4(x % y, -x % y, x % -y, -x % -y); +} + +[test] +uniform 0 float4 42.0 5.0 0.0 0.0 +draw quad +probe all rgba (2.0, -2.0, 2.0, -2.0) + +[pixel shader] +uniform float2 a; + +float4 main() : SV_TARGET +{ + int x = a.x; + int y = a.y; + return float4(x / y, -x / y, x / -y, -x / -y); +} + +[test] +uniform 0 float4 45.0 5.0 0.0 0.0 +draw quad +probe all rgba (9.0, -9.0, -9.0, 9.0) + +[pixel shader] +uniform float2 a; + +float4 main() : SV_TARGET +{ + int x = a.x; + int y = a.y; + return float4(x % y, -x % y, x % -y, -x % -y); +} + +[test] +uniform 0 float4 45.0 5.0 0.0 0.0 +draw quad +probe all rgba (0.0, 0.0, 0.0, 0.0) + [pixel shader] uniform float4 a;
diff --git a/tests/arithmetic-int.shader_test b/tests/arithmetic-int.shader_test index 8b6d6d7c..f4c98904 100644 --- a/tests/arithmetic-int.shader_test +++ b/tests/arithmetic-int.shader_test @@ -24,6 +24,58 @@ float4 main() : SV_TARGET draw quad probe all rgba (5.0, 5.0, -5.0, 3.0)
+[pixel shader] +float4 main() : SV_TARGET +{ + int x = 42; + int y = 5; + + return float4(x / y, -x / y, x / -y, -x / -y); +} + +[test] +draw quad +probe all rgba (8.0, -8.0, -8.0, 8.0) + +[pixel shader] +float4 main() : SV_TARGET +{ + int x = 42; + int y = 5; + + return float4(x % y, -x % y, x % -y, -x % -y); +} + +[test] +draw quad +probe all rgba (2.0, -2.0, 2.0, -2.0) + +[pixel shader] +float4 main() : SV_TARGET +{ + int x = 45; + int y = 5; + + return float4(x / y, -x / y, x / -y, -x / -y); +} + +[test] +draw quad +probe all rgba (9.0, -9.0, -9.0, 9.0) + +[pixel shader] +float4 main() : SV_TARGET +{ + int x = 45; + int y = 5; + + return float4(x % y, -x % y, x % -y, -x % -y); +} + +[test] +draw quad +probe all rgba (0.0, 0.0, 0.0, 0.0) + [pixel shader fail] float4 main() : SV_TARGET {
From: Giovanni Mascellani gmascellani@codeweavers.com
--- tests/arithmetic-float.shader_test | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/tests/arithmetic-float.shader_test b/tests/arithmetic-float.shader_test index 36838d95..558d5d10 100644 --- a/tests/arithmetic-float.shader_test +++ b/tests/arithmetic-float.shader_test @@ -24,6 +24,32 @@ float4 main() : SV_TARGET draw quad probe all rgba (5.0, 5.0, -5.0, 3.0)
+[pixel shader] +float4 main() : SV_TARGET +{ + float x = 42; + float y = 5; + + return float4(x % y, -x % y, x % -y, -x % -y); +} + +[test] +draw quad +probe all rgba (2.0, -2.0, 2.0, -2.0) 16 + +[pixel shader] +float4 main() : SV_TARGET +{ + float x = 45; + float y = 5; + + return float4(x % y, -x % y, x % -y, -x % -y); +} + +[test] +draw quad +probe all rgba (0.0, 0.0, 0.0, 0.0) + [require] % Infinities are not allowed in SM1 shader model >= 4.0
From: Giovanni Mascellani gmascellani@codeweavers.com
The point of the "uniform" variants is to avoid hiding code generation bugs because of the constant folding optimization. --- Makefile.am | 1 + tests/arithmetic-float-uniform.shader_test | 78 ++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 tests/arithmetic-float-uniform.shader_test
diff --git a/Makefile.am b/Makefile.am index b9068728..5a5a01c4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -53,6 +53,7 @@ vkd3d_cross_tests = \ vkd3d_shader_tests = \ tests/abs.shader_test \ tests/arithmetic-float.shader_test \ + tests/arithmetic-float-uniform.shader_test \ tests/arithmetic-int.shader_test \ tests/arithmetic-int-uniform.shader_test \ tests/arithmetic-uint.shader_test \ diff --git a/tests/arithmetic-float-uniform.shader_test b/tests/arithmetic-float-uniform.shader_test new file mode 100644 index 00000000..708dc270 --- /dev/null +++ b/tests/arithmetic-float-uniform.shader_test @@ -0,0 +1,78 @@ +[pixel shader] +uniform float2 a; + +float4 main() : SV_TARGET +{ + float x = a.x; + float y = a.y; + return float4(x + y, x - y, x * y, x / y); +} + +[test] +uniform 0 float4 5.0 15.0 0.0 0.0 +draw quad +probe all rgba (20.0, -10.0, 75.0, 0.33333333) 1 + +[pixel shader] +uniform float2 a; + +float4 main() : SV_TARGET +{ + float x = a.x; + float y = a.y; + return float4(x % y, +x, -x, y / x); +} + +[test] +uniform 0 float4 5.0 15.0 0.0 0.0 +draw quad +probe all rgba (5.0, 5.0, -5.0, 3.0) 1 + +[pixel shader] +uniform float2 a; + +float4 main() : SV_TARGET +{ + float x = a.x; + float y = a.y; + return float4(x % y, -x % y, x % -y, -x % -y); +} + +[test] +uniform 0 float4 42.0 5.0 0.0 0.0 +draw quad +probe all rgba (2.0, -2.0, 2.0, -2.0) 16 + +[pixel shader] +uniform float2 a; + +float4 main() : SV_TARGET +{ + float x = a.x; + float y = a.y; + return float4(x % y, -x % y, x % -y, -x % -y); +} + +[test] +uniform 0 float4 45.0 5.0 0.0 0.0 +draw quad +probe all rgba (0.0, 0.0, 0.0, 0.0) + +[require] +% Infinities are not allowed in SM1 +shader model >= 4.0 + +[pixel shader] +uniform float2 a; + +float4 main() : SV_TARGET +{ + float x = a.x; + float y = a.y; + return x / y; +} + +[test] +uniform 0 float4 1.0 0.0 0.0 0.0 +draw quad +probe all rgba (1e99, 1e99, 1e99, 1e99)
This merge request was approved by Zebediah Figura.
This merge request was approved by Henri Verbeet.