-- v2: vkd3d-shader/hlsl: Support lit() intrinsic.
From: Nikolay Sivov nsivov@codeweavers.com
--- Makefile.am | 1 + libs/vkd3d-shader/hlsl.h | 2 + libs/vkd3d-shader/hlsl.y | 119 +++++++++++++++++++++++++++---- libs/vkd3d-shader/hlsl_codegen.c | 8 +-- tests/lit.shader_test | 62 ++++++++++++++++ 5 files changed, 176 insertions(+), 16 deletions(-) create mode 100644 tests/lit.shader_test
diff --git a/Makefile.am b/Makefile.am index f9199472..f5052a5d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -115,6 +115,7 @@ vkd3d_shader_tests = \ tests/hlsl-transpose.shader_test \ tests/hlsl-vector-indexing.shader_test \ tests/hlsl-vector-indexing-uniform.shader_test \ + tests/lit.shader_test \ tests/logic-operations.shader_test \ tests/math.shader_test \ tests/matrix-semantics.shader_test \ diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 81b1a61d..0183f702 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -972,6 +972,8 @@ struct vkd3d_string_buffer *hlsl_type_to_string(struct hlsl_ctx *ctx, const stru struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, unsigned int modifiers); const char *hlsl_node_type_to_string(enum hlsl_ir_node_type type);
+struct hlsl_ir_load *hlsl_add_conditional(struct hlsl_ctx *ctx, struct list *instrs, + struct hlsl_ir_node *condition, struct hlsl_ir_node *if_true, struct hlsl_ir_node *if_false); void hlsl_add_function(struct hlsl_ctx *ctx, char *name, struct hlsl_ir_function_decl *decl); bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var);
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 76b0eae7..236c8a67 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2610,6 +2610,111 @@ static bool intrinsic_lerp(struct hlsl_ctx *ctx, return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_ADD, params->args[0], mul, loc); }
+static struct hlsl_ir_node * add_pow_expr(struct hlsl_ctx *ctx, + struct list *instrs, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, + const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *log, *mul; + + if (!(log = add_unary_arithmetic_expr(ctx, instrs, HLSL_OP1_LOG2, arg1, loc))) + return NULL; + + if (!(mul = add_binary_arithmetic_expr(ctx, instrs, HLSL_OP2_MUL, arg2, log, loc))) + return NULL; + + return add_unary_arithmetic_expr(ctx, instrs, HLSL_OP1_EXP2, mul, loc); +} + +static bool intrinsic_lit(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *n_l_neg, *n_h_neg, *specular_or, *specular_pow; + struct hlsl_ir_constant *init, *zero; + struct hlsl_ir_node *n_l, *n_h, *m; + struct hlsl_ir_node *diffuse; + struct hlsl_ir_store *store; + struct hlsl_deref var_deref; + struct hlsl_type *ret_type; + struct hlsl_ir_load *load; + struct hlsl_ir_var *var; + struct hlsl_block block; + + if (params->args[0]->data_type->type != HLSL_CLASS_SCALAR + || params->args[1]->data_type->type != HLSL_CLASS_SCALAR + || params->args[2]->data_type->type != HLSL_CLASS_SCALAR) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "Invalid argument type."); + return false; + } + + if (!(n_l = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) + return false; + + if (!(n_h = intrinsic_float_convert_arg(ctx, params, params->args[1], loc))) + return false; + + if (!(m = intrinsic_float_convert_arg(ctx, params, params->args[2], loc))) + return false; + + ret_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4); + + if (!(var = hlsl_new_synthetic_var(ctx, "lit", ret_type, loc))) + return false; + hlsl_init_simple_deref_from_var(&var_deref, var); + + if (!(init = hlsl_new_constant(ctx, ret_type, loc))) + return false; + init->value[0].f = 1.0f; + init->value[1].f = 0.0f; + init->value[2].f = 0.0f; + init->value[3].f = 1.0f; + list_add_tail(params->instrs, &init->node.entry); + + if (!(store = hlsl_new_simple_store(ctx, var, &init->node))) + return false; + list_add_tail(params->instrs, &store->node.entry); + + if (!(zero = hlsl_new_float_constant(ctx, 0.0f, loc))) + return false; + list_add_tail(params->instrs, &zero->node.entry); + + /* Diffuse component. */ + if (!(diffuse = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MAX, n_l, &zero->node, loc))) + return false; + + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, 1, diffuse))) + return false; + list_move_tail(params->instrs, &block.instrs); + + /* Specular component. */ + if (!(n_h_neg = add_binary_comparison_expr(ctx, params->instrs, HLSL_OP2_LESS, + n_h, &zero->node, loc))) + return false; + + if (!(n_l_neg = add_binary_comparison_expr(ctx, params->instrs, HLSL_OP2_LESS, + n_l, &zero->node, loc))) + return false; + + if (!(specular_or = add_binary_logical_expr(ctx, params->instrs, HLSL_OP2_LOGIC_OR, n_l_neg, n_h_neg, loc))) + return false; + + if (!(specular_pow = add_pow_expr(ctx, params->instrs, n_h, m, loc))) + return false; + + if (!(load = hlsl_add_conditional(ctx, params->instrs, specular_or, &zero->node, specular_pow))) + return false; + + if (!(store = hlsl_new_store_component(ctx, &block, &var_deref, 2, &load->node))) + return false; + list_move_tail(params->instrs, &block.instrs); + + if (!(load = hlsl_new_var_load(ctx, var, *loc))) + return false; + list_add_tail(params->instrs, &load->node.entry); + + return true; +} + static bool intrinsic_max(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -2757,21 +2862,10 @@ static bool intrinsic_normalize(struct hlsl_ctx *ctx, static bool intrinsic_pow(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { - struct hlsl_ir_node *log, *exp, *mul; - if (!elementwise_intrinsic_float_convert_args(ctx, params, loc)) return false;
- if (!(log = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_LOG2, params->args[0], loc))) - return false; - - if (!(mul = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, params->args[1], log, loc))) - return false; - - if (!(exp = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_EXP2, mul, loc))) - return false; - - return true; + return !!add_pow_expr(ctx, params->instrs, params->args[0], params->args[1], loc); }
static bool intrinsic_round(struct hlsl_ctx *ctx, @@ -2977,6 +3071,7 @@ intrinsic_functions[] = {"ldexp", 2, true, intrinsic_ldexp}, {"length", 1, true, intrinsic_length}, {"lerp", 3, true, intrinsic_lerp}, + {"lit", 3, true, intrinsic_lit}, {"max", 2, true, intrinsic_max}, {"min", 2, true, intrinsic_min}, {"mul", 2, true, intrinsic_mul}, diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 80d52dfc..3874b992 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -1865,7 +1865,7 @@ static bool lower_casts_to_bool(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr return true; }
-static struct hlsl_ir_load *add_conditional(struct hlsl_ctx *ctx, struct list *instrs, +struct hlsl_ir_load *hlsl_add_conditional(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *condition, struct hlsl_ir_node *if_true, struct hlsl_ir_node *if_false) { struct hlsl_ir_store *store; @@ -1962,7 +1962,7 @@ static bool lower_int_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, return false; list_add_before(&instr->entry, &neg->entry);
- if (!(cond = add_conditional(ctx, &instr->entry, and, neg, &cast3->node))) + if (!(cond = hlsl_add_conditional(ctx, &instr->entry, and, neg, &cast3->node))) return false; hlsl_replace_node(instr, &cond->node);
@@ -2030,7 +2030,7 @@ static bool lower_int_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, return false; list_add_before(&instr->entry, &neg->entry);
- if (!(cond = add_conditional(ctx, &instr->entry, and, neg, &cast3->node))) + if (!(cond = hlsl_add_conditional(ctx, &instr->entry, and, neg, &cast3->node))) return false; hlsl_replace_node(instr, &cond->node);
@@ -2105,7 +2105,7 @@ static bool lower_float_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr return false; list_add_before(&instr->entry, &neg2->entry);
- if (!(cond = add_conditional(ctx, &instr->entry, ge, arg2, neg2))) + if (!(cond = hlsl_add_conditional(ctx, &instr->entry, ge, arg2, neg2))) return false;
if (!(one = hlsl_new_constant(ctx, type, &instr->loc))) diff --git a/tests/lit.shader_test b/tests/lit.shader_test new file mode 100644 index 00000000..729acef5 --- /dev/null +++ b/tests/lit.shader_test @@ -0,0 +1,62 @@ +[pixel shader] +float4 main(uniform float4 u) : sv_target +{ + return lit(u.x, u.y, u.z); +} + +[test] +uniform 0 float4 -0.1 10.0 0.0 0.0 +draw quad +probe all rgba (1.0, 0.0, 0.0, 1.0) + +[test] +uniform 0 float4 1.2 -0.1 0.0 0.0 +draw quad +probe all rgba (1.0, 1.2, 0.0, 1.0) + +[test] +uniform 0 float4 1.2 2.0 3.0 0.0 +draw quad +probe all rgba (1.0, 1.2, 8.0, 1.0) + +[pixel shader fail] +float4 main(uniform float4 u) : sv_target +{ + return lit(u.xy, u.y, u.z); +} + +[pixel shader fail] +float4 main(uniform float4 u) : sv_target +{ + return lit(u.x, u.xy, u.z); +} + +[pixel shader fail] +float4 main(uniform float4 u) : sv_target +{ + return lit(u.x, u.y, u.yz); +} + +[pixel shader fail] +uniform float4x4 m; + +float4 main(uniform float4 u) : sv_target +{ + return lit(m, u.y, u.z); +} + +[pixel shader fail] +uniform float4x4 m; + +float4 main(uniform float4 u) : sv_target +{ + return lit(u.x, m, u.z); +} + +[pixel shader fail] +uniform float4x4 m; + +float4 main(uniform float4 u) : sv_target +{ + return lit(u.x, u.y, m); +}
On Thu Feb 16 21:56:41 2023 +0000, Giovanni Mascellani wrote:
This shader causes an assertion to be thrown:
float4 main(uniform float4 u) : sv_target { lit(u.x, u.y, u); return float4(0.0, 0.0, 0.0, 0.0); }
Please, check the argument types in `intrinsic_lit()`. As usual, having a few tests with uncommon types would be great (and would have spotted this problem immediately).
Thanks, I added some failing test cases.
This merge request was approved by Francisco Casas.
This merge request was approved by Giovanni Mascellani.
This needs a (trivial) rebase after !80.