From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 46 +++++++++++++++++++++------ libs/vkd3d-shader/hlsl.h | 3 ++ libs/vkd3d-shader/hlsl.y | 33 +++++++++++++++++-- tests/hlsl/technique-fx_2.shader_test | 6 ++-- tests/hlsl/technique-fx_4.shader_test | 4 +-- tests/hlsl/technique-fx_5.shader_test | 4 +-- 6 files changed, 76 insertions(+), 20 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index da3bbda1b..2f78bdb59 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -98,19 +98,22 @@ bool hlsl_add_var(struct hlsl_ctx *ctx, struct hlsl_ir_var *decl, bool local_var struct hlsl_scope *scope = ctx->cur_scope; struct hlsl_ir_var *var;
- LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) + if (decl->name) { - if (!strcmp(decl->name, var->name)) - return false; - } - if (local_var && scope->upper->upper == ctx->globals) - { - /* Check whether the variable redefines a function parameter. */ - LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry) + LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) { - if (!strcmp(decl->name, var->name)) + if (var->name && !strcmp(decl->name, var->name)) return false; } + if (local_var && scope->upper->upper == ctx->globals) + { + /* Check whether the variable redefines a function parameter. */ + LIST_FOR_EACH_ENTRY(var, &scope->upper->vars, struct hlsl_ir_var, scope_entry) + { + if (var->name && !strcmp(decl->name, var->name)) + return false; + } + } }
list_add_tail(&scope->vars, &decl->scope_entry); @@ -123,7 +126,7 @@ struct hlsl_ir_var *hlsl_get_var(struct hlsl_scope *scope, const char *name)
LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) { - if (!strcmp(name, var->name)) + if (var->name && !strcmp(name, var->name)) return var; } if (!scope->upper) @@ -915,6 +918,8 @@ bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2 if (t1->class == HLSL_CLASS_ARRAY) return t1->e.array.elements_count == t2->e.array.elements_count && hlsl_types_are_equal(t1->e.array.type, t2->e.array.type); + if (t1->base_type == HLSL_TYPE_TECHNIQUE && t1->e.version != t2->e.version) + return false;
return true; } @@ -996,6 +1001,8 @@ struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, default: break; } + if (type->base_type == HLSL_TYPE_TECHNIQUE) + type->e.version = old->e.version;
hlsl_type_calculate_reg_size(ctx, type);
@@ -3355,6 +3362,18 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) {"VERTEXSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_VERTEXSHADER, 1, 1}, };
+ static const struct + { + char *name; + unsigned int version; + } + technique_types[] = + { + {"technique", 9}, + {"technique10", 10}, + {"technique11", 11}, + }; + for (bt = 0; bt <= HLSL_TYPE_LAST_SCALAR; ++bt) { for (y = 1; y <= 4; ++y) @@ -3459,6 +3478,13 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) effect_types[i].base_type, effect_types[i].dimx, effect_types[i].dimy); hlsl_scope_add_type(ctx->globals, type); } + + for (i = 0; i < ARRAY_SIZE(technique_types); ++i) + { + type = hlsl_new_type(ctx, technique_types[i].name, HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE, 1, 1); + type->e.version = technique_types[i].version; + hlsl_scope_add_type(ctx->globals, type); + } }
static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compile_info *compile_info, diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 21b2fe383..bb63b010e 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -95,6 +95,7 @@ enum hlsl_base_type HLSL_TYPE_UAV, HLSL_TYPE_PIXELSHADER, HLSL_TYPE_VERTEXSHADER, + HLSL_TYPE_TECHNIQUE, HLSL_TYPE_STRING, HLSL_TYPE_VOID, }; @@ -191,6 +192,8 @@ struct hlsl_type /* Format of the data contained within the type if the base_type is HLSL_TYPE_TEXTURE or * HLSL_TYPE_UAV. */ struct hlsl_type *resource_format; + /* Additional field to distinguish object types. Currently used only for technique types. */ + unsigned int version; } e;
/* Number of numeric register components used by one value of this type, for each regset. diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 0123f4df1..ff10de9b9 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1096,6 +1096,30 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters return true; }
+static bool add_technique(struct hlsl_ctx *ctx, const char *name, const char *typename, + const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_var *var; + struct hlsl_type *type; + + type = hlsl_get_type(ctx->globals, typename, false, false); + if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) + return false; + + if (!hlsl_add_var(ctx, var, false)) + { + struct hlsl_ir_var *old = hlsl_get_var(ctx->cur_scope, var->name); + + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED, + "Variable "%s" was already declared in this scope.", var->name); + hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, ""%s" was previously declared here.", old->name); + hlsl_free_var(var); + return false; + } + + return true; +} + static struct hlsl_reg_reservation parse_reg_reservation(const char *reg_string) { struct hlsl_reg_reservation reservation = {0}; @@ -5110,7 +5134,8 @@ pass_list: technique9: KW_TECHNIQUE technique_name '{' pass_list '}' { - hlsl_fixme(ctx, &@$, "Unsupported 'technique' declaration."); + if (!add_technique(ctx, $2, "technique", &@1)) + YYABORT; }
technique10: @@ -5120,7 +5145,8 @@ 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."); + if (!add_technique(ctx, $2, "technique10", &@1)) + YYABORT; }
technique11: @@ -5130,7 +5156,8 @@ 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."); + if (!add_technique(ctx, $2, "technique11", &@1)) + YYABORT; }
global_technique: diff --git a/tests/hlsl/technique-fx_2.shader_test b/tests/hlsl/technique-fx_2.shader_test index f86cc005d..e0ac1901e 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 { } diff --git a/tests/hlsl/technique-fx_4.shader_test b/tests/hlsl/technique-fx_4.shader_test index 7968cb9de..02317483a 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 { } diff --git a/tests/hlsl/technique-fx_5.shader_test b/tests/hlsl/technique-fx_5.shader_test index 29aa616f9..fd1cf4cf9 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 { }