From 4467c655f04be55ee3a9bcfae555c8e0c794a060 Mon Sep 17 00:00:00 2001 From: Petrichor Park Date: Wed, 14 Aug 2024 13:53:25 -0500 Subject: [PATCH] vkd3d-shader/hlsl: Factor out add_binary_expr() and use it for assignment operators. This fixes a lot of internal compiler errors with assignment operators, especially bitwise ones. The bitwise-assignment test has the motivating examples. --- libs/vkd3d-shader/hlsl.y | 74 +++++++-------- tests/hlsl/bitwise-assignment.shader_test | 104 ++++++++++++++++++++++ tests/hlsl/bitwise.shader_test | 18 ++++ 3 files changed, 160 insertions(+), 36 deletions(-) create mode 100644 tests/hlsl/bitwise-assignment.shader_test diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 3273d73b..3f319dea 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1899,6 +1899,41 @@ static struct hlsl_ir_node *add_binary_dot_expr(struct hlsl_ctx *ctx, struct hls return add_expr(ctx, instrs, op, args, ret_type, loc); } +static struct hlsl_ir_node *add_binary_expr(struct hlsl_ctx *ctx, struct hlsl_block *block, enum hlsl_ir_expr_op op, + struct hlsl_ir_node *lhs, struct hlsl_ir_node *rhs, const struct vkd3d_shader_location *loc) +{ + switch (op) + { + case HLSL_OP2_ADD: + case HLSL_OP2_DIV: + case HLSL_OP2_MOD: + case HLSL_OP2_MUL: + return add_binary_arithmetic_expr(ctx, block, op, lhs, rhs, loc); + + case HLSL_OP2_BIT_AND: + case HLSL_OP2_BIT_OR: + case HLSL_OP2_BIT_XOR: + return add_binary_bitwise_expr(ctx, block, op, lhs, rhs, loc); + + case HLSL_OP2_LESS: + case HLSL_OP2_GEQUAL: + case HLSL_OP2_EQUAL: + case HLSL_OP2_NEQUAL: + return add_binary_comparison_expr(ctx, block, op, lhs, rhs, loc); + + case HLSL_OP2_LOGIC_AND: + case HLSL_OP2_LOGIC_OR: + return add_binary_logical_expr(ctx, block, op, lhs, rhs, loc); + + case HLSL_OP2_LSHIFT: + case HLSL_OP2_RSHIFT: + return add_binary_shift_expr(ctx, block, op, lhs, rhs, loc); + + default: + vkd3d_unreachable(); + } +} + static struct hlsl_block *add_binary_expr_merge(struct hlsl_ctx *ctx, struct hlsl_block *block1, struct hlsl_block *block2, enum hlsl_ir_expr_op op, const struct vkd3d_shader_location *loc) { @@ -1907,41 +1942,8 @@ static struct hlsl_block *add_binary_expr_merge(struct hlsl_ctx *ctx, struct hls hlsl_block_add_block(block1, block2); destroy_block(block2); - switch (op) - { - case HLSL_OP2_ADD: - case HLSL_OP2_DIV: - case HLSL_OP2_MOD: - case HLSL_OP2_MUL: - add_binary_arithmetic_expr(ctx, block1, op, arg1, arg2, loc); - break; - - case HLSL_OP2_BIT_AND: - case HLSL_OP2_BIT_OR: - case HLSL_OP2_BIT_XOR: - add_binary_bitwise_expr(ctx, block1, op, arg1, arg2, loc); - break; - - case HLSL_OP2_LESS: - case HLSL_OP2_GEQUAL: - case HLSL_OP2_EQUAL: - case HLSL_OP2_NEQUAL: - add_binary_comparison_expr(ctx, block1, op, arg1, arg2, loc); - break; - - case HLSL_OP2_LOGIC_AND: - case HLSL_OP2_LOGIC_OR: - add_binary_logical_expr(ctx, block1, op, arg1, arg2, loc); - break; - - case HLSL_OP2_LSHIFT: - case HLSL_OP2_RSHIFT: - add_binary_shift_expr(ctx, block1, op, arg1, arg2, loc); - break; - - default: - vkd3d_unreachable(); - } + if (add_binary_expr(ctx, block1, op, arg1, arg2, loc) == NULL) + return NULL; return block1; } @@ -2065,7 +2067,7 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct hlsl_blo enum hlsl_ir_expr_op op = op_from_assignment(assign_op); VKD3D_ASSERT(op); - if (!(rhs = add_binary_arithmetic_expr(ctx, block, op, lhs, rhs, &rhs->loc))) + if (!(rhs = add_binary_expr(ctx, block, op, lhs, rhs, &rhs->loc))) return NULL; } diff --git a/tests/hlsl/bitwise-assignment.shader_test b/tests/hlsl/bitwise-assignment.shader_test new file mode 100644 index 00000000..5e29ae11 --- /dev/null +++ b/tests/hlsl/bitwise-assignment.shader_test @@ -0,0 +1,104 @@ +[require] +shader model >= 4.0 + +[pixel shader] +uniform uint4 nonconst; + +float4 main() : SV_TARGET +{ + uint a = 35, r = 2; + + uint shifted = a; shifted >>= nonconst.x; + a >>= r; + return float4(a, shifted, 0, 0); +} + +[test] +uniform 0 uint4 2 0 0 0 +todo(glsl) draw quad +probe (0, 0) rgba (8, 8, 0, 0) + +[pixel shader] +uniform uint4 nonconst; + +float4 main() : SV_TARGET +{ + int a = 5, b = -12; + uint r = 1; + + int shifted_a = a; shifted_a >>= nonconst.x; + int shifted_b = b; shifted_b >>= nonconst.x; + a >>= r; + b >>= r; + return float4(a, b, shifted_a, shifted_b); +} + +[test] +uniform 0 uint4 1 0 0 0 +todo(glsl) draw quad +probe (0, 0) rgba (2, -6, 2, -6) + +[pixel shader] +uniform uint4 nonconst; + +float4 main() : SV_TARGET +{ + uint a = 35, r = 3; + + uint shifted = a; shifted <<= nonconst.x; + a <<= r; + return float4(a, shifted, 0, 0); +} + +[test] +uniform 0 uint4 3 0 0 0 +todo(glsl) draw quad +probe (0, 0) rgba (280, 280, 0, 0) + +[pixel shader] +uniform uint4 nonconst; + +float4 main() : SV_TARGET +{ + int a = 5, b = -12; + uint r = 2; + + int shifted_a = a; shifted_a <<= nonconst.x; + int shifted_b = b; shifted_b <<= nonconst.x; + a <<= r; + b <<= r; + return float4(a, b, shifted_a, shifted_b); +} + +[test] +uniform 0 uint4 2 0 0 0 +todo(glsl) draw quad +probe (0, 0) rgba (20, -48, 20, -48) + +[pixel shader fail] +% Make sure that bitshifts DON'T work with floats +float4 main() : SV_TARGET +{ + float x = 5.0, y = 15.0; + x <<= y; + y <<= x; + return float4(x, y, 0, 0); +} + +[pixel shader] +float4 main() : SV_TARGET +{ + int source = 55; + int i = -0x4141; + uint u = 128; + + int a = source; a &= i; + int b = source; b |= u; + int c = source; c ^= i; + + return float4(a, b, c, 0); +} + +[test] +todo(glsl) draw quad +probe (0, 0) rgba (55, 183, -16760, 0) diff --git a/tests/hlsl/bitwise.shader_test b/tests/hlsl/bitwise.shader_test index f098cb85..bd41f116 100644 --- a/tests/hlsl/bitwise.shader_test +++ b/tests/hlsl/bitwise.shader_test @@ -129,6 +129,24 @@ float4 main() : SV_TARGET todo(glsl) draw quad probe (0, 0) rgba (0.0, 0.0, 163840.0, 480.0) +[pixel shader fail] +% Make sure that bitshifts DON'T work with floats +float4 main() : SV_TARGET +{ + uint u = 5; + float f = 15.0; + + return float4(u >> f, 0, 0, 0); +} +[pixel shader fail] +float4 main() : SV_TARGET +{ + uint u = 5; + float f = 15.0; + + return float4(f >> u, 0, 0, 0); +} + [pixel shader] float4 main() : SV_TARGET {