From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl_sm1.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm1.c b/libs/vkd3d-shader/hlsl_sm1.c index 5050b7a9..e299aa1b 100644 --- a/libs/vkd3d-shader/hlsl_sm1.c +++ b/libs/vkd3d-shader/hlsl_sm1.c @@ -609,12 +609,28 @@ static void write_sm1_constant(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffe write_sm1_instruction(ctx, buffer, &sm1_instr); }
+static void write_sm1_per_component_unary_op(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, + const struct hlsl_ir_node *instr, D3DSHADER_INSTRUCTION_OPCODE_TYPE opcode) +{ + struct hlsl_ir_expr *expr = hlsl_ir_expr(instr); + struct hlsl_ir_node *arg1 = expr->operands[0].node; + unsigned int i; + + for (i = 0; i < instr->data_type->dimx; ++i) + { + struct hlsl_reg src = arg1->reg, dst = instr->reg; + + src.writemask = hlsl_combine_writemasks(src.writemask, 1u << i); + dst.writemask = hlsl_combine_writemasks(dst.writemask, 1u << i); + write_sm1_unary_op(ctx, buffer, opcode, &dst, &src, 0); + } +} + static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_node *instr) { struct hlsl_ir_expr *expr = hlsl_ir_expr(instr); struct hlsl_ir_node *arg1 = expr->operands[0].node; struct hlsl_ir_node *arg2 = expr->operands[1].node; - unsigned int i;
assert(instr->reg.allocated);
@@ -632,15 +648,11 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b break;
case HLSL_OP1_RCP: - case HLSL_OP1_RSQ: - for (i = 0; i < instr->data_type->dimx; ++i) - { - struct hlsl_reg src = arg1->reg, dst = instr->reg; + write_sm1_per_component_unary_op(ctx, buffer, instr, D3DSIO_RCP); + break;
- src.writemask = hlsl_combine_writemasks(src.writemask, 1u << i); - dst.writemask = hlsl_combine_writemasks(dst.writemask, 1u << i); - write_sm1_unary_op(ctx, buffer, expr->op == HLSL_OP1_RCP ? D3DSIO_RCP : D3DSIO_RSQ, &dst, &src, 0); - } + case HLSL_OP1_RSQ: + write_sm1_per_component_unary_op(ctx, buffer, instr, D3DSIO_RSQ); break;
case HLSL_OP2_ADD:
From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl_sm1.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm1.c b/libs/vkd3d-shader/hlsl_sm1.c index e299aa1b..a66d4028 100644 --- a/libs/vkd3d-shader/hlsl_sm1.c +++ b/libs/vkd3d-shader/hlsl_sm1.c @@ -643,6 +643,10 @@ static void write_sm1_expr(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *b
switch (expr->op) { + case HLSL_OP1_EXP2: + write_sm1_per_component_unary_op(ctx, buffer, instr, D3DSIO_EXP); + break; + case HLSL_OP1_NEG: write_sm1_unary_op(ctx, buffer, D3DSIO_MOV, &instr->reg, &arg1->reg, D3DSPSM_NEG); break;
From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index bca49ee6..3eee09ae 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2491,6 +2491,17 @@ static bool intrinsic_dot(struct hlsl_ctx *ctx, return !!add_binary_dot_expr(ctx, params->instrs, params->args[0], params->args[1], loc); }
+static bool intrinsic_exp2(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *arg; + + if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) + return false; + + return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_EXP2, arg, loc); +} + static bool intrinsic_floor(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -2932,6 +2943,7 @@ intrinsic_functions[] = {"cos", 1, true, intrinsic_cos}, {"cross", 2, true, intrinsic_cross}, {"dot", 2, true, intrinsic_dot}, + {"exp2", 1, true, intrinsic_exp2}, {"floor", 1, true, intrinsic_floor}, {"frac", 1, true, intrinsic_frac}, {"ldexp", 2, true, intrinsic_ldexp},
From: Nikolay Sivov nsivov@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 3eee09ae..77355724 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2491,6 +2491,26 @@ static bool intrinsic_dot(struct hlsl_ctx *ctx, return !!add_binary_dot_expr(ctx, params->instrs, params->args[0], params->args[1], loc); }
+static bool intrinsic_exp(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_constant *coeff; + struct hlsl_ir_node *arg, *mul; + + if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) + return false; + + /* 1/ln(2) */ + if (!(coeff = hlsl_new_float_constant(ctx, 1.442695, loc))) + return false; + list_add_tail(params->instrs, &coeff->node.entry); + + if (!(mul = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, &coeff->node, params->args[0], loc))) + return false; + + return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_EXP2, mul, loc); +} + static bool intrinsic_exp2(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -2943,6 +2963,7 @@ intrinsic_functions[] = {"cos", 1, true, intrinsic_cos}, {"cross", 2, true, intrinsic_cross}, {"dot", 2, true, intrinsic_dot}, + {"exp", 1, true, intrinsic_exp}, {"exp2", 1, true, intrinsic_exp2}, {"floor", 1, true, intrinsic_floor}, {"frac", 1, true, intrinsic_frac},
From: Nikolay Sivov nsivov@codeweavers.com
--- Makefile.am | 1 + tests/exp.shader_test | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/exp.shader_test
diff --git a/Makefile.am b/Makefile.am index b237b4af..2b731111 100644 --- a/Makefile.am +++ b/Makefile.am @@ -59,6 +59,7 @@ vkd3d_shader_tests = \ tests/cbuffer.shader_test \ tests/compute.shader_test \ tests/conditional.shader_test \ + tests/exp.shader_test \ tests/floor.shader_test \ tests/frac.shader_test \ tests/hlsl-array-dimension.shader_test \ diff --git a/tests/exp.shader_test b/tests/exp.shader_test new file mode 100644 index 00000000..de3be685 --- /dev/null +++ b/tests/exp.shader_test @@ -0,0 +1,25 @@ +[pixel shader] +uniform float4 f; + +float4 main() : sv_target +{ + return exp2(f); +} + +[test] +uniform 0 float4 -1.0 0.0 1.0 2.0 +draw quad +probe all rgba (0.5, 1.0, 2.0, 4.0) 1 + +[pixel shader] +uniform float4 f; + +float4 main() : sv_target +{ + return exp(f); +} + +[test] +uniform 0 float4 -1.0 0.0 1.0 2.0 +draw quad +probe all rgba (0.36787948, 1.0, 2.7182815, 7.38905573) 2
+ /* 1/ln(2) */ + if (!(coeff = hlsl_new_float_constant(ctx, 1.442695, loc))) + return false;
hlsl_new_float_constant() takes a float argument, but we're passing it a double here. Some compilers complain about that, but it seems good practice to use a float literal here in any case.
Ok, sure. It's used like that in all other cases too, I'll change that separately later.