diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 9c75c87d..54227041 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1214,12 +1214,23 @@ static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl return true; } -static bool parse_reservation_index(const char *string, char *type, uint32_t *index) +static bool parse_reservation_index(const char *string, char *type, uint32_t *index, unsigned int bracket_offset) { - if (!sscanf(string + 1, "%u", index)) - return false; + char *endptr; *type = ascii_tolower(string[0]); + + if (string[1] == '\0') + { + *index = bracket_offset; + return true; + } + + *index = strtoul(string + 1, &endptr, 10) + bracket_offset; + + if (endptr == string + 1) + return false; + return true; } @@ -6545,22 +6556,35 @@ register_reservation: ':' KW_REGISTER '(' any_identifier ')' { memset(&$$, 0, sizeof($$)); - if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index)) + if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index, 0)) hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, "Invalid register reservation '%s'.", $4); vkd3d_free($4); } + | ':' KW_REGISTER '(' any_identifier '[' expr ']' ')' + { + memset(&$$, 0, sizeof($$)); + if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index, + evaluate_static_expression_as_uint(ctx, $6, &@6))) + { + hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $4); + } + + vkd3d_free($4); + vkd3d_free($6); + } | ':' KW_REGISTER '(' any_identifier ',' any_identifier ')' { memset(&$$, 0, sizeof($$)); - if (parse_reservation_index($6, &$$.reg_type, &$$.reg_index)) + if (parse_reservation_index($6, &$$.reg_type, &$$.reg_index, 0)) { hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); } else if (parse_reservation_space($6, &$$.reg_space)) { - if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index)) + if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index, 0)) hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, "Invalid register reservation '%s'.", $4); } @@ -6573,12 +6597,47 @@ register_reservation: vkd3d_free($4); vkd3d_free($6); } + | ':' KW_REGISTER '(' any_identifier '[' expr ']' ',' any_identifier ')' + { + memset(&$$, 0, sizeof($$)); + + if (!parse_reservation_space($9, &$$.reg_space)) + hlsl_error(ctx, &@9, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register space reservation '%s'.", $9); + + if (!parse_reservation_index($4, &$$.reg_type, &$$.reg_index, + evaluate_static_expression_as_uint(ctx, $6, &@6))) + { + hlsl_error(ctx, &@4, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $4); + } + + vkd3d_free($4); + vkd3d_free($6); + vkd3d_free($9); + } + | ':' KW_REGISTER '(' any_identifier ',' any_identifier '[' expr ']' ')' + { + hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); + + memset(&$$, 0, sizeof($$)); + if (!parse_reservation_index($6, &$$.reg_type, &$$.reg_index, + evaluate_static_expression_as_uint(ctx, $8, &@8))) + { + hlsl_error(ctx, &@6, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $6); + } + + vkd3d_free($4); + vkd3d_free($6); + vkd3d_free($8); + } | ':' KW_REGISTER '(' any_identifier ',' any_identifier ',' any_identifier ')' { hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); memset(&$$, 0, sizeof($$)); - if (!parse_reservation_index($6, &$$.reg_type, &$$.reg_index)) + if (!parse_reservation_index($6, &$$.reg_type, &$$.reg_index, 0)) hlsl_error(ctx, &@6, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, "Invalid register reservation '%s'.", $6); @@ -6590,6 +6649,27 @@ register_reservation: vkd3d_free($6); vkd3d_free($8); } + | ':' KW_REGISTER '(' any_identifier ',' any_identifier '[' expr ']' ',' any_identifier ')' + { + hlsl_fixme(ctx, &@4, "Reservation shader target %s.", $4); + + memset(&$$, 0, sizeof($$)); + if (!parse_reservation_index($6, &$$.reg_type, &$$.reg_index, + evaluate_static_expression_as_uint(ctx, $8, &@8))) + { + hlsl_error(ctx, &@6, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register reservation '%s'.", $6); + } + + if (!parse_reservation_space($11, &$$.reg_space)) + hlsl_error(ctx, &@11, VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION, + "Invalid register space reservation '%s'.", $11); + + vkd3d_free($4); + vkd3d_free($6); + vkd3d_free($8); + vkd3d_free($11); + } packoffset_reservation: ':' KW_PACKOFFSET '(' any_identifier ')' diff --git a/tests/hlsl/register-reservations-numeric.shader_test b/tests/hlsl/register-reservations-numeric.shader_test index a87a3652..a6d7e087 100644 --- a/tests/hlsl/register-reservations-numeric.shader_test +++ b/tests/hlsl/register-reservations-numeric.shader_test @@ -296,7 +296,7 @@ uniform 0 float 1.0 todo(glsl) draw quad probe (0, 0) rgba (1.0, 1.0, 1.0, 1.0) -[pixel shader todo] +[pixel shader] // Numeric expr, no offset in the identifier. DXC ignores this. float a : register (c[1 + 1 * 2 * 0]); @@ -308,11 +308,11 @@ float4 main() : sv_target [test] uniform 0 float 1.0 uniform 4 float 2.0 -todo(glsl|sm<6) draw quad +todo(glsl) draw quad if(sm<6) probe (0, 0) rgba (2.0, 2.0, 2.0, 2.0) if(sm>=6) probe (0, 0) rgba(1.0, 1.0, 1.0, 1.0) -[pixel shader todo] +[pixel shader] // Numeric expr. DXC also ignores this. float a : register (c0[1 + 1 * 2 * 0]); @@ -324,11 +324,11 @@ float4 main() : sv_target [test] uniform 0 float 0.0 uniform 4 float 1.0 -todo(glsl|sm<6) draw quad +todo(glsl) draw quad if(sm<6) probe (0, 0) rgba (1.0, 1.0, 1.0, 1.0) if(sm>=6) probe (0, 0) rgba (0.0, 0.0, 0.0, 0.0) -[pixel shader todo] +[pixel shader] // Float offsets truncate. float a : register (c0[0.6 + 0.6]); @@ -340,11 +340,11 @@ float4 main() : sv_target [test] uniform 0 float 0.0 uniform 4 float 1.0 -todo(glsl|sm<6) draw quad +todo(glsl) draw quad if(sm<6) probe (0, 0) rgba (1.0, 1.0, 1.0, 1.0) if(sm>=6) probe (0, 0) rgba (0.0, 0.0, 0.0, 0.0) -[pixel shader todo] +[pixel shader] // Booleans are interpreted as integers in the usual way. float a : register (c0[true + false * true]); @@ -356,11 +356,11 @@ float4 main() : sv_target [test] uniform 0 float 0.0 uniform 4 float 1.0 -todo(glsl|sm<6) draw quad +todo(glsl) draw quad if(sm<6) probe (0, 0) rgba (1.0, 1.0, 1.0, 1.0) if(sm>=6) probe (0, 0) rgba (0.0, 0.0, 0.0, 0.0) -[pixel shader fail(sm>=6) todo] +[pixel shader fail(sm>=6)] // Negative offsets. DXC fails to compile this. float a : register (c2[-1]); @@ -371,7 +371,7 @@ float4 main() : sv_target [test] uniform 4 float 1.0 -todo draw quad +todo(glsl) draw quad probe (0, 0) rgba (1.0, 1.0, 1.0, 1.0) % Weird FXC behavior. @@ -484,7 +484,7 @@ size (2d, 1, 2) [require] shader model >= 4.0 -[pixel shader todo] +[pixel shader] Texture2D tex : register(t[1]); sampler sam : register(s[1]); @@ -494,6 +494,6 @@ float4 main() : sv_target } [test] -todo(sm<6) draw quad +todo(glsl) draw quad if(sm<6) probe (0, 0) rgba(2.0, 2.0, 2.0, 2.0) if(sm>=6) probe (0, 0) rgba(0.5, 0.5, 0.5, 0.5) diff --git a/tests/hlsl/register-reservations-space.shader_test b/tests/hlsl/register-reservations-space.shader_test index 71644e5e..fe42b100 100644 --- a/tests/hlsl/register-reservations-space.shader_test +++ b/tests/hlsl/register-reservations-space.shader_test @@ -30,7 +30,7 @@ todo(glsl) draw quad probe (0, 0) rgba (1, 1, 1, 99) % Bracket syntax for registers. Ignored in SM>=6. -[pixel shader todo] +[pixel shader] Texture2D tex1 : register(t[1], space0); float4 main() : sv_target @@ -39,7 +39,7 @@ float4 main() : sv_target } [test] -todo(sm<6) draw quad +todo(glsl) draw quad if(sm>=6) probe (0, 0) rgba (0, 0, 0, 99) if(sm<6) probe (0, 0) rgba (1, 1, 1, 99)