From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 26 +++++++ libs/vkd3d-shader/hlsl.h | 21 +++++ libs/vkd3d-shader/hlsl.y | 108 +++++++++++++++++++++++++- tests/hlsl/technique-fx_2.shader_test | 10 +-- tests/hlsl/technique-fx_4.shader_test | 8 +- tests/hlsl/technique-fx_5.shader_test | 8 +- 6 files changed, 165 insertions(+), 16 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index c8677f41..4bbaba0b 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -142,6 +142,12 @@ void hlsl_free_var(struct hlsl_ir_var *decl) vkd3d_free(decl); }
+void hlsl_free_technique(struct hlsl_technique *technique) +{ + vkd3d_free(technique->name); + vkd3d_free(technique); +} + bool hlsl_type_is_row_major(const struct hlsl_type *type) { /* Default to column-major if the majority isn't explicitly set, which can @@ -3544,6 +3550,8 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil
list_init(&ctx->buffers);
+ list_init(&ctx->effect_groups); + if (!(ctx->globals_buffer = hlsl_new_buffer(ctx, HLSL_BUFFER_CONSTANT, hlsl_strdup(ctx, "$Globals"), NULL, &ctx->location))) return false; @@ -3572,8 +3580,19 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil return true; }
+static void cleanup_effect_group(struct hlsl_effect_group *group) +{ + unsigned int i; + + for (i = 0; i < group->count; ++i) + hlsl_free_technique(group->techniques[i]); + vkd3d_free((void *)group->name); + vkd3d_free(group->techniques); +} + static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) { + struct hlsl_effect_group *group, *next_group; struct hlsl_buffer *buffer, *next_buffer; struct hlsl_scope *scope, *next_scope; struct hlsl_ir_var *var, *next_var; @@ -3606,6 +3625,13 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) vkd3d_free(buffer); }
+ cleanup_effect_group(&ctx->default_effect_group); + LIST_FOR_EACH_ENTRY_SAFE(group, next_group, &ctx->effect_groups, struct hlsl_effect_group, entry) + { + cleanup_effect_group(group); + vkd3d_free(group); + } + vkd3d_free(ctx->constant_defs.regs); }
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 309d7080..07662bf9 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -435,6 +435,19 @@ struct hlsl_ir_var uint32_t is_separated_resource : 1; };
+struct hlsl_technique +{ + char *name; +}; + +struct hlsl_effect_group +{ + struct list entry; + char *name; + struct hlsl_technique **techniques; + unsigned int count; +}; + /* Sized array of variables representing a function's parameters. */ struct hlsl_func_parameters { @@ -842,6 +855,11 @@ struct hlsl_ctx struct rb_tree functions; /* Pointer to the current function; changes as the parser reads the code. */ const struct hlsl_ir_function_decl *cur_function; + /* Default effect group. Techniques defined outside of explicit groups belong here. + Groups are only supported in fx_5_0, we use single default group for older profiles too. */ + struct hlsl_effect_group default_effect_group; + /* Explicit effect groups; linked by the hlsl_effect_group.entry. */ + struct list effect_groups;
/* Counter for generating unique internal variable names. */ unsigned int internal_name_counter; @@ -1166,6 +1184,7 @@ void hlsl_free_instr(struct hlsl_ir_node *node); void hlsl_free_instr_list(struct list *list); void hlsl_free_type(struct hlsl_type *type); void hlsl_free_var(struct hlsl_ir_var *decl); +void hlsl_free_technique(struct hlsl_technique *technique);
struct hlsl_ir_function *hlsl_get_function(struct hlsl_ctx *ctx, const char *name); struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const char *name); @@ -1257,6 +1276,8 @@ struct hlsl_ir_switch_case *hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned struct hlsl_block *body, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_new_switch(struct hlsl_ctx *ctx, struct hlsl_ir_node *selector, struct list *cases, const struct vkd3d_shader_location *loc); +struct hlsl_effect_group *hlsl_new_effect_group(struct hlsl_ctx *ctx, const char *name, + struct hlsl_technique *techniques, unsigned int count);
void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5); diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index c9e7335b..82ed99e6 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -114,6 +114,12 @@ struct parse_attribute_list const struct hlsl_attribute **attrs; };
+struct parse_technique_list +{ + struct hlsl_technique **techniques; + size_t count, capacity; +}; + }
%code provides @@ -1096,6 +1102,68 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters return true; }
+static bool add_technique(struct hlsl_ctx *ctx, struct parse_technique_list *list, struct hlsl_technique *technique) +{ + if (!hlsl_array_reserve(ctx, (void **)&list->techniques, &list->capacity, list->count + 1, sizeof(*list->techniques))) + return false; + list->techniques[list->count++] = technique; + return true; +} + +static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, const struct parse_technique_list *techniques) +{ + struct hlsl_effect_group *group; + + if (!(group = hlsl_alloc(ctx, sizeof(*group)))) + return false; + if (!(group->name = hlsl_strdup(ctx, name))) + { + vkd3d_free(group); + return false; + } + + group->techniques = techniques->techniques; + group->count = techniques->count; + + list_add_tail(&ctx->effect_groups, &group->entry); + + return true; +} + +static struct hlsl_technique *create_technique(struct hlsl_ctx *ctx, const char *name, + const struct vkd3d_shader_location *loc) +{ + struct hlsl_technique *technique; + struct hlsl_ir_var *var; + + if (!(technique = hlsl_alloc(ctx, sizeof(*technique)))) + return NULL; + + if (name) + { + if (!(technique->name = hlsl_strdup(ctx, name))) + { + vkd3d_free(technique); + return NULL; + } + + if (!(var = hlsl_new_var(ctx, name, ctx->builtin_types.Void, loc, NULL, 0, NULL))) + { + hlsl_free_technique(technique); + return NULL; + } + + if (!hlsl_add_var(ctx, var, false)) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, "Redefintion of '%s'.", name); + hlsl_free_technique(technique); + return NULL; + } + } + + return technique; +} + static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string) { struct hlsl_reg_reservation reservation = {0}; @@ -4766,6 +4834,8 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls struct hlsl_attribute *attr; struct parse_attribute_list attr_list; struct hlsl_ir_switch_case *switch_case; + struct hlsl_technique *technique; + struct parse_technique_list techniques; }
%token KW_BLENDSTATE @@ -4972,6 +5042,12 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls
%type <switch_case> switch_case
+%type <technique> technique +%type <technique> technique9 +%type <technique> technique10 +%type <technique> technique11 +%type <techniques> techniques + %type <type> field_type %type <type> named_struct_spec %type <type> unnamed_struct_spec @@ -4999,6 +5075,7 @@ hlsl_prog: } | hlsl_prog preproc_directive | hlsl_prog technique + | hlsl_prog effect_group | hlsl_prog ';'
technique_name: @@ -5014,7 +5091,7 @@ pass_list: technique9: KW_TECHNIQUE technique_name '{' pass_list '}' { - hlsl_fixme(ctx, &@$, "Unsupported 'technique' declaration."); + $$ = create_technique(ctx, $2, &@2); }
technique10: @@ -5024,7 +5101,7 @@ technique10: hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "The 'technique10' keyword is invalid for this profile.");
- hlsl_fixme(ctx, &@$, "Unsupported 'technique10' declaration."); + $$ = create_technique(ctx, $2, &@2); }
technique11: @@ -5034,13 +5111,38 @@ technique11: hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, "The 'technique11' keyword is invalid for this profile.");
- hlsl_fixme(ctx, &@$, "Unsupported 'technique11' declaration."); + $$ = create_technique(ctx, $2, &@2); }
technique: technique9 | technique10 | technique11 + { + $$ = $1; + } + +techniques: + technique + { + memset(&$$, 0, sizeof($$)); + if (!add_technique(ctx, &$$, $1)) + YYABORT; + } + | techniques technique + { + $$ = $1; + if (!add_technique(ctx, &$$, $2)) + YYABORT; + } + +effect_group: + KW_FXGROUP any_identifier '{' scope_start techniques '}' + { + if (!(add_effect_group(ctx, $2, &$5))) + YYABORT; + hlsl_pop_scope(ctx); + }
buffer_declaration: buffer_type any_identifier colon_attribute diff --git a/tests/hlsl/technique-fx_2.shader_test b/tests/hlsl/technique-fx_2.shader_test index f86cc005..4a18430a 100644 --- a/tests/hlsl/technique-fx_2.shader_test +++ b/tests/hlsl/technique-fx_2.shader_test @@ -90,7 +90,7 @@ technique10 float4 f;
% fx_5_0 keyword fails with fx_2_0 profile -[effect fail todo] +[effect fail] technique { } @@ -99,7 +99,7 @@ technique11 { }
-[effect fail todo] +[effect fail] technique { } @@ -108,7 +108,7 @@ tEchnique10 { }
-[effect fail todo] +[effect fail] technique { } @@ -123,7 +123,7 @@ fxgroup group }
% Regular shaders with technique blocks -[vertex shader todo] +[vertex shader] float4 main() : sv_position { return 0; @@ -147,7 +147,7 @@ fxgroup group technique10 {} }
-[pixel shader todo] +[pixel shader] float4 main() : sv_target { return 0; diff --git a/tests/hlsl/technique-fx_4.shader_test b/tests/hlsl/technique-fx_4.shader_test index 7968cb9d..9bd1a8d7 100644 --- a/tests/hlsl/technique-fx_4.shader_test +++ b/tests/hlsl/technique-fx_4.shader_test @@ -60,7 +60,7 @@ technique11 { }
-[effect fail todo] +[effect fail] technique { } @@ -69,7 +69,7 @@ tEchnique10 { }
-[effect fail todo] +[effect fail] technique { } @@ -97,7 +97,7 @@ float4 technIque10; float4 technIque11;
% Regular shaders with technique blocks -[vertex shader todo] +[vertex shader] float4 main() : sv_position { return 0; @@ -120,7 +120,7 @@ fxgroup group technique10 {} }
-[pixel shader todo] +[pixel shader] float4 main() : sv_target { return 0; diff --git a/tests/hlsl/technique-fx_5.shader_test b/tests/hlsl/technique-fx_5.shader_test index 29aa616f..0ef88cd0 100644 --- a/tests/hlsl/technique-fx_5.shader_test +++ b/tests/hlsl/technique-fx_5.shader_test @@ -60,7 +60,7 @@ technique11 { }
-[effect fail todo] +[effect fail] technique { } @@ -69,7 +69,7 @@ tEchnique10 { }
-[effect fail todo] +[effect fail] technique { } @@ -97,7 +97,7 @@ float4 technIque10; float4 technIque11;
% Regular shaders with technique blocks -[vertex shader todo] +[vertex shader] float4 main() : sv_position { return 0; @@ -120,7 +120,7 @@ fxgroup group technique10 {} }
-[pixel shader todo] +[pixel shader] float4 main() : sv_target { return 0;