-- v2: vkd3d-shader/hlsl: Support clip() intrinsic.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- Makefile.am | 1 + libs/vkd3d-shader/hlsl.y | 47 +++++++++++++++++++++++++++++++++++++ tests/hlsl-clip.shader_test | 22 +++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 tests/hlsl-clip.shader_test
diff --git a/Makefile.am b/Makefile.am index 0a61365d..ae5f5dcc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -79,6 +79,7 @@ vkd3d_shader_tests = \ tests/hlsl-attributes.shader_test \ tests/hlsl-bool-cast.shader_test \ tests/hlsl-clamp.shader_test \ + tests/hlsl-clip.shader_test \ tests/hlsl-comma.shader_test \ tests/hlsl-cross.shader_test \ tests/hlsl-d3dcolor-to-ubyte4.shader_test \ diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index dae1851c..c1e909ea 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2539,6 +2539,52 @@ static bool intrinsic_clamp(struct hlsl_ctx *ctx, return !!add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MIN, max, params->args[2], loc); }
+static bool intrinsic_clip(struct hlsl_ctx *ctx, + const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_node *zero, *bool_false, *or, *cmp, *load, *discard, *iff; + struct hlsl_block then_block; + unsigned int i, count; + + if (!elementwise_intrinsic_float_convert_args(ctx, params, loc)) + return false; + + if (!(zero = hlsl_new_float_constant(ctx, 0.0f, loc))) + return false; + list_add_tail(params->instrs, &zero->entry); + + if (!(cmp = add_binary_comparison_expr(ctx, params->instrs, HLSL_OP2_LESS, params->args[0], zero, loc))) + return false; + + if (!(bool_false = hlsl_new_bool_constant(ctx, false, loc))) + return false; + list_add_tail(params->instrs, &bool_false->entry); + + or = bool_false; + + count = hlsl_type_component_count(cmp->data_type); + for (i = 0; i < count; ++i) + { + if (!(load = add_load_component(ctx, params->instrs, cmp, i, loc))) + return false; + + if (!(or = add_binary_logical_expr(ctx, params->instrs, HLSL_OP2_LOGIC_OR, or, load, loc))) + return false; + } + + hlsl_block_init(&then_block); + + if (!(discard = hlsl_new_jump(ctx, HLSL_IR_JUMP_DISCARD, loc))) + return false; + hlsl_block_add_instr(&then_block, discard); + + if (!(iff = hlsl_new_if(ctx, or, &then_block, NULL, loc))) + return false; + list_add_tail(params->instrs, &iff->entry); + + return true; +} + static bool intrinsic_cos(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { @@ -3482,6 +3528,7 @@ intrinsic_functions[] = {"asfloat", 1, true, intrinsic_asfloat}, {"asuint", -1, true, intrinsic_asuint}, {"clamp", 3, true, intrinsic_clamp}, + {"clip", 1, true, intrinsic_clip}, {"cos", 1, true, intrinsic_cos}, {"cross", 2, true, intrinsic_cross}, {"ddx", 1, true, intrinsic_ddx}, diff --git a/tests/hlsl-clip.shader_test b/tests/hlsl-clip.shader_test new file mode 100644 index 00000000..f9859e1b --- /dev/null +++ b/tests/hlsl-clip.shader_test @@ -0,0 +1,22 @@ +[pixel shader] +uniform float4 x; + +float4 main() : sv_target +{ + clip(x); + return x; +} + +[test] +uniform 0 float4 1 2 3 4 +draw quad +probe all rgba (1, 2, 3, 4) +uniform 0 float4 9 8 7 6 +draw quad +probe all rgba (9, 8, 7, 6) +uniform 0 float4 -1 8 7 6 +draw quad +probe all rgba (9, 8, 7, 6) +uniform 0 float4 9 0 7 6 +draw quad +probe all rgba (9, 0, 7, 6)
On Wed May 24 17:21:09 2023 +0000, Zebediah Figura wrote:
This should be LOGIC_OR.
Thanks, it was copied from any(), which probably has to be changed too.
This merge request was approved by Zebediah Figura.
For what it's worth, I think this pretty much corresponds to shader model 1-3 texkill.
On Wed May 24 20:23:01 2023 +0000, Henri Verbeet wrote:
For what it's worth, I think this pretty much corresponds to shader model 1-3 texkill.
It does, and I was considering saying that we should make it a HLSL op accordingly. On reflection, though, I decided we probably don't, but rather we probably want to do a "raising" peephole. I wouldn't be surprised if there are programs out there that spell out clip() as something like "if (any(x < 0)) discard".
Then again, if I write that out in a shader, native d3dcompiler doesn't seem capable of optimizing that all the way down to texkill()...
However, while testing, I did just discover that both sm1 texkill and HLSL clip() actually only check the first 3 components, so this patch needs to be fixed accordingly.
Sorry, it turns out this was wrong. I misread sm4 output, and while 1.x does ignore the w component, 2.x and 3.x do not.
This merge request was approved by Zebediah Figura.