From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- tests/hlsl/technique-fx_2.shader_test | 31 +++++++++++++ tests/hlsl/technique-fx_4.shader_test | 24 ++++++++++ tests/hlsl/technique-fx_5.shader_test | 66 +++++++++++++++++++++++++++ 3 files changed, 121 insertions(+)
diff --git a/tests/hlsl/technique-fx_2.shader_test b/tests/hlsl/technique-fx_2.shader_test index 90c734d5..42e523f2 100644 --- a/tests/hlsl/technique-fx_2.shader_test +++ b/tests/hlsl/technique-fx_2.shader_test @@ -38,6 +38,13 @@ float4 main() : sv_target return float4(0, 0, 0, 0); }
+[pixel shader fail todo] +float4 main() : sv_target +{ + float4 fxgroup = {0, 0, 0, 0}; + return fxgroup; +} + [pixel shader] typedef float4 Technique10; typedef float4 Technique11; @@ -62,6 +69,13 @@ float4 main() : sv_target return teChnique11; }
+[pixel shader] +float4 main() : sv_target +{ + float4 fxGroup = {0, 0, 0, 0}; + return fxGroup; +} + [effect todo] technique { @@ -103,6 +117,11 @@ tEchnique11 { }
+[effect fail] +fxgroup group +{ +} + % Regular shaders with technique blocks [vertex shader todo] float4 main() : sv_position @@ -122,6 +141,12 @@ technique11 { }
+// Empty groups are not allowed +fxgroup group +{ + technique10 {} +} + [pixel shader todo] float4 main() : sv_target { @@ -139,3 +164,9 @@ technique10 technique11 { } + +// Empty groups are not allowed +fxgroup group +{ + technique10 {} +} diff --git a/tests/hlsl/technique-fx_4.shader_test b/tests/hlsl/technique-fx_4.shader_test index fb8a3e67..2fc481de 100644 --- a/tests/hlsl/technique-fx_4.shader_test +++ b/tests/hlsl/technique-fx_4.shader_test @@ -9,6 +9,13 @@ float4 main() : sv_target return teChnique; }
+[pixel shader fail todo] +float4 main() : sv_target +{ + float4 fxgroup = {0, 0, 0, 0}; + return fxgroup; +} + [pixel shader] float4 main() : sv_target { @@ -23,6 +30,13 @@ float4 main() : sv_target return teChnique11; }
+[pixel shader] +float4 main() : sv_target +{ + float4 fxGroup = {0, 0, 0, 0}; + return fxGroup; +} + [effect todo] technique { @@ -101,6 +115,11 @@ technique11 { }
+fxgroup group +{ + technique10 {} +} + [pixel shader todo] float4 main() : sv_target { @@ -118,3 +137,8 @@ technique10 technique11 { } + +fxgroup group +{ + technique10 {} +} diff --git a/tests/hlsl/technique-fx_5.shader_test b/tests/hlsl/technique-fx_5.shader_test index aeea1a84..152227c6 100644 --- a/tests/hlsl/technique-fx_5.shader_test +++ b/tests/hlsl/technique-fx_5.shader_test @@ -9,6 +9,13 @@ float4 main() : sv_target return teChnique; }
+[pixel shader fail todo] +float4 main() : sv_target +{ + float4 fxgroup = {0, 0, 0, 0}; + return fxgroup; +} + [pixel shader] float4 main() : sv_target { @@ -23,6 +30,13 @@ float4 main() : sv_target return teChnique11; }
+[pixel shader] +float4 main() : sv_target +{ + float4 fxGroup = {0, 0, 0, 0}; + return fxGroup; +} + [effect todo] technique { @@ -101,6 +115,11 @@ technique11 { }
+fxgroup group +{ + technique10 {} +} + [pixel shader todo] float4 main() : sv_target { @@ -118,3 +137,50 @@ technique10 technique11 { } + +fxgroup group +{ + technique10 {} +} + +% Groups syntax + +% Name has to be specified, it belongs to global scope +[effect fail] +fxgroup +{ +} + +% Group can't be empty +[effect fail] +fxgroup group +{ +} + +[effect fail] +float4 group; + +fxgroup group +{ +} + +% Groups can only contain a list of techniques +[effect fail] +fxgroup group +{ + float4 v; + + technique11 {} +} + +% Group provides scope for techniques +[effect todo] +fxgroup group1 +{ + technique11 tech0 {} +} + +fxgroup group2 +{ + technique11 tech0 {} +}
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.l | 1 + libs/vkd3d-shader/hlsl.y | 1 + tests/hlsl/technique-fx_2.shader_test | 2 +- tests/hlsl/technique-fx_4.shader_test | 2 +- tests/hlsl/technique-fx_5.shader_test | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.l b/libs/vkd3d-shader/hlsl.l index 83fe1d34..7eda671a 100644 --- a/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d-shader/hlsl.l @@ -89,6 +89,7 @@ else {return KW_ELSE; } extern {return KW_EXTERN; } false {return KW_FALSE; } for {return KW_FOR; } +fxgroup {return KW_FXGROUP; } GeometryShader {return KW_GEOMETRYSHADER; } groupshared {return KW_GROUPSHARED; } if {return KW_IF; } diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 3c30c0cb..c9e7335b 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -4788,6 +4788,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls %token KW_EXTERN %token KW_FALSE %token KW_FOR +%token KW_FXGROUP %token KW_GEOMETRYSHADER %token KW_GROUPSHARED %token KW_IF diff --git a/tests/hlsl/technique-fx_2.shader_test b/tests/hlsl/technique-fx_2.shader_test index 42e523f2..f86cc005 100644 --- a/tests/hlsl/technique-fx_2.shader_test +++ b/tests/hlsl/technique-fx_2.shader_test @@ -38,7 +38,7 @@ float4 main() : sv_target return float4(0, 0, 0, 0); }
-[pixel shader fail todo] +[pixel shader fail] float4 main() : sv_target { float4 fxgroup = {0, 0, 0, 0}; diff --git a/tests/hlsl/technique-fx_4.shader_test b/tests/hlsl/technique-fx_4.shader_test index 2fc481de..7968cb9d 100644 --- a/tests/hlsl/technique-fx_4.shader_test +++ b/tests/hlsl/technique-fx_4.shader_test @@ -9,7 +9,7 @@ float4 main() : sv_target return teChnique; }
-[pixel shader fail todo] +[pixel shader fail] float4 main() : sv_target { float4 fxgroup = {0, 0, 0, 0}; diff --git a/tests/hlsl/technique-fx_5.shader_test b/tests/hlsl/technique-fx_5.shader_test index 152227c6..29aa616f 100644 --- a/tests/hlsl/technique-fx_5.shader_test +++ b/tests/hlsl/technique-fx_5.shader_test @@ -9,7 +9,7 @@ float4 main() : sv_target return teChnique; }
-[pixel shader fail todo] +[pixel shader fail] float4 main() : sv_target { float4 fxgroup = {0, 0, 0, 0};
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;
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.h | 2 +- libs/vkd3d-shader/hlsl.y | 19 +++++++++++++++++-- tests/hlsl/technique-fx_5.shader_test | 14 ++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 07662bf9..8b0a7c21 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -445,7 +445,7 @@ struct hlsl_effect_group struct list entry; char *name; struct hlsl_technique **techniques; - unsigned int count; + size_t count, capacity; };
/* Sized array of variables representing a function's parameters. */ diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 82ed99e6..e4c97d78 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -5042,6 +5042,7 @@ static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hls
%type <switch_case> switch_case
+%type <technique> default_group_technique %type <technique> technique %type <technique> technique9 %type <technique> technique10 @@ -5074,7 +5075,7 @@ hlsl_prog: destroy_block($2); } | hlsl_prog preproc_directive - | hlsl_prog technique + | hlsl_prog default_group_technique | hlsl_prog effect_group | hlsl_prog ';'
@@ -5114,9 +5115,23 @@ technique11: $$ = create_technique(ctx, $2, &@2); }
-technique: +default_group_technique: technique9 | technique10 + | technique11 + { + struct hlsl_effect_group *group = &ctx->default_effect_group; + + if (!hlsl_array_reserve(ctx, (void **)&group->techniques, &group->capacity, + group->count + 1, sizeof(*group->techniques))) + { + YYABORT; + } + group->techniques[group->count++] = $1; + } + +technique: + technique10 | technique11 { $$ = $1; diff --git a/tests/hlsl/technique-fx_5.shader_test b/tests/hlsl/technique-fx_5.shader_test index 0ef88cd0..0826c20b 100644 --- a/tests/hlsl/technique-fx_5.shader_test +++ b/tests/hlsl/technique-fx_5.shader_test @@ -184,3 +184,17 @@ fxgroup group2 { technique11 tech0 {} } + +% fx_4_x techniques are allowed in explicit groups, fx_2_0 ones are not +[effect fail] +fxgroup group +{ + technique t1 {} + technique10 t2 {} +} + +[effect todo] +fxgroup group +{ + technique10 {} +}
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.h | 3 +++ libs/vkd3d-shader/hlsl.y | 54 +++++++++++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 12 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 8b0a7c21..fde556e7 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -438,6 +438,9 @@ struct hlsl_ir_var struct hlsl_technique { char *name; + /* Skips serialization of the technique its data. Used to control + exclude techniques with syntax that's not supported by target profile. */ + bool skip; };
struct hlsl_effect_group diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index e4c97d78..d30efdc0 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1113,6 +1113,7 @@ static bool add_technique(struct hlsl_ctx *ctx, struct parse_technique_list *lis static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, const struct parse_technique_list *techniques) { struct hlsl_effect_group *group; + unsigned int i;
if (!(group = hlsl_alloc(ctx, sizeof(*group)))) return false; @@ -1125,19 +1126,56 @@ static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, const struc group->techniques = techniques->techniques; group->count = techniques->count;
+ /* Explicit groups are only used with fx_5_0, skip all contained techniques for older profiles. */ + if (ctx->profile->major_version < 5) + { + for (i = 0; i < group->count; ++i) + group->techniques[i]->skip = true; + } + list_add_tail(&ctx->effect_groups, &group->entry);
return true; }
+enum technique_type +{ + TECHNIQUE9, + TECHNIQUE10, + TECHNIQUE11, +}; + static struct hlsl_technique *create_technique(struct hlsl_ctx *ctx, const char *name, - const struct vkd3d_shader_location *loc) + enum technique_type technique_type, const struct vkd3d_shader_location *loc) { struct hlsl_technique *technique; struct hlsl_ir_var *var; + bool skip; + + if (technique_type == TECHNIQUE9) + { + skip = ctx->profile->major_version > 2; + } + else if (technique_type == TECHNIQUE10) + { + if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, + "The 'technique10' keyword is invalid for this profile."); + + skip = ctx->profile->major_version == 2; + } + else if (technique_type == TECHNIQUE11) + { + if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, + "The 'technique11' keyword is invalid for this profile."); + + skip = ctx->profile->major_version == 4; + }
if (!(technique = hlsl_alloc(ctx, sizeof(*technique)))) return NULL; + technique->skip = skip;
if (name) { @@ -5092,27 +5130,19 @@ pass_list: technique9: KW_TECHNIQUE technique_name '{' pass_list '}' { - $$ = create_technique(ctx, $2, &@2); + $$ = create_technique(ctx, $2, TECHNIQUE9, &@2); }
technique10: KW_TECHNIQUE10 technique_name '{' pass_list '}' { - if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, - "The 'technique10' keyword is invalid for this profile."); - - $$ = create_technique(ctx, $2, &@2); + $$ = create_technique(ctx, $2, TECHNIQUE10, &@2); }
technique11: KW_TECHNIQUE11 technique_name '{' pass_list '}' { - if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) - hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, - "The 'technique11' keyword is invalid for this profile."); - - $$ = create_technique(ctx, $2, &@2); + $$ = create_technique(ctx, $2, TECHNIQUE11, &@2); }
default_group_technique:
From patch 3:
``` + 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; + } ```
I'm inclined to think we should either make techniques variables, or make them non-variables, rather than doing both.
(Also, creating a variable but setting the type to "void" is probably going to result in some less-than-perfectly-clear error messages).
As a side note, I won't ask to change it, but patch 3/5 does two different things which I feel could have been split: it creates actual objects for techniques, and separately it implements effect group syntax.
From patch 5/5:
``` + if (technique_type == TECHNIQUE9) + { + skip = ctx->profile->major_version > 2; + } + else if (technique_type == TECHNIQUE10) + { + if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, + "The 'technique10' keyword is invalid for this profile."); + + skip = ctx->profile->major_version == 2; + } + else if (technique_type == TECHNIQUE11) + { + if (ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT && ctx->profile->major_version == 2) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX, + "The 'technique11' keyword is invalid for this profile."); + + skip = ctx->profile->major_version == 4; + } ```
This may be a casualty of introducing code that isn't actually used yet (which is itself not great), but it seems surprising that we're going to emit an hlsl_error() and also bother setting the skip field, especially when we aren't doing the same for the 11 variant.
Also, would it maybe be more idiomatic to just store the technique level, and implement this logic when we actually emit techniques? [Are we going to need to store that information anyway?]
I'm inclined to think we should either make techniques variables, or make them non-variables, rather than doing both.
(Also, creating a variable but setting the type to "void" is probably going to result in some less-than-perfectly-clear error messages).
There are not really variables. There needs to be some way to have technique blocks at top level, then fxgroup block at top level, and techniques within groups. Next and final nesting level are passes that are contained in techniques. I don't see how this can nicely fit in the type system. That's why I used void.
Regarding skips, now I think that using lists here might be a better fit, so that I can do cleanup based on profile, before going further.
So, if not using variables, the only functionality needed here is to have something dummy in global scope that takes up the name, within groups, or within techniques you can't have variables, so it's easy to check names there against already added techniques/passes.
And yes, some splitting is necessary. I wanted some comments first to figure out general direction.
There are not really variables. There needs to be some way to have technique blocks at top level, then fxgroup block at top level, and techniques within groups. Next and final nesting level are passes that are contained in techniques. I don't see how this can nicely fit in the type system. That's why I used void.
I don't immediately see why it can't? You don't need to encode any of this in the type system. Any data that techniques have can just go in the hlsl_ir_var instead.
This goes for other effect-specific objects too, probably. At least some of those act (even) more like variables.
Void variables aren't bad, but slightly better for error reporting purposes would be to introduce a HLSL_TYPE_TECHNIQUE.
Alternatively we could just check for a name conflict with techniques in every place that we check for a name conflict with variables. I don't know offhand how many such places there are, so I don't know how ugly this would end up being.
On Fri Nov 3 19:51:35 2023 +0000, Zebediah Figura wrote:
There are not really variables. There needs to be some way to have
technique blocks at top level, then fxgroup block at top level, and techniques within groups. Next and final nesting level are passes that are contained in techniques. I don't see how this can nicely fit in the type system. That's why I used void. I don't immediately see why it can't? You don't need to encode any of this in the type system. Any data that techniques have can just go in the hlsl_ir_var instead. This goes for other effect-specific objects too, probably. At least some of those act (even) more like variables. Void variables aren't bad, but slightly better for error reporting purposes would be to introduce a HLSL_TYPE_TECHNIQUE. Alternatively we could just check for a name conflict with techniques in every place that we check for a name conflict with variables. I don't know offhand how many such places there are, so I don't know how ugly this would end up being.
Ok, I can do TYPE_TECHNIQUE with CLASS_OBJECT, same for groups and passes. And later for other state types. Yes, hlsl_ir_var for group/technique/pass will need something extra in it.
It seems more sustainable to have them as regular variables so we don't need to chase conflict checks. I still think it's better to have a separate list for them and not use extern_vars. First so we don't need to filter them out for regular profiles compilation, and second so that order they appear in is stable and predictable, it's critical that order is preserved for index access. Maybe single list is already working well for that, but I think keeping effect objects slightly separately from normal shader compilation is not a bad idea.
I still think it's better to have a separate list for them and not use extern_vars. First so we don't need to filter them out for regular profiles compilation, and second so that order they appear in is stable and predictable, it's critical that order is preserved for index access. Maybe single list is already working well for that, but I think keeping effect objects slightly separately from normal shader compilation is not a bad idea.
I don't have a preëxisting opinion about that one, at least. Note that we already have some sorting logic for extern_vars, but that's not to pass a judgement on whether we should add more.
The main impetus for its addition was to collect globals, entry point parameters, and the entry point return value, all in one place, but that obviously isn't going to matter for techniques, or other things that are only in the global scope.
On Fri Nov 3 20:33:19 2023 +0000, Zebediah Figura wrote:
I still think it's better to have a separate list for them and not use
extern_vars. First so we don't need to filter them out for regular profiles compilation, and second so that order they appear in is stable and predictable, it's critical that order is preserved for index access. Maybe single list is already working well for that, but I think keeping effect objects slightly separately from normal shader compilation is not a bad idea. I don't have a preëxisting opinion about that one, at least. Note that we already have some sorting logic for extern_vars, but that's not to pass a judgement on whether we should add more. The main impetus for its addition was to collect globals, entry point parameters, and the entry point return value, all in one place, but that obviously isn't going to matter for techniques, or other things that are only in the global scope.
Looking again, I think having them as regular variables is not great, because name is optional for techniques and passes. And having a name is a minimum you'd expect from a variable.
Looking again, I think having them as regular variables is not great, because name is optional for techniques and passes. And having a name is a minimum you'd expect from a variable.
We can generate names if necessary. It also shouldn't be too difficult to handle nameless variables, but generating a name is probably easier.