Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
-- v4: vkd3d-shader/tpf: Initial support for writing fx_4_0/fx_4_1 binaries. vkd3d-shader/hlsl: Handle effect group statement. vkd3d-shader/hlsl: Add variables for techniques. vkd3d-shader/hlsl: Rename rule for top-level techniques. vkd3d-shader/hlsl: Add 'fxgroup' token. tests: Add some tests for effects groups syntax. vkd3d-shader: Add separate binary target types for effects.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- include/vkd3d_shader.h | 12 ++++ libs/vkd3d-shader/hlsl.c | 19 ++++++ libs/vkd3d-shader/vkd3d_shader_main.c | 3 + libs/vkd3d-utils/vkd3d_utils_main.c | 84 +++++++++++++++++---------- programs/vkd3d-compiler/main.c | 9 +++ 5 files changed, 97 insertions(+), 30 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index 94f79c7c7..7e4c46b50 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -734,6 +734,18 @@ enum vkd3d_shader_target_type * An 'OpenGL Shading Language' shader. \since 1.3 */ VKD3D_SHADER_TARGET_GLSL, + /** + * Binary format used by Direct3D 9 effects. \since 1.10 + */ + VKD3D_SHADER_TARGET_D3D_FX, + /** + * Binary format used by Direct3D 10.x effects. \since 1.10 + */ + VKD3D_SHADER_TARGET_DXBC_FX, + /** + * Binary format used by Direct3D 11.x effects. \since 1.10 + */ + VKD3D_SHADER_TARGET_FX,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_TARGET_TYPE), }; diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 1d3fd0f7d..14088a188 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3645,6 +3645,25 @@ int hlsl_compile_shader(const struct vkd3d_shader_code *hlsl, const struct vkd3d "The '%s' target profile is incompatible with the 'dxbc-tpf' target type.", profile->name); return VKD3D_ERROR_INVALID_ARGUMENT; } + else if (compile_info->target_type == VKD3D_SHADER_TARGET_D3D_FX && strcmp(profile->name, "fx_2_0")) + { + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "The '%s' target profile is incompatible with the 'd3d-fx' target type.", profile->name); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + else if (compile_info->target_type == VKD3D_SHADER_TARGET_DXBC_FX && !(profile->major_version == 4 + && profile->type == VKD3D_SHADER_TYPE_EFFECT)) + { + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "The '%s' target profile is incompatible with the 'dxbc-fx' target type.", profile->name); + return VKD3D_ERROR_INVALID_ARGUMENT; + } + else if (compile_info->target_type == VKD3D_SHADER_TARGET_FX && strcmp(profile->name, "fx_5_0")) + { + vkd3d_shader_error(message_context, NULL, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "The '%s' target profile is incompatible with the 'fx' target type.", profile->name); + return VKD3D_ERROR_INVALID_ARGUMENT; + }
if (!hlsl_ctx_init(&ctx, compile_info, profile, message_context)) return VKD3D_ERROR_OUT_OF_MEMORY; diff --git a/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d-shader/vkd3d_shader_main.c index 28d647b3d..780733b31 100644 --- a/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1724,6 +1724,9 @@ const enum vkd3d_shader_target_type *vkd3d_shader_get_supported_target_types( { VKD3D_SHADER_TARGET_D3D_BYTECODE, VKD3D_SHADER_TARGET_DXBC_TPF, + VKD3D_SHADER_TARGET_D3D_FX, + VKD3D_SHADER_TARGET_DXBC_FX, + VKD3D_SHADER_TARGET_FX, };
static const enum vkd3d_shader_target_type d3dbc_types[] = diff --git a/libs/vkd3d-utils/vkd3d_utils_main.c b/libs/vkd3d-utils/vkd3d_utils_main.c index 306674cd1..27ac0c663 100644 --- a/libs/vkd3d-utils/vkd3d_utils_main.c +++ b/libs/vkd3d-utils/vkd3d_utils_main.c @@ -179,28 +179,12 @@ static void close_include(const struct vkd3d_shader_code *code, void *context) ID3DInclude_Close(iface, code->code); }
-HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filename, - const D3D_SHADER_MACRO *macros, ID3DInclude *include, const char *entry_point, - const char *profile, UINT flags, UINT effect_flags, UINT secondary_flags, - const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader_blob, - ID3DBlob **messages_blob) +static enum vkd3d_shader_target_type get_target_for_profile(const char *profile) { - struct vkd3d_shader_preprocess_info preprocess_info; - struct vkd3d_shader_hlsl_source_info hlsl_info; - struct vkd3d_shader_compile_option options[4]; - struct vkd3d_shader_compile_info compile_info; - struct vkd3d_shader_compile_option *option; - struct vkd3d_shader_code byte_code; - const D3D_SHADER_MACRO *macro; size_t profile_len, i; - char *messages; - HRESULT hr; - int ret;
static const char * const d3dbc_profiles[] = { - "fx_2_", - "ps.1.", "ps.2.", "ps.3.", @@ -220,6 +204,58 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen "tx_1_", };
+ static const struct fx_profile + { + const char *name; + enum vkd3d_shader_target_type target; + } + fx_profiles[] = + { + { "fx_2_0", VKD3D_SHADER_TARGET_D3D_FX }, + { "fx_4_0", VKD3D_SHADER_TARGET_DXBC_FX }, + { "fx_4_1", VKD3D_SHADER_TARGET_DXBC_FX }, + { "fx_5_0", VKD3D_SHADER_TARGET_FX }, + }; + + profile_len = strlen(profile); + for (i = 0; i < ARRAY_SIZE(d3dbc_profiles); ++i) + { + size_t len = strlen(d3dbc_profiles[i]); + + if (len <= profile_len && !memcmp(profile, d3dbc_profiles[i], len)) + { + return VKD3D_SHADER_TARGET_D3D_BYTECODE; + } + } + + for (i = 0; i < ARRAY_SIZE(fx_profiles); ++i) + { + if (!strcmp(profile, fx_profiles[i].name)) + { + return fx_profiles[i].target; + } + } + + return VKD3D_SHADER_TARGET_DXBC_TPF; +} + +HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filename, + const D3D_SHADER_MACRO *macros, ID3DInclude *include, const char *entry_point, + const char *profile, UINT flags, UINT effect_flags, UINT secondary_flags, + const void *secondary_data, SIZE_T secondary_data_size, ID3DBlob **shader_blob, + ID3DBlob **messages_blob) +{ + struct vkd3d_shader_preprocess_info preprocess_info; + struct vkd3d_shader_hlsl_source_info hlsl_info; + struct vkd3d_shader_compile_option options[4]; + struct vkd3d_shader_compile_info compile_info; + struct vkd3d_shader_compile_option *option; + struct vkd3d_shader_code byte_code; + const D3D_SHADER_MACRO *macro; + char *messages; + HRESULT hr; + int ret; + TRACE("data %p, data_size %lu, filename %s, macros %p, include %p, entry_point %s, " "profile %s, flags %#x, effect_flags %#x, secondary_flags %#x, secondary_data %p, " "secondary_data_size %lu, shader_blob %p, messages_blob %p.\n", @@ -246,24 +282,12 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen compile_info.source.code = data; compile_info.source.size = data_size; compile_info.source_type = VKD3D_SHADER_SOURCE_HLSL; - compile_info.target_type = VKD3D_SHADER_TARGET_DXBC_TPF; + compile_info.target_type = get_target_for_profile(profile); compile_info.options = options; compile_info.option_count = 1; compile_info.log_level = VKD3D_SHADER_LOG_INFO; compile_info.source_name = filename;
- profile_len = strlen(profile); - for (i = 0; i < ARRAY_SIZE(d3dbc_profiles); ++i) - { - size_t len = strlen(d3dbc_profiles[i]); - - if (len <= profile_len && !memcmp(profile, d3dbc_profiles[i], len)) - { - compile_info.target_type = VKD3D_SHADER_TARGET_D3D_BYTECODE; - break; - } - } - preprocess_info.type = VKD3D_SHADER_STRUCTURE_TYPE_PREPROCESS_INFO; preprocess_info.next = &hlsl_info; preprocess_info.macros = (const struct vkd3d_shader_macro *)macros; diff --git a/programs/vkd3d-compiler/main.c b/programs/vkd3d-compiler/main.c index 2e5f2b977..4d66467b2 100644 --- a/programs/vkd3d-compiler/main.c +++ b/programs/vkd3d-compiler/main.c @@ -105,6 +105,15 @@ target_type_info[] = "dxbc-tpf", "A 'Tokenized Program Format' shader embedded in a DXBC container.\n" " This is the format used for Direct3D shader model 4 and 5 shaders.\n", true}, + {VKD3D_SHADER_TARGET_D3D_FX, + "d3d-fx", "Binary format used by Direct3D 9 effects.\n", + true}, + {VKD3D_SHADER_TARGET_DXBC_FX, + "dxbc-fx", "Binary format used by Direct3D 10.x effects. DXBC is used as a container.\n", + true}, + {VKD3D_SHADER_TARGET_FX, + "fx", "Binary format used by Direct3D 11 effects.\n", + true}, {VKD3D_SHADER_TARGET_GLSL, "glsl", "An 'OpenGL Shading Language' shader.\n", false}
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 90c734d53..42e523f22 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 fb8a3e675..2fc481de5 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 aeea1a84f..152227c62 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
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 553387b1e..9ce27c3ff 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -4993,7 +4993,7 @@ hlsl_prog: destroy_block($2); } | hlsl_prog preproc_directive - | hlsl_prog technique + | hlsl_prog global_technique | hlsl_prog ';'
technique_name: @@ -5032,7 +5032,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.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 0e5f2bb61..c4c0dd249 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 0e72a539e..553387b1e 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 42e523f22..f86cc005d 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 2fc481de5..7968cb9de 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 152227c62..29aa616f9 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 | 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 14088a188..acdae5e54 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 309d7080f..8fd1429b8 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 9ce27c3ff..b52e571fb 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}; @@ -5009,7 +5036,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: @@ -5019,7 +5047,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: @@ -5029,7 +5058,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 { }
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 acdae5e54..2e451d94e 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 8fd1429b8..b6611dddc 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 b52e571fb..adcd91b22 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}; @@ -5021,6 +5046,7 @@ hlsl_prog: } | hlsl_prog preproc_directive | hlsl_prog global_technique + | hlsl_prog effect_group | hlsl_prog ';'
technique_name: @@ -5067,6 +5093,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 e0ac1901e..4a18430ad 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 02317483a..9bd1a8d74 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 fd1cf4cf9..0ef88cd0e 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 619665ad3..b098c1144 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 2e451d94e..36b58eb98 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3692,6 +3692,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 b6611dddc..9a2026e70 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 6eac5d490..5842b01af 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d-shader/hlsl_codegen.c @@ -4875,3 +4875,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 fbc04f61f..ebdeda798 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d-shader/tpf.c @@ -5754,3 +5754,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 780733b31..f946d7c93 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 ab7300115..89191972f 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -1307,7 +1307,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 4a18430ad..10b6fdf09 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 9bd1a8d74..cdc5746e0 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 18:36:24 2023 +0000, Nikolay Sivov wrote:
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.
I pushed something to use separate target types for those. Please take a look.
On Tue Nov 7 12:55:34 2023 +0000, Nikolay Sivov wrote:
I pushed something to use separate target types for those. Please take a look.
I don't know much about the other effect versions, but superficially `write_fx10()` and `write_sm4_shdr()` look different enough to justify a different type.
For the other types, I'd wait to expose them in the public header until we're able to emit at least something.