diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index 14ff9c4e..0857ebb6 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -56,6 +56,70 @@ static void string_storage_destroy(struct rb_entry *entry, void *context) vkd3d_free(string_entry); } +struct state_block_function_info +{ + const char *name; + unsigned int min_args, max_args; +}; + +static const struct state_block_function_info *get_state_block_function_info(const char *name) +{ + static const struct state_block_function_info valid_functions[] = + { + {"SetBlendState", 3, 3}, + {"SetDepthStencilState", 2, 2}, + {"SetRasterizerState", 1, 1}, + {"SetVertexShader", 1, 1}, + {"SetDomainShader", 1, 1}, + {"SetHullShader", 1, 1}, + {"SetGeometryShader", 1, 1}, + {"SetPixelShader", 1, 1}, + {"SetComputeShader", 1, 1}, + {"OMSetRenderTargets", 2, 9}, + }; + + for (unsigned int i = 0; i < ARRAY_SIZE(valid_functions); ++i) + { + if (!strcmp(name, valid_functions[i].name)) + return &valid_functions[i]; + } + return NULL; +} + +bool hlsl_validate_state_block_entry(struct hlsl_ctx *ctx, struct hlsl_state_block_entry *entry, + const struct vkd3d_shader_location *loc) +{ + if (entry->is_function_call) + { + const struct state_block_function_info *info = get_state_block_function_info(entry->name); + + if (!info) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY, + "Invalid state block function '%s'.", entry->name); + return false; + } + if (entry->args_count < info->min_args || entry->args_count > info->max_args) + { + if (info->min_args == info->max_args) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY, + "Invalid argument count for state block function '%s' (expected %u).", + entry->name, info->min_args); + } + else + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY, + "Invalid argument count for state block function '%s' (expected from %u to %u).", + entry->name, info->min_args, info->max_args); + } + return false; + } + } + + return true; +} + struct fx_write_context; struct fx_write_context_ops diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 65e5ab17..4a17818e 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -1293,6 +1293,9 @@ bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func); void hlsl_dump_var_default_values(const struct hlsl_ir_var *var); +bool hlsl_validate_state_block_entry(struct hlsl_ctx *ctx, struct hlsl_state_block_entry *entry, + const struct vkd3d_shader_location *loc); + void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body); int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out); diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 7cba28cd..80e73e38 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -7405,6 +7405,8 @@ state_block: hlsl_src_from_node(&entry->args[i], $4.args[i]); vkd3d_free($4.args); + hlsl_validate_state_block_entry(ctx, entry, &@4); + $$ = $1; state_block_add_entry($$, entry); } diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 7d1f4942..f038fd89 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -151,6 +151,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE = 5028, VKD3D_SHADER_ERROR_HLSL_MISSING_TECHNIQUE = 5029, VKD3D_SHADER_ERROR_HLSL_UNKNOWN_MODIFIER = 5030, + VKD3D_SHADER_ERROR_HLSL_INVALID_STATE_BLOCK_ENTRY = 5031, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, diff --git a/tests/hlsl/state-block-function-syntax.shader_test b/tests/hlsl/state-block-function-syntax.shader_test index da9387b0..6b7d85e3 100644 --- a/tests/hlsl/state-block-function-syntax.shader_test +++ b/tests/hlsl/state-block-function-syntax.shader_test @@ -27,7 +27,7 @@ sampler sam float4 main() : sv_target { return 0; } -[pixel shader fail(sm<6) todo] +[pixel shader fail(sm<6)] sampler sam { SetSomeotherState(); @@ -36,7 +36,7 @@ sampler sam float4 main() : sv_target { return 0; } -[pixel shader fail(sm<6) todo] +[pixel shader fail(sm<6)] sampler sam { Setblendstate(1, 2, 3); // Test case-sensitivity.