Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Makefile.am | 2 ++ tests/cast-to-float.shader_test | 29 +++++++++++++++++++++++++++++ tests/shader_runner_d3d12.c | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 tests/cast-to-float.shader_test
diff --git a/Makefile.am b/Makefile.am index 05d9f00c6..d707a26b3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,6 +54,7 @@ vkd3d_shader_runners = \ tests/shader_runner_d3d12
vkd3d_shader_tests = \ + tests/cast-to-float.shader_test \ tests/conditional.shader_test \ tests/hlsl-array-dimension.shader_test \ tests/hlsl-bool-cast.shader_test \ @@ -266,6 +267,7 @@ tests_vkd3d_api_LDADD = libvkd3d.la @VULKAN_LIBS@ tests_vkd3d_shader_api_LDADD = libvkd3d-shader.la SHADER_TEST_LOG_COMPILER = tests/shader_runner_d3d12 XFAIL_TESTS = \ + tests/cast-to-float.shader_test \ tests/conditional.shader_test \ tests/hlsl-array-dimension.shader_test \ tests/hlsl-bool-cast.shader_test \ diff --git a/tests/cast-to-float.shader_test b/tests/cast-to-float.shader_test new file mode 100644 index 000000000..75822e527 --- /dev/null +++ b/tests/cast-to-float.shader_test @@ -0,0 +1,29 @@ +[pixel shader] + +float4 main(uniform int i, uniform uint u, uniform bool b, uniform half h) : sv_target +{ + return float4(((float)i) + 1.5, ((float)u) - 2.5, ((float)b) / 2, h); +} + +[test] +uniform 0 int -1 +uniform 1 uint 3 +uniform 2 int -2 +uniform 3 float 0.5 +draw quad +probe all rgba (0.5, 0.5, 0.5, 0.5) + +[pixel shader] + +float4 main() : sv_target +{ + int i = -1; + uint u = 3; + bool b = true; + half h = 0.5; + return float4(((float)i) + 1.5, ((float)u) - 2.5, ((float)b) / 2, h); +} + +[test] +draw quad +probe all rgba (0.5, 0.5, 0.5, 0.5) diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 2221c0f87..86151e424 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c @@ -109,7 +109,7 @@ enum parse_state STATE_TEST, };
-static bool match_string(const char *line, const char *token, const char **const rest) +static bool match_string(char *line, const char *token, char **const rest) { size_t len = strlen(token);
@@ -124,7 +124,7 @@ static bool match_string(const char *line, const char *token, const char **const return true; }
-static void parse_test_directive(struct shader_context *context, const char *line) +static void parse_test_directive(struct shader_context *context, char *line) { const char *const orig_line = line;
@@ -242,11 +242,38 @@ static void parse_test_directive(struct shader_context *context, const char *lin } memcpy(context->uniforms + offset, &v, sizeof(v)); } + else if (match_string(line, "float", &line)) + { + float f; + + if (!(f = strtof(line, &line)) && !line) + goto err; + if (offset + 1 > context->uniform_count) + { + context->uniform_count = offset + 1; + context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms)); + } + memcpy(context->uniforms + offset, &f, sizeof(f)); + } + else if (match_string(line, "int", &line)) + { + int i; + + if (!(i = strtol(line, &line, 0))) + goto err; + if (offset + 1 > context->uniform_count) + { + context->uniform_count = offset + 1; + context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms)); + } + memcpy(context->uniforms + offset, &i, sizeof(i)); + } else if (match_string(line, "uint", &line)) { unsigned int u;
- sscanf(line, "%u", &u); + if (!(u = strtoul(line, &line, 0))) + goto err; if (offset + 1 > context->uniform_count) { context->uniform_count = offset + 1;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Makefile.am | 2 ++ tests/cast-to-half.shader_test | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/cast-to-half.shader_test
diff --git a/Makefile.am b/Makefile.am index d707a26b3..a1b6eb31b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -55,6 +55,7 @@ vkd3d_shader_runners = \
vkd3d_shader_tests = \ tests/cast-to-float.shader_test \ + tests/cast-to-half.shader_test \ tests/conditional.shader_test \ tests/hlsl-array-dimension.shader_test \ tests/hlsl-bool-cast.shader_test \ @@ -268,6 +269,7 @@ tests_vkd3d_shader_api_LDADD = libvkd3d-shader.la SHADER_TEST_LOG_COMPILER = tests/shader_runner_d3d12 XFAIL_TESTS = \ tests/cast-to-float.shader_test \ + tests/cast-to-half.shader_test \ tests/conditional.shader_test \ tests/hlsl-array-dimension.shader_test \ tests/hlsl-bool-cast.shader_test \ diff --git a/tests/cast-to-half.shader_test b/tests/cast-to-half.shader_test new file mode 100644 index 000000000..6db5412de --- /dev/null +++ b/tests/cast-to-half.shader_test @@ -0,0 +1,29 @@ +[pixel shader] + +float4 main(uniform int i, uniform uint u, uniform bool b, uniform float f) : sv_target +{ + return float4(((half)i) + 1.5, ((half)u) - 2.5, ((half)b) / 2, f); +} + +[test] +uniform 0 int -1 +uniform 1 uint 3 +uniform 2 int -2 +uniform 3 float 0.5 +draw quad +probe all rgba (0.5, 0.5, 0.5, 0.5) + +[pixel shader] + +float4 main() : sv_target +{ + int i = -1; + uint u = 3; + bool b = true; + float f = 0.5; + return float4(((half)i) + 1.5, ((half)u) - 2.5, ((half)b) / 2, f); +} + +[test] +draw quad +probe all rgba (0.5, 0.5, 0.5, 0.5)
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Makefile.am | 2 ++ tests/cast-to-int.shader_test | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/cast-to-int.shader_test
diff --git a/Makefile.am b/Makefile.am index a1b6eb31b..da57a6893 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,6 +56,7 @@ vkd3d_shader_runners = \ vkd3d_shader_tests = \ tests/cast-to-float.shader_test \ tests/cast-to-half.shader_test \ + tests/cast-to-int.shader_test \ tests/conditional.shader_test \ tests/hlsl-array-dimension.shader_test \ tests/hlsl-bool-cast.shader_test \ @@ -270,6 +271,7 @@ SHADER_TEST_LOG_COMPILER = tests/shader_runner_d3d12 XFAIL_TESTS = \ tests/cast-to-float.shader_test \ tests/cast-to-half.shader_test \ + tests/cast-to-int.shader_test \ tests/conditional.shader_test \ tests/hlsl-array-dimension.shader_test \ tests/hlsl-bool-cast.shader_test \ diff --git a/tests/cast-to-int.shader_test b/tests/cast-to-int.shader_test new file mode 100644 index 000000000..93ca3a5fe --- /dev/null +++ b/tests/cast-to-int.shader_test @@ -0,0 +1,41 @@ +[pixel shader] + +float4 main(uniform float f, uniform uint u, uniform bool b, uniform half h) : sv_target +{ + float4 ret; + + ret.x = ((float)(int)f) - 1.5; + ret.y = ((float)(int)u) + 2.5; + ret.z = ((float)(int)b) / 2; + ret.w = ((float)(int)h) + 3.5; + return ret; +} + +[test] +uniform 0 float 2.6 +uniform 1 uint 0xfffffffe +uniform 2 int -2 +uniform 3 float -3.6 +draw quad +probe all rgba (0.5, 0.5, 0.5, 0.5) + +[pixel shader] + +float4 main() : sv_target +{ + float f = 2.6; + uint u = 0xfffffffe; + bool b = true; + half h = -3.6; + float4 ret; + + ret.x = ((float)(int)f) - 1.5; + ret.y = ((float)(int)u) + 2.5; + ret.z = ((float)(int)b) / 2; + ret.w = ((float)(int)h) + 3.5; + return ret; +} + +[test] +draw quad +probe all rgba (0.5, 0.5, 0.5, 0.5)
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- Makefile.am | 2 ++ tests/cast-to-uint.shader_test | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/cast-to-uint.shader_test
diff --git a/Makefile.am b/Makefile.am index da57a6893..9f747f478 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,6 +57,7 @@ vkd3d_shader_tests = \ tests/cast-to-float.shader_test \ tests/cast-to-half.shader_test \ tests/cast-to-int.shader_test \ + tests/cast-to-uint.shader_test \ tests/conditional.shader_test \ tests/hlsl-array-dimension.shader_test \ tests/hlsl-bool-cast.shader_test \ @@ -272,6 +273,7 @@ XFAIL_TESTS = \ tests/cast-to-float.shader_test \ tests/cast-to-half.shader_test \ tests/cast-to-int.shader_test \ + tests/cast-to-uint.shader_test \ tests/conditional.shader_test \ tests/hlsl-array-dimension.shader_test \ tests/hlsl-bool-cast.shader_test \ diff --git a/tests/cast-to-uint.shader_test b/tests/cast-to-uint.shader_test new file mode 100644 index 000000000..93dcdeefe --- /dev/null +++ b/tests/cast-to-uint.shader_test @@ -0,0 +1,41 @@ +[pixel shader] + +float4 main(uniform float f, uniform int u, uniform bool b, uniform half h) : sv_target +{ + float4 ret; + + ret.x = ((float)(uint)f) - 1.5; + ret.y = ((float)(uint)u) - 1.5; + ret.z = ((float)(uint)b) / 2; + ret.w = ((float)(uint)h) + 0.5; + return ret; +} + +[test] +uniform 0 float 2.6 +uniform 1 int 2 +uniform 2 int -2 +uniform 3 float -3.6 +draw quad +probe all rgba (0.5, 0.5, 0.5, 0.5) + +[pixel shader] + +float4 main() : sv_target +{ + float f = 2.6; + int u = 2; + bool b = true; + half h = -3.6; + float4 ret; + + ret.x = ((float)(uint)f) - 1.5; + ret.y = ((float)(uint)u) - 1.5; + ret.z = ((float)(uint)b) / 2; + ret.w = ((float)(uint)h) + 0.5; + return ret; +} + +[test] +draw quad +probe all rgba (0.5, 0.5, 0.5, 0.5)
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
On Thu, Sep 9, 2021 at 6:01 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
Makefile.am | 2 ++ tests/cast-to-uint.shader_test | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/cast-to-uint.shader_test
diff --git a/tests/cast-to-uint.shader_test b/tests/cast-to-uint.shader_test new file mode 100644 index 000000000..93dcdeefe --- /dev/null +++ b/tests/cast-to-uint.shader_test @@ -0,0 +1,41 @@ +[pixel shader]
+float4 main(uniform float f, uniform int u, uniform bool b, uniform half h) : sv_target
Not that it matters but since here the second parameter is "int" maybe it would have been nicer to rename it appropriately :)
On 9/9/21 6:22 PM, Matteo Bruni wrote:
On Thu, Sep 9, 2021 at 6:01 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
Makefile.am | 2 ++ tests/cast-to-uint.shader_test | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/cast-to-uint.shader_test
diff --git a/tests/cast-to-uint.shader_test b/tests/cast-to-uint.shader_test new file mode 100644 index 000000000..93dcdeefe --- /dev/null +++ b/tests/cast-to-uint.shader_test @@ -0,0 +1,41 @@ +[pixel shader]
+float4 main(uniform float f, uniform int u, uniform bool b, uniform half h) : sv_target
Not that it matters but since here the second parameter is "int" maybe it would have been nicer to rename it appropriately :)
Oops, that was a mistake. Probably not worth fixing, though.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 160da47fd..cac71ef7e 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -981,6 +981,40 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, { switch (expr->op) { + case HLSL_OP1_CAST: + { + const struct hlsl_type *src_type = arg1->data_type; + + /* Narrowing casts need to be lowered. */ + if (src_type->dimx != expr->node.data_type->dimx) + hlsl_fixme(ctx, expr->node.loc, "Narrowing cast.\n"); + + switch (src_type->base_type) + { + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: + write_sm4_unary_op(buffer, VKD3D_SM4_OP_MOV, &expr->node, arg1, 0); + break; + + case HLSL_TYPE_BOOL: + case HLSL_TYPE_INT: + write_sm4_unary_op(buffer, VKD3D_SM4_OP_ITOF, &expr->node, arg1, 0); + break; + + case HLSL_TYPE_UINT: + write_sm4_unary_op(buffer, VKD3D_SM4_OP_UTOF, &expr->node, arg1, 0); + break; + + case HLSL_TYPE_DOUBLE: + hlsl_fixme(ctx, expr->node.loc, "Casts from double to int are not implemented.\n"); + break; + + default: + break; + } + break; + } + case HLSL_OP1_NEG: write_sm4_unary_op(buffer, VKD3D_SM4_OP_MOV, &expr->node, arg1, VKD3D_SM4_REGISTER_MODIFIER_NEGATE); break;
On Thu, Sep 9, 2021 at 6:02 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl_sm4.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 160da47fd..cac71ef7e 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -981,6 +981,40 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, { switch (expr->op) {
case HLSL_OP1_CAST:
{
const struct hlsl_type *src_type = arg1->data_type;
/* Narrowing casts need to be lowered. */
if (src_type->dimx != expr->node.data_type->dimx)
hlsl_fixme(ctx, expr->node.loc, "Narrowing cast.\n");
switch (src_type->base_type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
write_sm4_unary_op(buffer, VKD3D_SM4_OP_MOV, &expr->node, arg1, 0);
break;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
write_sm4_unary_op(buffer, VKD3D_SM4_OP_ITOF, &expr->node, arg1, 0);
break;
As far as I'm aware, booleans in SM4+ are represented in quite a peculiar way: false is represented as 0, true is canonically 0xffffffff. I think the idea is to be able to use the result of a conditional expression directly as a mask and such, but don't quote me on that. For sure it's different from SM1-3, which use the traditional 0 and 1 values for false and true.
That's probably the reason why native uses MOVC to convert from bool (to float or anything else) and, most importantly, NE for the opposite direction (with 0 as the other comparand).
On 9/9/21 6:16 PM, Matteo Bruni wrote:
On Thu, Sep 9, 2021 at 6:02 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl_sm4.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 160da47fd..cac71ef7e 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -981,6 +981,40 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, { switch (expr->op) {
case HLSL_OP1_CAST:
{
const struct hlsl_type *src_type = arg1->data_type;
/* Narrowing casts need to be lowered. */
if (src_type->dimx != expr->node.data_type->dimx)
hlsl_fixme(ctx, expr->node.loc, "Narrowing cast.\n");
switch (src_type->base_type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
write_sm4_unary_op(buffer, VKD3D_SM4_OP_MOV, &expr->node, arg1, 0);
break;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
write_sm4_unary_op(buffer, VKD3D_SM4_OP_ITOF, &expr->node, arg1, 0);
break;
As far as I'm aware, booleans in SM4+ are represented in quite a peculiar way: false is represented as 0, true is canonically 0xffffffff. I think the idea is to be able to use the result of a conditional expression directly as a mask and such, but don't quote me on that. For sure it's different from SM1-3, which use the traditional 0 and 1 values for false and true.
That's probably the reason why native uses MOVC to convert from bool (to float or anything else) and, most importantly, NE for the opposite direction (with 0 as the other comparand).
"(int)(bool)true" evaluates to 1 in anything I've been able to test. Under what circumstances do you have it evaluating to ~0?
On Fri, Sep 10, 2021 at 1:32 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
On 9/9/21 6:16 PM, Matteo Bruni wrote:
On Thu, Sep 9, 2021 at 6:02 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl_sm4.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 160da47fd..cac71ef7e 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -981,6 +981,40 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, { switch (expr->op) {
case HLSL_OP1_CAST:
{
const struct hlsl_type *src_type = arg1->data_type;
/* Narrowing casts need to be lowered. */
if (src_type->dimx != expr->node.data_type->dimx)
hlsl_fixme(ctx, expr->node.loc, "Narrowing cast.\n");
switch (src_type->base_type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
write_sm4_unary_op(buffer, VKD3D_SM4_OP_MOV, &expr->node, arg1, 0);
break;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
write_sm4_unary_op(buffer, VKD3D_SM4_OP_ITOF, &expr->node, arg1, 0);
break;
As far as I'm aware, booleans in SM4+ are represented in quite a peculiar way: false is represented as 0, true is canonically 0xffffffff. I think the idea is to be able to use the result of a conditional expression directly as a mask and such, but don't quote me on that. For sure it's different from SM1-3, which use the traditional 0 and 1 values for false and true.
That's probably the reason why native uses MOVC to convert from bool (to float or anything else) and, most importantly, NE for the opposite direction (with 0 as the other comparand).
"(int)(bool)true" evaluates to 1 in anything I've been able to test. Under what circumstances do you have it evaluating to ~0?
Yeah, the bool -> int conversion explicitly makes sure to give you 1 (by means of the MOVC instruction). You need to look at the generated shader bytecode. Try with this shader:
bool4 main(uniform int i, uniform uint u, uniform bool b, uniform float f) : sv_target { return bool4(((float)(bool)i) + 1.5, ((float)(bool)u) - 2.5, ((float)(bool)b) / 2, f); }
On 9/9/21 6:41 PM, Matteo Bruni wrote:
On Fri, Sep 10, 2021 at 1:32 AM Zebediah Figura (she/her) zfigura@codeweavers.com wrote:
On 9/9/21 6:16 PM, Matteo Bruni wrote:
On Thu, Sep 9, 2021 at 6:02 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
libs/vkd3d-shader/hlsl_sm4.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 160da47fd..cac71ef7e 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -981,6 +981,40 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, { switch (expr->op) {
case HLSL_OP1_CAST:
{
const struct hlsl_type *src_type = arg1->data_type;
/* Narrowing casts need to be lowered. */
if (src_type->dimx != expr->node.data_type->dimx)
hlsl_fixme(ctx, expr->node.loc, "Narrowing cast.\n");
switch (src_type->base_type)
{
case HLSL_TYPE_HALF:
case HLSL_TYPE_FLOAT:
write_sm4_unary_op(buffer, VKD3D_SM4_OP_MOV, &expr->node, arg1, 0);
break;
case HLSL_TYPE_BOOL:
case HLSL_TYPE_INT:
write_sm4_unary_op(buffer, VKD3D_SM4_OP_ITOF, &expr->node, arg1, 0);
break;
As far as I'm aware, booleans in SM4+ are represented in quite a peculiar way: false is represented as 0, true is canonically 0xffffffff. I think the idea is to be able to use the result of a conditional expression directly as a mask and such, but don't quote me on that. For sure it's different from SM1-3, which use the traditional 0 and 1 values for false and true.
That's probably the reason why native uses MOVC to convert from bool (to float or anything else) and, most importantly, NE for the opposite direction (with 0 as the other comparand).
"(int)(bool)true" evaluates to 1 in anything I've been able to test. Under what circumstances do you have it evaluating to ~0?
Yeah, the bool -> int conversion explicitly makes sure to give you 1 (by means of the MOVC instruction). You need to look at the generated shader bytecode. Try with this shader:
bool4 main(uniform int i, uniform uint u, uniform bool b, uniform float f) : sv_target { return bool4(((float)(bool)i) + 1.5, ((float)(bool)u) - 2.5, ((float)(bool)b) / 2, f); }
Ah, sure, I guess it would only show up for RTV or UAV writes.
I'll leave the bool case out of this patch, then.
Hi,
Il 10/09/21 01:16, Matteo Bruni ha scritto:
As far as I'm aware, booleans in SM4+ are represented in quite a peculiar way: false is represented as 0, true is canonically 0xffffffff. I think the idea is to be able to use the result of a conditional expression directly as a mask and such, but don't quote me on that. For sure it's different from SM1-3, which use the traditional 0 and 1 values for false and true.
Well, isn't it our choice how we decide to represent things internally? The only important requirement is that casts (and everything else) have the correct semantics. Whether inside a true bool variable there is 1, ~0u or whatever else it's our decision. If we store 1 for true, then we have to use MOVC (or a comparison followed by INEG) when casting to bool and MOV or ITOF when casting to int or float. If we store ~0, then we use a simple comparison for casting to bool and MOVC (or INEG and possibly ITOF) to cast to int or float.
In case we want to be closer to native (though I'm not sure it's really a requirement in this case: I expect all this opcodes to be well supported everywhere), then probably choosing to represent true as ~0u is better, but it's just a matter of choice. The really important thing is to be aware and consistent with the choice.
So what do we decide? I already have patches that implements comparison operators that assume that true is represented as 1. I can fix them, but please tell me what do we want.
Giovanni.
On Wed, Sep 15, 2021 at 9:16 AM Giovanni Mascellani gmascellani@codeweavers.com wrote:
Hi,
Il 10/09/21 01:16, Matteo Bruni ha scritto:
As far as I'm aware, booleans in SM4+ are represented in quite a peculiar way: false is represented as 0, true is canonically 0xffffffff. I think the idea is to be able to use the result of a conditional expression directly as a mask and such, but don't quote me on that. For sure it's different from SM1-3, which use the traditional 0 and 1 values for false and true.
Well, isn't it our choice how we decide to represent things internally? The only important requirement is that casts (and everything else) have the correct semantics. Whether inside a true bool variable there is 1, ~0u or whatever else it's our decision. If we store 1 for true, then we have to use MOVC (or a comparison followed by INEG) when casting to bool and MOV or ITOF when casting to int or float. If we store ~0, then we use a simple comparison for casting to bool and MOVC (or INEG and possibly ITOF) to cast to int or float.
In case we want to be closer to native (though I'm not sure it's really a requirement in this case: I expect all this opcodes to be well supported everywhere), then probably choosing to represent true as ~0u is better, but it's just a matter of choice. The really important thing is to be aware and consistent with the choice.
So what do we decide? I already have patches that implements comparison operators that assume that true is represented as 1. I can fix them, but please tell me what do we want.
Giovanni.
Yeah, we do want to have true as ~0u for SM4+ (there is no real bool type in < SM4, so that doesn't matter). There is no reason to do things differently and there might be some other unexpected way for the internal representation of true to leak in a visible manner.
Hi,
Il 15/09/21 09:27, Matteo Bruni ha scritto:
Yeah, we do want to have true as ~0u for SM4+ (there is no real bool type in < SM4, so that doesn't matter). There is no reason to do things differently and there might be some other unexpected way for the internal representation of true to leak in a visible manner.
Ok, I got convinced by this:
http://shader-playground.timjones.io/a33fbc87153ccd6774030f11d005ad1a
Which BTW means that either we store true as ~0u, or we convert it when returning a bool from a function, and at that point it's easier to just store ~0u.
On the other hand, the same example means that strictly speaking we also have to canonicalize bools which the shader receives as parameters.
I'll fix my patches.
Giovanni.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index cac71ef7e..250d30e60 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -1038,6 +1038,48 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, break; }
+ case HLSL_TYPE_INT: + { + switch (expr->op) + { + case HLSL_OP1_CAST: + { + const struct hlsl_type *src_type = arg1->data_type; + + /* Narrowing casts need to be lowered. */ + if (src_type->dimx != expr->node.data_type->dimx) + hlsl_fixme(ctx, expr->node.loc, "Narrowing cast."); + + switch (src_type->base_type) + { + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: + write_sm4_unary_op(buffer, VKD3D_SM4_OP_FTOI, &expr->node, arg1, 0); + break; + + case HLSL_TYPE_BOOL: + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: + write_sm4_unary_op(buffer, VKD3D_SM4_OP_MOV, &expr->node, arg1, 0); + break; + + case HLSL_TYPE_DOUBLE: + hlsl_fixme(ctx, expr->node.loc, "SM4 cast from double to int."); + break; + + default: + break; + } + break; + } + + default: + hlsl_fixme(ctx, expr->node.loc, "SM4 int "%s" expression.", debug_hlsl_expr_op(expr->op)); + break; + } + break; + } + default: { struct vkd3d_string_buffer *string;
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- libs/vkd3d-shader/hlsl_sm4.c | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c index 250d30e60..1ff45b181 100644 --- a/libs/vkd3d-shader/hlsl_sm4.c +++ b/libs/vkd3d-shader/hlsl_sm4.c @@ -1080,6 +1080,48 @@ static void write_sm4_expr(struct hlsl_ctx *ctx, break; }
+ case HLSL_TYPE_UINT: + { + switch (expr->op) + { + case HLSL_OP1_CAST: + { + const struct hlsl_type *src_type = arg1->data_type; + + /* Narrowing casts need to be lowered. */ + if (src_type->dimx != expr->node.data_type->dimx) + hlsl_fixme(ctx, expr->node.loc, "SM4 narrowing cast.\n"); + + switch (src_type->base_type) + { + case HLSL_TYPE_HALF: + case HLSL_TYPE_FLOAT: + write_sm4_unary_op(buffer, VKD3D_SM4_OP_FTOU, &expr->node, arg1, 0); + break; + + case HLSL_TYPE_BOOL: + case HLSL_TYPE_INT: + case HLSL_TYPE_UINT: + write_sm4_unary_op(buffer, VKD3D_SM4_OP_MOV, &expr->node, arg1, 0); + break; + + case HLSL_TYPE_DOUBLE: + hlsl_fixme(ctx, expr->node.loc, "SM4 cast from double to uint.\n"); + break; + + default: + break; + } + break; + } + + default: + hlsl_fixme(ctx, expr->node.loc, "SM4 uint "%s" expression.\n", debug_hlsl_expr_op(expr->op)); + break; + } + break; + } + default: { struct vkd3d_string_buffer *string;
On Thu, Sep 9, 2021 at 6:01 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
Makefile.am | 2 ++ tests/cast-to-float.shader_test | 29 +++++++++++++++++++++++++++++ tests/shader_runner_d3d12.c | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 tests/cast-to-float.shader_test
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 2221c0f87..86151e424 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c
@@ -242,11 +242,38 @@ static void parse_test_directive(struct shader_context *context, const char *lin } memcpy(context->uniforms + offset, &v, sizeof(v)); }
else if (match_string(line, "float", &line))
{
float f;
if (!(f = strtof(line, &line)) && !line)
goto err;
if (offset + 1 > context->uniform_count)
{
context->uniform_count = offset + 1;
context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
}
memcpy(context->uniforms + offset, &f, sizeof(f));
}
else if (match_string(line, "int", &line))
{
int i;
if (!(i = strtol(line, &line, 0)))
goto err;
if (offset + 1 > context->uniform_count)
{
context->uniform_count = offset + 1;
context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
}
memcpy(context->uniforms + offset, &i, sizeof(i));
} else if (match_string(line, "uint", &line)) { unsigned int u;
sscanf(line, "%u", &u);
if (!(u = strtoul(line, &line, 0)))
goto err; if (offset + 1 > context->uniform_count) { context->uniform_count = offset + 1;
Strictly speaking, it doesn't seem necessary to change and use the strto*() functions instead of sscanf() in all the non-float4 cases. Unless you have plans...
On 9/9/21 6:21 PM, Matteo Bruni wrote:
On Thu, Sep 9, 2021 at 6:01 AM Zebediah Figura zfigura@codeweavers.com wrote:
Signed-off-by: Zebediah Figura zfigura@codeweavers.com
Makefile.am | 2 ++ tests/cast-to-float.shader_test | 29 +++++++++++++++++++++++++++++ tests/shader_runner_d3d12.c | 33 ++++++++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 tests/cast-to-float.shader_test
diff --git a/tests/shader_runner_d3d12.c b/tests/shader_runner_d3d12.c index 2221c0f87..86151e424 100644 --- a/tests/shader_runner_d3d12.c +++ b/tests/shader_runner_d3d12.c
@@ -242,11 +242,38 @@ static void parse_test_directive(struct shader_context *context, const char *lin } memcpy(context->uniforms + offset, &v, sizeof(v)); }
else if (match_string(line, "float", &line))
{
float f;
if (!(f = strtof(line, &line)) && !line)
goto err;
if (offset + 1 > context->uniform_count)
{
context->uniform_count = offset + 1;
context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
}
memcpy(context->uniforms + offset, &f, sizeof(f));
}
else if (match_string(line, "int", &line))
{
int i;
if (!(i = strtol(line, &line, 0)))
goto err;
if (offset + 1 > context->uniform_count)
{
context->uniform_count = offset + 1;
context->uniforms = realloc(context->uniforms, context->uniform_count * sizeof(*context->uniforms));
}
memcpy(context->uniforms + offset, &i, sizeof(i));
} else if (match_string(line, "uint", &line)) { unsigned int u;
sscanf(line, "%u", &u);
if (!(u = strtoul(line, &line, 0)))
goto err; if (offset + 1 > context->uniform_count) { context->uniform_count = offset + 1;
Strictly speaking, it doesn't seem necessary to change and use the strto*() functions instead of sscanf() in all the non-float4 cases. Unless you have plans...
That was me wanting to use 0x, and being too lazy to fix this the right way. Fortunately a two-second look at the man page for sscanf(3) tells me the right way to fix this :-)