From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 593ca0a3d..e70d82d0f 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3344,7 +3344,6 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) effect_types[] = { {"dword", HLSL_CLASS_SCALAR, HLSL_TYPE_UINT, 1, 1}, - {"float", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1}, {"vector", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1}, {"matrix", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4}, {"STRING", HLSL_CLASS_OBJECT, HLSL_TYPE_STRING, 1, 1},
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl_codegen.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 0f4c4441b..0d4b68be5 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -2763,6 +2763,12 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru first = expr->operands[1].node; second = expr->operands[2].node;
+ if (cond->data_type->class > HLSL_CLASS_VECTOR || instr->data_type->class > HLSL_CLASS_VECTOR) + { + hlsl_fixme(ctx, &instr->loc, "Lower ternary of type other than scalar or vector.\n"); + return false; + } + if (ctx->profile->major_version < 4 && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL) { struct hlsl_ir_node *abs, *neg;
From: Zebediah Figura zfigura@codeweavers.com
--- tests/hlsl/ternary.shader_test | 254 +++++++++++++++++++++++++++++++++ 1 file changed, 254 insertions(+)
diff --git a/tests/hlsl/ternary.shader_test b/tests/hlsl/ternary.shader_test index 587b3d556..5a73084cf 100644 --- a/tests/hlsl/ternary.shader_test +++ b/tests/hlsl/ternary.shader_test @@ -14,6 +14,7 @@ uniform 0 float4 0.0 10.0 11.0 12.0 todo(sm>=6) draw quad probe all rgba (-1.0, 9.0, 10.0, 11.0)
+ [pixel shader] uniform float4 x;
@@ -32,6 +33,7 @@ uniform 0 float4 1.1 3.0 4.0 5.0 todo(sm>=6) draw quad probe all rgba (1.1, 2.0, 0.0, 0.0)
+ [pixel shader] float4 f;
@@ -47,6 +49,7 @@ uniform 0 float4 1.0 0.0 0.0 0.0 todo(sm>=6) draw quad probe all rgba (0.5, 0.6, 0.7, 0.0)
+ [pixel shader fail(sm>=6)] float4 x, y, z;
@@ -61,3 +64,254 @@ uniform 4 float4 1.0 2.0 3.0 4.0 uniform 8 float4 5.0 6.0 7.0 8.0 draw quad probe all rgba (5.0, 2.0, 7.0, 4.0) + + +% The usual type conversion is applied to the first and second expression, as +% long as they are numeric. + +[pixel shader fail] + +uniform float2x4 a; +uniform float3x2 b; + +float4 main() : sv_target +{ + 0 ? a : b; + return 0; +} + + +[pixel shader] + +uniform float3x3 a; +uniform float2x2 b; + +float4 main() : sv_target +{ + return float4(0 ? a : b); +} + + +[pixel shader] + +uniform float3 a; +uniform float4 b; + +float4 main() : sv_target +{ + return float4(0 ? a : b, 1.0); +} + + +% The condition is more restrictive. Either: +% * the class and dimensions must match exactly; +% * one of the two is scalar; +% * one is a typeN and the other is a type1xN + +[pixel shader fail todo] + +uniform float4 cond; +uniform float2x2 a, b; + +float4 main() : sv_target +{ + return float4(cond ? a : b); +} + + +[pixel shader fail todo] + +uniform float2x2 cond; +uniform float4 a, b; + +float4 main() : sv_target +{ + return float4(cond ? a : b); +} + + +[pixel shader] + +uniform float2x2 cond; +uniform float2x2 a, b; + +float4 main() : sv_target +{ + return float4(cond ? a : b); +} + + +[pixel shader fail todo] + +uniform float3 cond; +uniform float4 a, b; + +float4 main() : sv_target +{ + (cond ? a : b); + return 0; +} + + +[pixel shader fail todo] + +uniform float4 cond; +uniform float4x1 a, b; + +float4 main() : sv_target +{ + (cond ? a : b); + return 0; +} + + +% As may be expected, this yields the type of the arguments, not the conditional. + +[pixel shader] + +uniform float4 cond; +uniform float1x4 a, b; + +float4 main() : sv_target +{ + return (cond ? a : b)[0]; +} + + +[pixel shader todo] + +uniform float1x4 cond; +uniform float4 a, b; + +float4 main() : sv_target +{ + return (cond ? a : b)[0]; +} + + +[pixel shader fail] + +uniform float1x4 cond; +uniform float4 a, b; + +float4 main() : sv_target +{ + return (cond ? a : b)[0][0]; +} + + +[pixel shader] + +uniform float1 cond; +uniform float1x1 a, b; + +float4 main() : sv_target +{ + return (cond ? a : b)[0][0]; +} + + +[pixel shader] + +uniform float cond; +uniform float4 a, b; + +float4 main() : sv_target +{ + return float4(cond ? a : b); +} + +[test] +uniform 0 float4 1.0 0.0 0.0 0.0 +uniform 4 float4 1.0 2.0 3.0 4.0 +uniform 8 float4 5.0 6.0 7.0 8.0 +draw quad +probe all rgba (1.0, 2.0, 3.0, 4.0) + + +[pixel shader todo] + +// "scalar" can mean any 1-component numeric type. +uniform float1x1 cond; +uniform float4 a, b; + +float4 main() : sv_target +{ + return float4(cond ? a : b); +} + + +[pixel shader todo] + +uniform float4 cond; +uniform float4 a, b; + +float4 main() : sv_target +{ + return float4(cond ? a.x : b.x); +} + +[test] +uniform 0 float4 1.0 0.0 1.0 0.0 +uniform 4 float4 1.0 2.0 3.0 4.0 +uniform 8 float4 5.0 6.0 7.0 8.0 +todo draw quad +probe all rgba (1.0, 5.0, 1.0, 5.0) + + +[pixel shader todo] + +// "scalar" can mean any 1-component numeric type. +uniform float4 cond; +uniform float1x1 a, b; + +float4 main() : sv_target +{ + return float4(cond ? a : b); +} + + +% Objects can be used, but their types have to be identical. + +[pixel shader todo] +Texture2D t; + +float4 main() : sv_target +{ + Texture2D tmp = 0 ? t : t; + return 0; +} + + +[pixel shader fail todo] +Texture2D t; +float4 f; + +float4 main() : sv_target +{ + f ? t : t; + return 0; +} + + +[pixel shader fail] +Texture2D t; +Texture3D u; + +float4 main() : sv_target +{ + 0 ? t : u; + return 0; +} + + +% Of course objects cannot be used as the condition. + +[pixel shader fail todo] +Texture2D t; + +float4 main() : sv_target +{ + t ? 0 : 1; + return 0; +}
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 57c63c43f..c37895598 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3944,6 +3944,27 @@ static struct hlsl_block *add_constructor(struct hlsl_ctx *ctx, struct hlsl_type return params->instrs; }
+static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, + struct hlsl_ir_node *cond, struct hlsl_ir_node *first, struct hlsl_ir_node *second) +{ + struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; + struct hlsl_type *common_type; + + if (!(common_type = get_common_numeric_type(ctx, first, second, &first->loc))) + return false; + + if (!(first = add_implicit_conversion(ctx, block, first, common_type, &first->loc))) + return false; + + if (!(second = add_implicit_conversion(ctx, block, second, common_type, &second->loc))) + return false; + + args[0] = cond; + args[1] = first; + args[2] = second; + return add_expr(ctx, block, HLSL_OP3_TERNARY, args, common_type, &first->loc); +} + static unsigned int hlsl_offset_dim_count(enum hlsl_sampler_dim dim) { switch (dim) @@ -7007,27 +7028,13 @@ conditional_expr: struct hlsl_ir_node *cond = node_from_block($1); struct hlsl_ir_node *first = node_from_block($3); struct hlsl_ir_node *second = node_from_block($5); - struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = { 0 }; - struct hlsl_type *common_type;
hlsl_block_add_block($1, $3); hlsl_block_add_block($1, $5); destroy_block($3); destroy_block($5);
- if (!(common_type = get_common_numeric_type(ctx, first, second, &@3))) - YYABORT; - - if (!(first = add_implicit_conversion(ctx, $1, first, common_type, &@3))) - YYABORT; - - if (!(second = add_implicit_conversion(ctx, $1, second, common_type, &@5))) - YYABORT; - - args[0] = cond; - args[1] = first; - args[2] = second; - if (!add_expr(ctx, $1, HLSL_OP3_TERNARY, args, common_type, &@1)) + if (!add_ternary(ctx, $1, cond, first, second)) YYABORT; $$ = $1; }
From: Zebediah Figura zfigura@codeweavers.com
--- libs/vkd3d-shader/hlsl.y | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index c37895598..df104a85c 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -3950,14 +3950,36 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *args[HLSL_MAX_OPERANDS] = {0}; struct hlsl_type *common_type;
- if (!(common_type = get_common_numeric_type(ctx, first, second, &first->loc))) - return false; + if (first->data_type->class <= HLSL_CLASS_LAST_NUMERIC + && second->data_type->class <= HLSL_CLASS_LAST_NUMERIC) + { + if (!(common_type = get_common_numeric_type(ctx, first, second, &first->loc))) + return false;
- if (!(first = add_implicit_conversion(ctx, block, first, common_type, &first->loc))) - return false; + if (!(first = add_implicit_conversion(ctx, block, first, common_type, &first->loc))) + return false;
- if (!(second = add_implicit_conversion(ctx, block, second, common_type, &second->loc))) - return false; + if (!(second = add_implicit_conversion(ctx, block, second, common_type, &second->loc))) + return false; + } + else + { + struct vkd3d_string_buffer *first_string, *second_string; + + if (!hlsl_types_are_equal(first->data_type, second->data_type)) + { + first_string = hlsl_type_to_string(ctx, first->data_type); + second_string = hlsl_type_to_string(ctx, second->data_type); + if (first_string && second_string) + hlsl_error(ctx, &first->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Ternary argument types '%s' and '%s' do not match.", + first_string->buffer, second_string->buffer); + hlsl_release_string_buffer(ctx, first_string); + hlsl_release_string_buffer(ctx, second_string); + } + + common_type = first->data_type; + }
args[0] = cond; args[1] = first;