diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 5ddf4b6c..7dbb051f 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -2099,11 +2099,12 @@ static bool invert_swizzle_matrix(const struct hlsl_matrix_swizzle *swizzle, } static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *lhs, - enum parse_assign_op assign_op, struct hlsl_ir_node *rhs) + enum parse_assign_op assign_op, struct hlsl_ir_node *rhs, bool is_function_out_arg) { struct hlsl_type *lhs_type = lhs->data_type; unsigned int writemask = 0, width = 0; bool matrix_writemask = false; + bool first_cast = true; if (lhs->data_type->class == HLSL_CLASS_ERROR || rhs->data_type->class == HLSL_CLASS_ERROR) { @@ -2149,7 +2150,7 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc hlsl_fixme(ctx, &cast->loc, "Size change on the LHS."); return false; } - if (hlsl_version_ge(ctx, 4, 0)) + if (hlsl_version_ge(ctx, 4, 0) && (!is_function_out_arg || !first_cast)) { hlsl_error(ctx, &cast->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_LVALUE, "Base type casts are not allowed on the LHS for profiles >= 4."); @@ -2159,6 +2160,8 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc lhs_type = lhs->data_type; if (lhs_type->class == HLSL_CLASS_VECTOR || (lhs_type->class == HLSL_CLASS_MATRIX && matrix_writemask)) lhs_type = hlsl_get_vector_type(ctx, lhs->data_type->e.numeric.type, width); + + first_cast = false; } else if (lhs->type == HLSL_IR_SWIZZLE) { @@ -2370,7 +2373,7 @@ static bool add_increment(struct hlsl_ctx *ctx, struct hlsl_block *block, bool d return false; hlsl_block_add_instr(block, one); - if (!add_assignment(ctx, block, lhs, decrement ? ASSIGN_OP_SUB : ASSIGN_OP_ADD, one)) + if (!add_assignment(ctx, block, lhs, decrement ? ASSIGN_OP_SUB : ASSIGN_OP_ADD, one, false)) return false; if (post) @@ -3272,7 +3275,7 @@ static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx, return NULL; hlsl_block_add_instr(args->instrs, &load->node); - if (!add_assignment(ctx, args->instrs, arg, ASSIGN_OP_ASSIGN, &load->node)) + if (!add_assignment(ctx, args->instrs, arg, ASSIGN_OP_ASSIGN, &load->node, true)) return NULL; } } @@ -5457,7 +5460,7 @@ static bool intrinsic_interlocked(struct hlsl_ctx *ctx, enum hlsl_interlocked_op hlsl_error(ctx, &orig_val->loc, VKD3D_SHADER_ERROR_HLSL_MODIFIES_CONST, "Output argument to '%s' is const.", name); - if (!add_assignment(ctx, params->instrs, orig_val, ASSIGN_OP_ASSIGN, interlocked)) + if (!add_assignment(ctx, params->instrs, orig_val, ASSIGN_OP_ASSIGN, interlocked, true)) return false; } @@ -6394,7 +6397,7 @@ static bool add_assignment_from_component(struct hlsl_ctx *ctx, struct hlsl_bloc if (!(load = hlsl_add_load_component(ctx, instrs, src, component, loc))) return false; - if (!add_assignment(ctx, instrs, dest, ASSIGN_OP_ASSIGN, load)) + if (!add_assignment(ctx, instrs, dest, ASSIGN_OP_ASSIGN, load, false)) return false; return true; @@ -6550,7 +6553,7 @@ static bool add_getdimensions_method_call(struct hlsl_ctx *ctx, struct hlsl_bloc return false; hlsl_block_add_instr(block, sample_info); - if (!add_assignment(ctx, block, args[ARG_SAMPLE_COUNT], ASSIGN_OP_ASSIGN, sample_info)) + if (!add_assignment(ctx, block, args[ARG_SAMPLE_COUNT], ASSIGN_OP_ASSIGN, sample_info, false)) return false; } @@ -9839,7 +9842,7 @@ assignment_expr: hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_MODIFIES_CONST, "Statement modifies a const expression."); hlsl_block_add_block($3, $1); destroy_block($1); - if (!add_assignment(ctx, $3, lhs, $2, rhs)) + if (!add_assignment(ctx, $3, lhs, $2, rhs, false)) YYABORT; $$ = $3; } diff --git a/tests/hlsl/function-cast.shader_test b/tests/hlsl/function-cast.shader_test index e2593444..99de5a92 100644 --- a/tests/hlsl/function-cast.shader_test +++ b/tests/hlsl/function-cast.shader_test @@ -25,7 +25,7 @@ probe (0, 0) rgba (-1.0, -1.0, 2.0, 4.0) % In SM 6 a cast seems to implicitly promote the type to const, % so it fails to match the parameter of func(). -[pixel shader fail(sm>=6) todo(sm>=4)] +[pixel shader fail(sm>=6)] uniform float4 f; @@ -43,12 +43,12 @@ float4 main() : sv_target [test] uniform 0 float4 -1.9 -1.0 2.9 4.0 -todo(sm>=4) draw quad +draw quad probe (0, 0) rgba (-1.0, -1.0, 2.0, 4.0) % As above, but declare "x" as float4 and cast it to int4. -[pixel shader fail(sm>=6) todo(sm>=4)] +[pixel shader fail(sm>=6)] uniform float4 f; @@ -66,7 +66,7 @@ float4 main() : sv_target [test] uniform 0 float4 -1.9 -1.0 2.9 4.0 -todo(sm>=4) draw quad +draw quad probe (0, 0) rgba (-1.0, -1.0, 2.0, 4.0) @@ -93,7 +93,7 @@ probe (0, 0) rgba (-1.0, 0.0, 1.0, -3000000.0) 4 % An explicit cast gets applied right before assignment, as if it was on the lhs. -[pixel shader fail(sm>=6) todo(sm>=4)] +[pixel shader fail(sm>=6)] void fun(out float4 f) { f = float4(1.4, 2.6, 3.9, 4.3); @@ -108,7 +108,7 @@ float4 main() : sv_target } [test] -todo(sm>=4) draw quad +draw quad probe (0, 0) rgba(1, 2, 3, 4) diff --git a/tests/hlsl/trigonometry.shader_test b/tests/hlsl/trigonometry.shader_test index b966a8aa..1bce3628 100644 --- a/tests/hlsl/trigonometry.shader_test +++ b/tests/hlsl/trigonometry.shader_test @@ -162,7 +162,7 @@ float4 main() : sv_target return float4(6789); } -[pixel shader todo(sm>=4)] +[pixel shader] float4 main() : sv_target { int sin_out, cos_out; @@ -171,5 +171,5 @@ float4 main() : sv_target } [test] -todo(sm>=4 & sm<6) draw quad +todo(glsl | msl) draw quad probe (0, 0) rgba (0, 0, 0, 0);