vkd3d-shader/hlsl: Improve SM1 support for non-float operations, part 3.
Mainly the implementation of SM1 comparison operators, defined in terms of CMP and SLT instructions, and the capacity to transform SLT->CMP for pixel shaders and CMP->SLT for vertex shaders.
Merge request reports
Activity
1348 1348 return hlsl_new_expr(ctx, op, operands, arg1->data_type, &arg1->loc); 1349 1349 } 1350 1350 1351 struct hlsl_ir_node *hlsl_new_ternary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, I see, I probably intended this for creating the CMP instruction. So I did that now.
Edited by Francisco Casas
3057 struct hlsl_constant_value zero_value; 3058 3059 memset(operands, 0, sizeof(operands)); 3060 operands[0] = arg2_cast; 3061 if (!(neg = hlsl_new_expr(ctx, HLSL_OP1_NEG, operands, float_type, &instr->loc))) 3062 return false; 3063 hlsl_block_add_instr(block, neg); 3064 3065 memset(operands, 0, sizeof(operands)); 3066 operands[0] = arg1_cast; 3067 operands[1] = neg; 3068 if (!(sub = hlsl_new_expr(ctx, HLSL_OP2_ADD, operands, float_type, &instr->loc))) 3069 return false; 3070 hlsl_block_add_instr(block, sub); 3071 3072 /* Use MUL as a precarious ABS. */ While according to the documentation the "abs" instruction exists for all shader profiles starting from ps_2_0 and vs_2_0, the native compiler doesn't use it directly.
- For both ps_2_0 and vs_2_0 it uses this mul trick, because we only care if the absolute value is not 0.
- I checked now and for ps_3_0 and vs_3_0 it adds the "_abs" modifier to the src registers of the comparison instruction.
So it may make sense to actually add the path to use ABS if the
profile->major_version
is larger than 2.0, similarly to what lower_ternary() does. I don't know if this is necessary, the only case I can think of where this differ is for very large values where the multiplication falls outside the representable range of as a float, but even in those cases (which I think map to "inf"?) the sign should also be correct.I will check what happens on Windows on these cases.
changed this line in version 2 of the diff
added 5 commits
- 77935062 - vkd3d-shader/hlsl: Implement SM1 comparison operators.
- 55dd6b45 - tests: Test equality between tiny and between large numbers on ps_2_0.
- 4b188e1f - vkd3d-shader/hlsl: Lower SLT instructions for pixel shaders.
- dc7d15d0 - vkd3d-shader/hlsl: Use hlsl_fixme() on missing SM1 matrix writemask lowering.
- f4f78656 - vkd3d-shader/hlsl: Lower CMP instructions for vertex shaders.
Toggle commit list- Resolved by Francisco Casas
- Resolved by Francisco Casas
3076 3077 if (!(slt = hlsl_new_binary_expr(ctx, HLSL_OP2_SLT, zero, mul))) 3078 return false; 3079 hlsl_block_add_instr(block, slt); 3080 3081 negate = (expr->op == HLSL_OP2_EQUAL); 3082 break; 3083 } 3084 case HLSL_OP2_GEQUAL: 3085 case HLSL_OP2_LESS: 3086 { 3087 if (!(slt = hlsl_new_binary_expr(ctx, HLSL_OP2_SLT, arg1_cast, arg2_cast))) 3088 return false; 3089 hlsl_block_add_instr(block, slt); 3090 3091 negate = (expr->op == HLSL_OP2_GEQUAL); I think that's fine too (reproducing the native code opcode by opcode has never been a target of our HLSL compiler), but it seems that SGE also exists and FXC is willing to emit it for
vs_3_0
: https://shader-playground.timjones.io/27b940d613fd9365f083b11bb18139bf, just in case at some point this turns out to be relevant (in theory<
and>=
are not exactly one the opposite of the other, because of NaNs, but SM1-3 mostly pretend NaNs do not exist).
added 5 commits
- ef82cf11 - vkd3d-shader/hlsl: Implement SM1 comparison operators.
- 5ec5fae3 - tests: Test equality between tiny and between large numbers on ps_2_0.
- e93ddb6e - vkd3d-shader/hlsl: Lower SLT instructions for pixel shaders.
- 1099abf6 - vkd3d-shader/hlsl: Use hlsl_fixme() on missing SM1 matrix writemask lowering.
- 2a9bcbb9 - vkd3d-shader/hlsl: Lower CMP instructions for vertex shaders.
Toggle commit list