Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 44 ++++++++++++++++++++++++++++-- tests/cast-to-float.shader_test | 2 +- tests/cast-to-int.shader_test | 4 +-- tests/cast-to-uint.shader_test | 4 +-- tests/hlsl-bool-cast.shader_test | 18 ++++++++++++ tests/logic-operations.shader_test | 6 ++-- 6 files changed, 67 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 79027169..23678498 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -1459,6 +1459,44 @@ static bool type_is_float(const struct hlsl_type *type) return type->base_type == HLSL_TYPE_FLOAT || type->base_type == HLSL_TYPE_HALF; }
+static void write_sm4_cast_from_bool(struct hlsl_ctx *ctx, + struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_expr *expr, + const struct hlsl_ir_node *arg) +{ + struct sm4_instruction instr; + uint32_t c; + + switch (expr->node.data_type->base_type) + { + case HLSL_TYPE_FLOAT: + c = 0x3f800000; + break; + + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: + c = 1; + break; + + default: + assert(0); + } + + memset(&instr, 0, sizeof(instr)); + instr.opcode = VKD3D_SM4_OP_AND; + + sm4_dst_from_node(&instr.dsts[0], &expr->node); + instr.dst_count = 1; + + sm4_src_from_node(&instr.srcs[0], arg, instr.dsts[0].writemask); + instr.srcs[1].swizzle_type = VKD3D_SM4_SWIZZLE_NONE; + instr.srcs[1].reg.type = VKD3D_SM4_RT_IMMCONST; + instr.srcs[1].reg.dim = VKD3D_SM4_DIMENSION_SCALAR; + instr.srcs[1].reg.immconst_uint[0] = c; + instr.src_count = 2; + + write_sm4_instruction(buffer, &instr); +} + static void write_sm4_cast(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_expr *expr) { @@ -1488,7 +1526,7 @@ static void write_sm4_cast(struct hlsl_ctx *ctx, break;
case HLSL_TYPE_BOOL: - hlsl_fixme(ctx, &expr->node.loc, "SM4 cast from bool to float."); + write_sm4_cast_from_bool(ctx, buffer, expr, arg1); break;
case HLSL_TYPE_DOUBLE: @@ -1514,7 +1552,7 @@ static void write_sm4_cast(struct hlsl_ctx *ctx, break;
case HLSL_TYPE_BOOL: - hlsl_fixme(ctx, &expr->node.loc, "SM4 cast from bool to int."); + write_sm4_cast_from_bool(ctx, buffer, expr, arg1); break;
case HLSL_TYPE_DOUBLE: @@ -1540,7 +1578,7 @@ static void write_sm4_cast(struct hlsl_ctx *ctx, break;
case HLSL_TYPE_BOOL: - hlsl_fixme(ctx, &expr->node.loc, "SM4 cast from bool to uint."); + write_sm4_cast_from_bool(ctx, buffer, expr, arg1); break;
case HLSL_TYPE_DOUBLE: diff --git a/tests/cast-to-float.shader_test b/tests/cast-to-float.shader_test index 1844b1f3..f0910020 100644 --- a/tests/cast-to-float.shader_test +++ b/tests/cast-to-float.shader_test @@ -12,7 +12,7 @@ uniform 0 int -1 uniform 1 uint 3 uniform 2 int -2 uniform 3 float 0.5 -todo draw quad +draw quad probe all rgba (0.5, 0.5, 0.5, 0.5)
[pixel shader] diff --git a/tests/cast-to-int.shader_test b/tests/cast-to-int.shader_test index ce42827b..4c5d0e2f 100644 --- a/tests/cast-to-int.shader_test +++ b/tests/cast-to-int.shader_test @@ -19,8 +19,8 @@ uniform 0 float 2.6 uniform 1 int -2 uniform 2 int -2 uniform 3 float -3.6 -todo draw quad -probe all rgba (0.5, 0.5, 0.5, 0.5) +draw quad +todo probe all rgba (0.5, 0.5, 0.5, 0.5)
[pixel shader]
diff --git a/tests/cast-to-uint.shader_test b/tests/cast-to-uint.shader_test index 8b7964ff..66f7267e 100644 --- a/tests/cast-to-uint.shader_test +++ b/tests/cast-to-uint.shader_test @@ -19,8 +19,8 @@ uniform 0 float 2.6 uniform 1 int 2 uniform 2 int -2 uniform 3 float -3.6 -todo draw quad -probe all rgba (0.5, 0.5, 0.5, 0.5) +draw quad +todo probe all rgba (0.5, 0.5, 0.5, 0.5)
[pixel shader]
diff --git a/tests/hlsl-bool-cast.shader_test b/tests/hlsl-bool-cast.shader_test index 8880b2f5..397cbcc0 100644 --- a/tests/hlsl-bool-cast.shader_test +++ b/tests/hlsl-bool-cast.shader_test @@ -12,3 +12,21 @@ float4 main() : SV_TARGET [test] draw quad probe all rgba (0.0, 0.0, 1.0, 1.0) + +[require] +shader model >= 4.0 + +[pixel shader] +uniform float4 x; +uniform int4 y; + +float4 main() : SV_TARGET +{ + return (float4)(bool4)x + 10.0 * (float4)(int4)(bool4)y; +} + +[test] +uniform 0 float4 0.0 0.0 2.0 4.0 +uniform 4 int4 0 1 0 10 +draw quad +probe all rgba (0.0, 10.0, 1.0, 11.0) diff --git a/tests/logic-operations.shader_test b/tests/logic-operations.shader_test index 9a5cec3f..f888e831 100644 --- a/tests/logic-operations.shader_test +++ b/tests/logic-operations.shader_test @@ -8,7 +8,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 1.0, 1.0, 1.0)
[pixel shader] @@ -61,7 +61,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 1.0, 1.0, 1.0)
[pixel shader] @@ -114,7 +114,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 1.0, 1.0, 1.0)
[pixel shader]
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 5 +++++ tests/logic-operations.shader_test | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 23678498..e806bdee 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -1659,6 +1659,11 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, write_sm4_unary_op(buffer, VKD3D_SM4_OP_LOG, &expr->node, arg1, 0); break;
+ case HLSL_OP1_LOGIC_NOT: + assert(dst_type->base_type == HLSL_TYPE_BOOL); + write_sm4_unary_op(buffer, VKD3D_SM4_OP_NOT, &expr->node, arg1, 0); + break; + case HLSL_OP1_NEG: switch (dst_type->base_type) { diff --git a/tests/logic-operations.shader_test b/tests/logic-operations.shader_test index f888e831..87e927f4 100644 --- a/tests/logic-operations.shader_test +++ b/tests/logic-operations.shader_test @@ -22,7 +22,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 1.0)
[pixel shader] @@ -75,7 +75,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 1.0)
[pixel shader] @@ -128,7 +128,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 1.0)
[pixel shader]
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 5 +++++ tests/logic-operations.shader_test | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index e806bdee..06a71abf 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -1857,6 +1857,11 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, break; }
+ case HLSL_OP2_LOGIC_AND: + assert(dst_type->base_type == HLSL_TYPE_BOOL); + write_sm4_binary_op(buffer, VKD3D_SM4_OP_AND, &expr->node, arg1, arg2); + break; + case HLSL_OP2_LSHIFT: assert(type_is_integer(dst_type)); assert(dst_type->base_type != HLSL_TYPE_BOOL); diff --git a/tests/logic-operations.shader_test b/tests/logic-operations.shader_test index 87e927f4..032b5b23 100644 --- a/tests/logic-operations.shader_test +++ b/tests/logic-operations.shader_test @@ -35,7 +35,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 1.0)
[pixel shader] @@ -88,7 +88,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 1.0)
[pixel shader] @@ -141,7 +141,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 0.0, 0.0, 1.0)
[pixel shader]
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 5 +++++ tests/logic-operations.shader_test | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 06a71abf..4d9855ba 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -1862,6 +1862,11 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, write_sm4_binary_op(buffer, VKD3D_SM4_OP_AND, &expr->node, arg1, arg2); break;
+ case HLSL_OP2_LOGIC_OR: + assert(dst_type->base_type == HLSL_TYPE_BOOL); + write_sm4_binary_op(buffer, VKD3D_SM4_OP_OR, &expr->node, arg1, arg2); + break; + case HLSL_OP2_LSHIFT: assert(type_is_integer(dst_type)); assert(dst_type->base_type != HLSL_TYPE_BOOL); diff --git a/tests/logic-operations.shader_test b/tests/logic-operations.shader_test index 032b5b23..360ca03b 100644 --- a/tests/logic-operations.shader_test +++ b/tests/logic-operations.shader_test @@ -48,7 +48,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 1.0, 1.0, 1.0)
[pixel shader] @@ -101,7 +101,7 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 1.0, 1.0, 1.0)
[pixel shader] @@ -154,5 +154,5 @@ float4 main() : SV_TARGET }
[test] -todo draw quad +draw quad probe all rgba (0.0, 1.0, 1.0, 1.0)
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- Makefile.am | 1 + tests/arithmetic-int-uniform.shader_test | 28 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/arithmetic-int-uniform.shader_test
diff --git a/Makefile.am b/Makefile.am index 0cb90b2b..60db7794 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,6 +54,7 @@ vkd3d_shader_tests = \ tests/abs.shader_test \ tests/arithmetic-float.shader_test \ tests/arithmetic-int.shader_test \ + tests/arithmetic-int-uniform.shader_test \ tests/arithmetic-uint.shader_test \ tests/bitwise.shader_test \ tests/cast-broadcast.shader_test \ diff --git a/tests/arithmetic-int-uniform.shader_test b/tests/arithmetic-int-uniform.shader_test new file mode 100644 index 00000000..9bd7f2ac --- /dev/null +++ b/tests/arithmetic-int-uniform.shader_test @@ -0,0 +1,28 @@ +[require] +shader model >= 4.0 + +[pixel shader] +uniform int x, y; + +float4 main() : SV_TARGET +{ + return float4(x + y, x - y, x * y, x / y); +} + +[test] +uniform 0 int4 5 15 0 0 +todo draw quad +probe all rgba (20.0, -10.0, 75.0, 0.0) + +[pixel shader] +uniform int x, y; + +float4 main() : SV_TARGET +{ + return float4(x % y, +x, -x, y / x); +} + +[test] +uniform 0 int4 5 15 0 0 +todo draw quad +probe all rgba (5.0, 5.0, -5.0, 3.0)
On 6/29/22 09:55, Giovanni Mascellani wrote:
diff --git a/tests/arithmetic-int-uniform.shader_test b/tests/arithmetic-int-uniform.shader_test new file mode 100644 index 00000000..9bd7f2ac --- /dev/null +++ b/tests/arithmetic-int-uniform.shader_test @@ -0,0 +1,28 @@ +[require] +shader model >= 4.0
Passing "uniform int" requires sm4 (well, sort of), but the actual operations should be possible with sm1. Perhaps pass the inputs as floats and then cast them to int variables before performing arithmetic?
+[pixel shader] +uniform int x, y;
+float4 main() : SV_TARGET +{
- return float4(x + y, x - y, x * y, x / y);
+}
+[test] +uniform 0 int4 5 15 0 0 +todo draw quad +probe all rgba (20.0, -10.0, 75.0, 0.0)
+[pixel shader] +uniform int x, y;
+float4 main() : SV_TARGET +{
- return float4(x % y, +x, -x, y / x);
+}
+[test] +uniform 0 int4 5 15 0 0 +todo draw quad +probe all rgba (5.0, 5.0, -5.0, 3.0)
Hi,
Il 01/07/22 06:43, Zebediah Figura ha scritto:
Passing "uniform int" requires sm4 (well, sort of), but the actual operations should be possible with sm1. Perhaps pass the inputs as floats and then cast them to int variables before performing arithmetic?
The main point of that test is to run the code that does some int operation lowering (division, modulus and absolute value; well, there is not absolute value, I'll add it), patches still to be contributed. SM4 doesn't represent those operations directly and rather requires some more complicated code to emulate them. I guess this doesn't happen in SM1, given that those operations are silently converted to float anyway, so I didn't consider it a priority anyway. But I can do what you suggested.
Giovanni.
On 7/1/22 03:25, Giovanni Mascellani wrote:
Hi,
Il 01/07/22 06:43, Zebediah Figura ha scritto:
Passing "uniform int" requires sm4 (well, sort of), but the actual operations should be possible with sm1. Perhaps pass the inputs as floats and then cast them to int variables before performing arithmetic?
The main point of that test is to run the code that does some int operation lowering (division, modulus and absolute value; well, there is not absolute value, I'll add it), patches still to be contributed. SM4 doesn't represent those operations directly and rather requires some more complicated code to emulate them. I guess this doesn't happen in SM1, given that those operations are silently converted to float anyway, so I didn't consider it a priority anyway. But I can do what you suggested.
Right, underlyingly what's being tested is going to be different. But eventually I imagine we'll want *some* manner of tests for int instructions in sm1, so it probably makes sense to reuse these. (Assuming they behave sanely, that is. No need to bend over backwards to accommodate both sm1 and sm4 in the same test unit.)
On 6/29/22 09:55, Giovanni Mascellani wrote:
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com
libs/vkd3d-shader/hlsl_sm4.c | 44 ++++++++++++++++++++++++++++-- tests/cast-to-float.shader_test | 2 +- tests/cast-to-int.shader_test | 4 +-- tests/cast-to-uint.shader_test | 4 +-- tests/hlsl-bool-cast.shader_test | 18 ++++++++++++ tests/logic-operations.shader_test | 6 ++-- 6 files changed, 67 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 79027169..23678498 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -1459,6 +1459,44 @@ static bool type_is_float(const struct hlsl_type *type) return type->base_type == HLSL_TYPE_FLOAT || type->base_type == HLSL_TYPE_HALF; }
+static void write_sm4_cast_from_bool(struct hlsl_ctx *ctx,
struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_expr *expr,
const struct hlsl_ir_node *arg)
+{
- struct sm4_instruction instr;
- uint32_t c;
- switch (expr->node.data_type->base_type)
- {
case HLSL_TYPE_FLOAT:
Should this include HLSL_TYPE_HALF as well?
c = 0x3f800000;
break;
Maybe not worth worrying about, but the hardcoded number could be avoided by doing something like
union { uint32_t u; float f; } c;
...
c.f = 1.0f;
case HLSL_TYPE_INT:
case HLSL_TYPE_UINT:
c = 1;
break;
default:
assert(0);
We don't need to handle doubles, but I'm not sure they should result in an assert either.
- }
- memset(&instr, 0, sizeof(instr));
- instr.opcode = VKD3D_SM4_OP_AND;
- sm4_dst_from_node(&instr.dsts[0], &expr->node);
- instr.dst_count = 1;
- sm4_src_from_node(&instr.srcs[0], arg, instr.dsts[0].writemask);
- instr.srcs[1].swizzle_type = VKD3D_SM4_SWIZZLE_NONE;
- instr.srcs[1].reg.type = VKD3D_SM4_RT_IMMCONST;
- instr.srcs[1].reg.dim = VKD3D_SM4_DIMENSION_SCALAR;
- instr.srcs[1].reg.immconst_uint[0] = c;
- instr.src_count = 2;
- write_sm4_instruction(buffer, &instr);
+}
I kind of wonder if this should be a lowering pass instead. It wouldn't apply to sm1, but it would (maybe?) be a bit easier to write, and it would apply to a hypothetical sm6 backend, if we indeed write our own instead of leveraging the Microsoft compiler.
Fine to leave it as is for now, I think, but food for thought.
- static void write_sm4_cast(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_expr *expr) {
@@ -1488,7 +1526,7 @@ static void write_sm4_cast(struct hlsl_ctx *ctx, break;
case HLSL_TYPE_BOOL:
hlsl_fixme(ctx, &expr->node.loc, "SM4 cast from bool to float.");
write_sm4_cast_from_bool(ctx, buffer, expr, arg1); break; case HLSL_TYPE_DOUBLE:
@@ -1514,7 +1552,7 @@ static void write_sm4_cast(struct hlsl_ctx *ctx, break;
case HLSL_TYPE_BOOL:
hlsl_fixme(ctx, &expr->node.loc, "SM4 cast from bool to int.");
write_sm4_cast_from_bool(ctx, buffer, expr, arg1); break; case HLSL_TYPE_DOUBLE:
@@ -1540,7 +1578,7 @@ static void write_sm4_cast(struct hlsl_ctx *ctx, break;
case HLSL_TYPE_BOOL:
hlsl_fixme(ctx, &expr->node.loc, "SM4 cast from bool to uint.");
write_sm4_cast_from_bool(ctx, buffer, expr, arg1); break; case HLSL_TYPE_DOUBLE:
Could we just pass the mask from here instead, and skip the switch inside of write_sm4_cast_from_bool()?
Hi,
Il 01/07/22 06:43, Zebediah Figura ha scritto:
I kind of wonder if this should be a lowering pass instead. It wouldn't apply to sm1, but it would (maybe?) be a bit easier to write, and it would apply to a hypothetical sm6 backend, if we indeed write our own instead of leveraging the Microsoft compiler.
Fine to leave it as is for now, I think, but food for thought.
I kind of thought the same, but then decided that at least for the time being this is not inappropriate. A lowering pass, in the current state, would generate longer code (it cannot inline the constant), at least by instruction number, and would likely require more code for all the bookkeeping. All of this, for no advantage I can see.
No problem with changing the approach in the future if a different balance is established.
Giovanni.