Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
-- v3: vkd3d-shader/tpf: Initial support for writing fx_4_0/fx_4_1 binaries.
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
Only technique10 and technique11 types could be nested in groups.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.y | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index c9e7335b..80feffa2 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -4998,7 +4998,7 @@ hlsl_prog: destroy_block($2); } | hlsl_prog preproc_directive - | hlsl_prog technique + | hlsl_prog global_technique | hlsl_prog ';'
technique_name: @@ -5037,7 +5037,7 @@ technique11: hlsl_fixme(ctx, &@$, "Unsupported 'technique11' declaration."); }
-technique: +global_technique: technique9 | technique10 | technique11
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 3 +++ libs/vkd3d-shader/hlsl.h | 3 +++ libs/vkd3d-shader/hlsl.y | 36 ++++++++++++++++++++++++--- 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, 46 insertions(+), 10 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index c8677f41..bf93ac13 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3388,6 +3388,9 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) {"float", HLSL_CLASS_SCALAR, HLSL_TYPE_FLOAT, 1, 1}, {"vector", HLSL_CLASS_VECTOR, HLSL_TYPE_FLOAT, 4, 1}, {"matrix", HLSL_CLASS_MATRIX, HLSL_TYPE_FLOAT, 4, 4}, + {"technique", HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE, 1, 1}, + {"technique10", HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE10, 1, 1}, + {"technique11", HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE11, 1, 1}, {"STRING", HLSL_CLASS_OBJECT, HLSL_TYPE_STRING, 1, 1}, {"TEXTURE", HLSL_CLASS_OBJECT, HLSL_TYPE_TEXTURE, 1, 1}, {"PIXELSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1}, diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 309d7080..8fd1429b 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -95,6 +95,9 @@ enum hlsl_base_type HLSL_TYPE_UAV, HLSL_TYPE_PIXELSHADER, HLSL_TYPE_VERTEXSHADER, + HLSL_TYPE_TECHNIQUE, + HLSL_TYPE_TECHNIQUE10, + HLSL_TYPE_TECHNIQUE11, HLSL_TYPE_STRING, HLSL_TYPE_VOID, }; diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 80feffa2..ff406cd6 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1096,6 +1096,33 @@ 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; + + if (!name) + name = hlsl_sprintf_alloc(ctx, "<technique-%u>", ctx->internal_name_counter++); + 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}; @@ -5014,7 +5041,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: @@ -5024,7 +5052,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: @@ -5034,7 +5063,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 f86cc005..e0ac1901 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 7968cb9d..02317483 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 29aa616f..fd1cf4cf 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 { }
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.c | 1 + libs/vkd3d-shader/hlsl.h | 3 ++ libs/vkd3d-shader/hlsl.y | 43 +++++++++++++++++++++++++++ tests/hlsl/technique-fx_2.shader_test | 4 +-- tests/hlsl/technique-fx_4.shader_test | 4 +-- tests/hlsl/technique-fx_5.shader_test | 4 +-- 6 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index bf93ac13..66cd26b8 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3391,6 +3391,7 @@ static void declare_predefined_types(struct hlsl_ctx *ctx) {"technique", HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE, 1, 1}, {"technique10", HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE10, 1, 1}, {"technique11", HLSL_CLASS_OBJECT, HLSL_TYPE_TECHNIQUE11, 1, 1}, + {"fxgroup", HLSL_CLASS_OBJECT, HLSL_TYPE_EFFECT_GROUP, 1, 1}, {"STRING", HLSL_CLASS_OBJECT, HLSL_TYPE_STRING, 1, 1}, {"TEXTURE", HLSL_CLASS_OBJECT, HLSL_TYPE_TEXTURE, 1, 1}, {"PIXELSHADER", HLSL_CLASS_OBJECT, HLSL_TYPE_PIXELSHADER, 1, 1}, diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 8fd1429b..b6611ddd 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -98,6 +98,7 @@ enum hlsl_base_type HLSL_TYPE_TECHNIQUE, HLSL_TYPE_TECHNIQUE10, HLSL_TYPE_TECHNIQUE11, + HLSL_TYPE_EFFECT_GROUP, HLSL_TYPE_STRING, HLSL_TYPE_VOID, }; @@ -402,6 +403,8 @@ struct hlsl_ir_var struct list scope_entry; /* Item entry in hlsl_ctx.extern_vars, if the variable is extern. */ struct list extern_entry; + /* Scope that variable itself defines, used to provide a container for techniques and passes. */ + struct hlsl_scope *scope;
/* Indexes of the IR instructions where the variable is first written and last read (liveness * range). The IR instructions are numerated starting from 2, because 0 means unused, and 1 diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index ff406cd6..a49d73d3 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -1123,6 +1123,31 @@ static bool add_technique(struct hlsl_ctx *ctx, const char *name, const char *ty return true; }
+static bool add_effect_group(struct hlsl_ctx *ctx, const char *name, struct hlsl_scope *scope, + const struct vkd3d_shader_location *loc) +{ + struct hlsl_ir_var *var; + struct hlsl_type *type; + + type = hlsl_get_type(ctx->globals, "fxgroup", false, false); + if (!(var = hlsl_new_var(ctx, name, type, loc, NULL, 0, NULL))) + return false; + var->scope = scope; + + 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}; @@ -5026,6 +5051,7 @@ hlsl_prog: } | hlsl_prog preproc_directive | hlsl_prog global_technique + | hlsl_prog effect_group | hlsl_prog ';'
technique_name: @@ -5072,6 +5098,23 @@ global_technique: | technique10 | technique11
+group_technique: + technique10 + | technique11 + +group_techniques: + group_technique + | group_techniques group_technique + +effect_group: + KW_FXGROUP any_identifier '{' scope_start group_techniques '}' + { + struct hlsl_scope *scope = ctx->cur_scope; + hlsl_pop_scope(ctx); + if (!(add_effect_group(ctx, $2, scope, &@2))) + YYABORT; + } + 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 e0ac1901..4a18430a 100644 --- a/tests/hlsl/technique-fx_2.shader_test +++ b/tests/hlsl/technique-fx_2.shader_test @@ -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 02317483..9bd1a8d7 100644 --- a/tests/hlsl/technique-fx_4.shader_test +++ b/tests/hlsl/technique-fx_4.shader_test @@ -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 fd1cf4cf..0ef88cd0 100644 --- a/tests/hlsl/technique-fx_5.shader_test +++ b/tests/hlsl/technique-fx_5.shader_test @@ -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 --- include/private/vkd3d_common.h | 1 + libs/vkd3d-shader/hlsl.c | 8 ++ libs/vkd3d-shader/hlsl.h | 2 + libs/vkd3d-shader/hlsl_codegen.c | 41 +++++++ libs/vkd3d-shader/tpf.c | 129 +++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 35 +++++- libs/vkd3d-shader/vkd3d_shader_private.h | 2 + tests/hlsl/technique-fx_2.shader_test | 2 +- tests/hlsl/technique-fx_4.shader_test | 10 +- 9 files changed, 221 insertions(+), 9 deletions(-)
diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h index 619665ad..b098c114 100644 --- a/include/private/vkd3d_common.h +++ b/include/private/vkd3d_common.h @@ -52,6 +52,7 @@ #define TAG_AON9 VKD3D_MAKE_TAG('A', 'o', 'n', '9') #define TAG_DXBC VKD3D_MAKE_TAG('D', 'X', 'B', 'C') #define TAG_DXIL VKD3D_MAKE_TAG('D', 'X', 'I', 'L') +#define TAG_FX10 VKD3D_MAKE_TAG('F', 'X', '1', '0') #define TAG_ISG1 VKD3D_MAKE_TAG('I', 'S', 'G', '1') #define TAG_ISGN VKD3D_MAKE_TAG('I', 'S', 'G', 'N') #define TAG_OSG1 VKD3D_MAKE_TAG('O', 'S', 'G', '1') diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 66cd26b8..dad61e57 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3673,6 +3673,14 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d return VKD3D_ERROR_NOT_IMPLEMENTED; }
+ if (ctx.profile->type == VKD3D_SHADER_TYPE_EFFECT) + { + ret = hlsl_emit_effect_binary(&ctx, out); + + hlsl_ctx_cleanup(&ctx); + return ret; + } + if ((func = hlsl_get_function(&ctx, entry_point))) { RB_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry) diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index b6611ddd..9a2026e7 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -1155,6 +1155,7 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl
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); +int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out);
bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain); bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other); @@ -1328,6 +1329,7 @@ bool hlsl_sm4_usage_from_semantic(struct hlsl_ctx *ctx, bool hlsl_sm4_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, bool output, enum vkd3d_shader_register_type *type, bool *has_idx); int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, struct vkd3d_shader_code *out); +int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out);
struct hlsl_ir_function_decl *hlsl_compile_internal_function(struct hlsl_ctx *ctx, const char *name, const char *hlsl);
diff --git a/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index 51c3d68f..ebd70ab4 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -4877,3 +4877,44 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry return VKD3D_ERROR_INVALID_ARGUMENT; } } + +int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) +{ + struct hlsl_ir_var *var; + + /* Reset generated names to simplify serialization. */ + LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) + { + enum hlsl_base_type type = var->data_type->base_type; + + if (type == HLSL_TYPE_TECHNIQUE + || type == HLSL_TYPE_TECHNIQUE10 + || type == HLSL_TYPE_TECHNIQUE11) + { + if (*var->name == '<') + { + vkd3d_free((void *)var->name); + var->name = NULL; + } + } + } + + if (ctx->profile->major_version == 2) + { + hlsl_fixme(ctx, &ctx->location, "Writing fx_2_0 binaries is not implemented."); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + else if (ctx->profile->major_version == 4) + { + return hlsl_fx_4_write(ctx, out); + } + else if (ctx->profile->major_version == 5) + { + hlsl_fixme(ctx, &ctx->location, "Writing fx_5_0 binaries is not implemented."); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } + else + { + vkd3d_unreachable(); + } +} diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index afdf8473..65572263 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -5751,3 +5751,132 @@ int hlsl_sm4_write(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_fun vkd3d_shader_free_shader_code(&dxbc.sections[i].data); return ret; } + +static uint32_t fx_get_string_size(const char *s) +{ + /* All empty strings share the same block. */ + return s ? strlen(s) + 1 : 0; +} + +struct fx_context +{ + uint32_t raw_section_size; + uint32_t raw_section_offset; + uint32_t raw_section_used; + uint32_t technique_count; +}; + +static uint32_t fx_put_raw_u32(struct vkd3d_bytecode_buffer *buffer, struct fx_context *ctx, uint32_t value) +{ + uint32_t offset = ctx->raw_section_offset + ctx->raw_section_used; + uint32_t ret = ctx->raw_section_used; + + set_u32(buffer, offset, value); + ctx->raw_section_used += sizeof(value); + return ret; +} + +static uint32_t fx_put_raw_string(struct vkd3d_bytecode_buffer *buffer, struct fx_context *ctx, const char *string) +{ + uint32_t ret = ctx->raw_section_used; + size_t size; + + /* Empty strings are using the same 4 bytes at the start of the section. */ + if (!string) + return 0; + + size = strlen(string) + 1; + set_string(buffer, ctx->raw_section_offset + ctx->raw_section_used, string, size); + ctx->raw_section_used += size; + return ret; +} + +typedef void (*fx_technique_func)(struct hlsl_ir_var *var, struct fx_context *ctx, struct vkd3d_bytecode_buffer *buffer); + +static void fx_foreach_technique(struct hlsl_scope *scope, fx_technique_func func, struct fx_context *ctx, + struct vkd3d_bytecode_buffer *buffer) +{ + struct hlsl_ir_var *var; + + LIST_FOR_EACH_ENTRY(var, &scope->vars, struct hlsl_ir_var, scope_entry) + { + if (var->data_type->base_type == HLSL_TYPE_TECHNIQUE10) + func(var, ctx, buffer); + } +} + +static void fx_technique_collect_stats(struct hlsl_ir_var *var, struct fx_context *ctx, struct vkd3d_bytecode_buffer *buffer) +{ + ctx->raw_section_size += fx_get_string_size(var->name); + ctx->technique_count++; +} + +static void fx_technique_write(struct hlsl_ir_var *var, struct fx_context *ctx, struct vkd3d_bytecode_buffer *buffer) +{ + uint32_t name_offset; + + name_offset = fx_put_raw_string(buffer, ctx, var->name); + put_u32(buffer, name_offset); + put_u32(buffer, 0); /* Pass count. */ + put_u32(buffer, 0); /* Annotation count. */ + + /* TODO: passes */ +} + +static void write_fx10(struct hlsl_ctx *ctx, struct dxbc_writer *dxbc) +{ + struct fx_context fx_ctx = { .raw_section_size = 4 }; + struct vkd3d_bytecode_buffer buffer = { 0 }; + + fx_foreach_technique(ctx->globals, fx_technique_collect_stats, &fx_ctx, &buffer); + fx_ctx.raw_section_size = align(fx_ctx.raw_section_size, 4); + + put_u32(&buffer, ctx->profile->minor_version == 0 ? 0xfeff1001 : 0xfeff1011); /* Version. */ + put_u32(&buffer, 0); /* Buffer count. */ + put_u32(&buffer, 0); /* Variable count. */ + put_u32(&buffer, 0); /* Object count. */ + put_u32(&buffer, 0); /* Pool buffer count. */ + put_u32(&buffer, 0); /* Pool variable count. */ + put_u32(&buffer, 0); /* Pool object count. */ + put_u32(&buffer, fx_ctx.technique_count); + put_u32(&buffer, fx_ctx.raw_section_size); + put_u32(&buffer, 0); /* String count. */ + put_u32(&buffer, 0); /* Texture object count. */ + put_u32(&buffer, 0); /* Depth stencil state count. */ + put_u32(&buffer, 0); /* Blend state count. */ + put_u32(&buffer, 0); /* Rasterizer state count. */ + put_u32(&buffer, 0); /* Sampler state count. */ + put_u32(&buffer, 0); /* Rendertarget view count. */ + put_u32(&buffer, 0); /* Depth stencil view count. */ + put_u32(&buffer, 0); /* Shader count. */ + put_u32(&buffer, 0); /* Inline shader count. */ + + fx_ctx.raw_section_offset = bytecode_reserve_bytes(&buffer, fx_ctx.raw_section_size); + fx_put_raw_u32(&buffer, &fx_ctx, 0); + + /* TODO: write buffers */ + /* TODO: write objects */ + /* TODO: shared buffers */ + /* TODO: shared objects */ + + fx_foreach_technique(ctx->globals, fx_technique_write, &fx_ctx, &buffer); + + add_section(ctx, dxbc, TAG_FX10, &buffer); +} + +int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) +{ + struct dxbc_writer dxbc; + size_t i; + int ret; + + dxbc_writer_init(&dxbc); + + write_fx10(ctx, &dxbc); + + if (!(ret = ctx->result)) + ret = dxbc_writer_write(&dxbc, out); + for (i = 0; i < dxbc.section_count; ++i) + vkd3d_shader_free_shader_code(&dxbc.sections[i].data); + return ret; +} diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 28d647b3..78f1815d 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -373,13 +373,42 @@ size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *byte return offset; }
-void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) +size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size) +{ + size_t offset = bytecode_align(buffer); + + if (buffer->status) + return offset; + + if (!vkd3d_array_reserve((void **)&buffer->data, &buffer->capacity, offset + size, 1)) + { + buffer->status = VKD3D_ERROR_OUT_OF_MEMORY; + return offset; + } + + memset(buffer->data + offset, 0xcd, size); + buffer->size = offset + size; + return offset; +} + +static void bytecode_set_bytes(struct vkd3d_bytecode_buffer *buffer, size_t offset, + const void *value, size_t size) { if (buffer->status) return;
- assert(vkd3d_bound_range(offset, sizeof(value), buffer->size)); - memcpy(buffer->data + offset, &value, sizeof(value)); + assert(vkd3d_bound_range(offset, size, buffer->size)); + memcpy(buffer->data + offset, value, size); +} + +void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value) +{ + bytecode_set_bytes(buffer, offset, &value, sizeof(value)); +} + +void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length) +{ + bytecode_set_bytes(buffer, offset, string, length); }
static void vkd3d_shader_dump_blob(const char *path, const char *profile, diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 912267e0..2d85bf6b 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1302,7 +1302,9 @@ struct vkd3d_bytecode_buffer /* Align to the next 4-byte offset, and return that offset. */ size_t bytecode_align(struct vkd3d_bytecode_buffer *buffer); size_t bytecode_put_bytes(struct vkd3d_bytecode_buffer *buffer, const void *bytes, size_t size); +size_t bytecode_reserve_bytes(struct vkd3d_bytecode_buffer *buffer, size_t size); void set_u32(struct vkd3d_bytecode_buffer *buffer, size_t offset, uint32_t value); +void set_string(struct vkd3d_bytecode_buffer *buffer, size_t offset, const char *string, size_t length);
static inline size_t put_u32(struct vkd3d_bytecode_buffer *buffer, uint32_t value) { diff --git a/tests/hlsl/technique-fx_2.shader_test b/tests/hlsl/technique-fx_2.shader_test index 4a18430a..10b6fdf0 100644 --- a/tests/hlsl/technique-fx_2.shader_test +++ b/tests/hlsl/technique-fx_2.shader_test @@ -86,7 +86,7 @@ technique10 }
% Effects without techniques are not allowed for fx_2_0 -[effect fail] +[effect fail todo] float4 f;
% fx_5_0 keyword fails with fx_2_0 profile diff --git a/tests/hlsl/technique-fx_4.shader_test b/tests/hlsl/technique-fx_4.shader_test index 9bd1a8d7..cdc5746e 100644 --- a/tests/hlsl/technique-fx_4.shader_test +++ b/tests/hlsl/technique-fx_4.shader_test @@ -37,7 +37,7 @@ float4 main() : sv_target return fxGroup; }
-[effect todo] +[effect] technique { } @@ -47,11 +47,11 @@ technique10 }
% Effects without techniques are allowed for fx_4_0+ -[effect todo] +[effect] float4 f;
% fx_2_0 keyword is allowed with fx_4_0+ profiles -[effect todo] +[effect] technique { } @@ -90,10 +90,10 @@ float4 technique10; [effect fail] float4 technique11;
-[effect todo] +[effect] float4 technIque10;
-[effect todo] +[effect] float4 technIque11;
% Regular shaders with technique blocks
On Mon Nov 6 16:08:31 2023 +0000, Nikolay Sivov wrote:
changed this line in [version 3 of the diff](/wine/vkd3d/-/merge_requests/443/diffs?diff_id=81555&start_sha=84b6e0175f782d29bc82a03175bf5b800cd49e9b#3cf804f245af47d51595ff932bf817c50967eea2_4919_4919)
Ok, thanks.
On Mon Nov 6 16:09:33 2023 +0000, Giovanni Mascellani wrote:
I guess the `+ 1` is for the string terminator. However, you're also adding it inside `set_string()`. Is that intended?
It's not intended, no. Fixed now.
Do we want effects targets to have a dedicated target type?
On Mon Nov 6 17:44:58 2023 +0000, Zebediah Figura wrote:
Do we want effects targets to have a dedicated target type?
What do you mean?
On Mon Nov 6 17:44:58 2023 +0000, Nikolay Sivov wrote:
What do you mean?
I mean, should they really use VKD3D_SHADER_TARGET_DXBC_TPF / VKD3D_SHADER_TARGET_D3D_BYTECODE, or do we want a new target type? This is an open API design question.
On Mon Nov 6 18:01:48 2023 +0000, Zebediah Figura wrote:
I mean, should they really use VKD3D_SHADER_TARGET_DXBC_TPF / VKD3D_SHADER_TARGET_D3D_BYTECODE, or do we want a new target type? This is an open API design question.
I think we can use VKD3D_SHADER_TARGET_NONE, and VKD3D_SHADER_TARGET_D3D_ASM if we'll ever want to disassembly them.
I don't know why such flexibility was introduced, maybe to compile hlsl to spriv binary in a single step? By default it makes sense to me to use corresponding formats for all profiles and indicate that with TARGET_NONE for example.