-- v3: vkd3d-shader/fx: Add support for writing shared object descriptions for fx_4_x. vkd3d-shader: Add an option to enable child effects compilation. vkd3d-shader/fx: Add initial support for writing uninitialized vertex/pixel shader objects.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/fx.c | 94 ++++++++++++++----- libs/vkd3d-shader/hlsl.y | 8 ++ .../effect-shader-objects-fx_2.shader_test | 2 +- .../effect-shader-objects-fx_5.shader_test | 2 +- 4 files changed, 80 insertions(+), 26 deletions(-)
diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index fd5c84432..14326c978 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -84,6 +84,7 @@ struct fx_write_context uint32_t buffer_count; uint32_t numeric_variable_count; uint32_t object_variable_count; + uint32_t shader_variable_count; int status;
const struct fx_write_context_ops *ops; @@ -320,19 +321,12 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, return value; }
-static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx) +static const char * get_fx_4_type_name(const struct hlsl_type *type) { - struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; - uint32_t name_offset, offset, size, stride, numeric_desc; - uint32_t elements_count = 0; - const char *name; - static const uint32_t variable_type[] = + static const char * const object_type_names[] = { - [HLSL_CLASS_SCALAR] = 1, - [HLSL_CLASS_VECTOR] = 1, - [HLSL_CLASS_MATRIX] = 1, - [HLSL_CLASS_OBJECT] = 2, - [HLSL_CLASS_STRUCT] = 3, + [HLSL_TYPE_RENDERTARGETVIEW] = "RenderTargetView", + [HLSL_TYPE_DEPTHSTENCILVIEW] = "DepthStencilView", }; static const char * const texture_type_names[] = { @@ -357,6 +351,39 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co [HLSL_SAMPLER_DIM_BUFFER] = "RWBuffer", [HLSL_SAMPLER_DIM_STRUCTURED_BUFFER] = "RWStructuredBuffer", }; + + if (type->base_type == HLSL_TYPE_TEXTURE) + return texture_type_names[type->sampler_dim]; + + if (type->base_type == HLSL_TYPE_UAV) + return uav_type_names[type->sampler_dim]; + + switch (type->base_type) + { + case HLSL_TYPE_PIXELSHADER: + case HLSL_TYPE_VERTEXSHADER: + case HLSL_TYPE_RENDERTARGETVIEW: + case HLSL_TYPE_DEPTHSTENCILVIEW: + return object_type_names[type->base_type]; + default: + return type->name; + } +} + +static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; + uint32_t name_offset, offset, size, stride, numeric_desc; + uint32_t elements_count = 0; + const char *name; + static const uint32_t variable_type[] = + { + [HLSL_CLASS_SCALAR] = 1, + [HLSL_CLASS_VECTOR] = 1, + [HLSL_CLASS_MATRIX] = 1, + [HLSL_CLASS_OBJECT] = 2, + [HLSL_CLASS_STRUCT] = 3, + }; struct hlsl_ctx *ctx = fx->ctx;
/* Resolve arrays to element type and number of elements. */ @@ -366,12 +393,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co type = hlsl_get_multiarray_element_type(type); }
- if (type->base_type == HLSL_TYPE_TEXTURE) - name = texture_type_names[type->sampler_dim]; - else if (type->base_type == HLSL_TYPE_UAV) - name = uav_type_names[type->sampler_dim]; - else - name = type->name; + name = get_fx_4_type_name(type);
name_offset = write_string(name, fx); offset = put_u32_unaligned(buffer, name_offset); @@ -424,6 +446,8 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co { static const uint32_t object_type[] = { + [HLSL_TYPE_PIXELSHADER] = 5, + [HLSL_TYPE_VERTEXSHADER] = 6, [HLSL_TYPE_RENDERTARGETVIEW] = 19, [HLSL_TYPE_DEPTHSTENCILVIEW] = 20, }; @@ -454,7 +478,9 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co switch (type->base_type) { case HLSL_TYPE_DEPTHSTENCILVIEW: + case HLSL_TYPE_PIXELSHADER: case HLSL_TYPE_RENDERTARGETVIEW: + case HLSL_TYPE_VERTEXSHADER: put_u32_unaligned(buffer, object_type[type->base_type]); break; case HLSL_TYPE_TEXTURE: @@ -695,9 +721,12 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write
static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) { + const struct hlsl_type *type = hlsl_get_multiarray_element_type(var->data_type); + uint32_t elements_count = hlsl_get_multiarray_size(var->data_type); struct vkd3d_bytecode_buffer *buffer = &fx->structured; uint32_t semantic_offset, bind_point = ~0u; - uint32_t name_offset, type_offset; + uint32_t name_offset, type_offset, i; + struct hlsl_ctx *ctx = fx->ctx;
if (var->reg_reservation.reg_type) bind_point = var->reg_reservation.reg_index; @@ -712,8 +741,29 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */ put_u32(buffer, bind_point); /* Explicit bind point */
+ /* Initializer */ + switch (type->base_type) + { + case HLSL_TYPE_TEXTURE: + case HLSL_TYPE_UAV: + case HLSL_TYPE_RENDERTARGETVIEW: + break; + case HLSL_TYPE_PIXELSHADER: + case HLSL_TYPE_VERTEXSHADER: + /* FIXME: write shader blobs, once parser support works. */ + for (i = 0; i < elements_count; ++i) + put_u32(buffer, 0); + ++fx->shader_variable_count; + break; + default: + hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.\n", + type->base_type); + } + put_u32(buffer, 0); /* Annotations count */ /* FIXME: write annotations */ + + ++fx->object_variable_count; }
static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx) @@ -809,7 +859,6 @@ static bool is_object_variable(const struct hlsl_ir_var *var) static void write_objects(struct fx_write_context *fx) { struct hlsl_ir_var *var; - uint32_t count = 0;
LIST_FOR_EACH_ENTRY(var, &fx->ctx->extern_vars, struct hlsl_ir_var, extern_entry) { @@ -817,10 +866,7 @@ static void write_objects(struct fx_write_context *fx) continue;
write_fx_4_object_variable(var, fx); - ++count; } - - fx->object_variable_count += count; }
static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) @@ -857,7 +903,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) 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, fx.shader_variable_count); /* Shader count. */ put_u32(&buffer, 0); /* Inline shader count. */
set_u32(&buffer, size_offset, fx.unstructured.size); @@ -915,7 +961,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) 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, fx.shader_variable_count); /* Shader count. */ put_u32(&buffer, 0); /* Inline shader count. */ put_u32(&buffer, fx.group_count); /* Group count. */ put_u32(&buffer, 0); /* UAV count. */ diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 8cdc82263..4883d6485 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -6453,6 +6453,14 @@ type_no_void: { $$ = hlsl_get_type(ctx->cur_scope, "DepthStencilView", true, true); } + | KW_VERTEXSHADER + { + $$ = hlsl_get_type(ctx->cur_scope, "VertexShader", true, true); + } + | KW_PIXELSHADER + { + $$ = hlsl_get_type(ctx->cur_scope, "PixelShader", true, true); + }
type: type_no_void diff --git a/tests/hlsl/effect-shader-objects-fx_2.shader_test b/tests/hlsl/effect-shader-objects-fx_2.shader_test index 8801ed1f7..7c6a8947a 100644 --- a/tests/hlsl/effect-shader-objects-fx_2.shader_test +++ b/tests/hlsl/effect-shader-objects-fx_2.shader_test @@ -26,7 +26,7 @@ float4 main() : sv_target return 0; }
-[effect todo] +[effect] vertexshader vs1; verteXshadeR vs2; pixelshader ps1; diff --git a/tests/hlsl/effect-shader-objects-fx_5.shader_test b/tests/hlsl/effect-shader-objects-fx_5.shader_test index 1d2f43386..34d681c1f 100644 --- a/tests/hlsl/effect-shader-objects-fx_5.shader_test +++ b/tests/hlsl/effect-shader-objects-fx_5.shader_test @@ -27,7 +27,7 @@ float4 main() : sv_target return 0; }
-[effect todo] +[effect] vertexshader vs1; verteXshadeR vs2; pixelshader ps1;
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- include/vkd3d_shader.h | 9 +++++++++ libs/vkd3d-shader/hlsl.c | 4 ++++ libs/vkd3d-shader/hlsl.h | 1 + libs/vkd3d-utils/vkd3d_utils_main.c | 11 +++++++++-- programs/vkd3d-compiler/main.c | 6 ++++++ 5 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h index ea0eb887e..b544c1927 100644 --- a/include/vkd3d_shader.h +++ b/include/vkd3d_shader.h @@ -285,6 +285,15 @@ enum vkd3d_shader_compile_option_name * \since 1.11 */ VKD3D_SHADER_COMPILE_OPTION_FEATURE = 0x0000000a, + /** + * If \a value is non-zero compilation will produce a child effect using + * shared object descriptions, as instructed by the "shared" modifier. + * Child effects are supported with fx_2_0, fx_4_0, and fx_4_1. This option + * and "shared" modifiers are ignored for fx_5_0 profile, and non-fx profiles. + * + * \since 1.12 + */ + VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT = 0x0000000b,
VKD3D_FORCE_32_BIT_ENUM(VKD3D_SHADER_COMPILE_OPTION_NAME), }; diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c index 45d02ce2b..f1e3e1973 100644 --- a/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d-shader/hlsl.c @@ -3596,6 +3596,10 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil { ctx->semantic_compat_mapping = option->value & VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES; } + else if (option->name == VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT) + { + ctx->child_effect = !!option->value; + } }
return true; diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index aad9b3c7b..9c55d9dfb 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -921,6 +921,7 @@ struct hlsl_ctx uint32_t found_numthreads : 1;
bool semantic_compat_mapping; + bool child_effect; };
struct hlsl_resource_load_params diff --git a/libs/vkd3d-utils/vkd3d_utils_main.c b/libs/vkd3d-utils/vkd3d_utils_main.c index c90aad45a..9a1b54065 100644 --- a/libs/vkd3d-utils/vkd3d_utils_main.c +++ b/libs/vkd3d-utils/vkd3d_utils_main.c @@ -244,7 +244,7 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen { 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_option options[5]; struct vkd3d_shader_compile_info compile_info; struct vkd3d_shader_compile_option *option; struct vkd3d_shader_code byte_code; @@ -262,7 +262,7 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen
if (flags & ~(D3DCOMPILE_DEBUG | D3DCOMPILE_PACK_MATRIX_ROW_MAJOR | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR)) FIXME("Ignoring flags %#x.\n", flags); - if (effect_flags) + if (effect_flags & ~D3DCOMPILE_EFFECT_CHILD_EFFECT) FIXME("Ignoring effect flags %#x.\n", effect_flags); if (secondary_flags) FIXME("Ignoring secondary flags %#x.\n", secondary_flags); @@ -330,6 +330,13 @@ HRESULT WINAPI D3DCompile2(const void *data, SIZE_T data_size, const char *filen option->value = VKD3D_SHADER_COMPILE_OPTION_BACKCOMPAT_MAP_SEMANTIC_NAMES; }
+ if (effect_flags & D3DCOMPILE_EFFECT_CHILD_EFFECT) + { + option = &options[compile_info.option_count++]; + option->name = VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT; + option->value = true; + } + ret = vkd3d_shader_compile(&compile_info, &byte_code, &messages);
if (messages && messages_blob) diff --git a/programs/vkd3d-compiler/main.c b/programs/vkd3d-compiler/main.c index 2289bfba9..bd5df9009 100644 --- a/programs/vkd3d-compiler/main.c +++ b/programs/vkd3d-compiler/main.c @@ -39,6 +39,7 @@ enum { OPTION_HELP = CHAR_MAX + 1, OPTION_BUFFER_UAV, + OPTION_CHILD_EFFECT, OPTION_ENTRY, OPTION_FRAGMENT_COORDINATE_ORIGIN, OPTION_MATRIX_STORAGE_ORDER, @@ -479,6 +480,7 @@ static bool parse_command_line(int argc, char **argv, struct options *options) { {"help", no_argument, NULL, OPTION_HELP}, {"buffer-uav", required_argument, NULL, OPTION_BUFFER_UAV}, + {"child-effect", no_argument, NULL, OPTION_CHILD_EFFECT}, {"entry", required_argument, NULL, OPTION_ENTRY}, {"fragment-coordinate-origin", required_argument, NULL, OPTION_FRAGMENT_COORDINATE_ORIGIN}, {"matrix-storage-order", required_argument, NULL, OPTION_MATRIX_STORAGE_ORDER}, @@ -523,6 +525,10 @@ static bool parse_command_line(int argc, char **argv, struct options *options) add_compile_option(options, VKD3D_SHADER_COMPILE_OPTION_BUFFER_UAV, buffer_uav); break;
+ case OPTION_CHILD_EFFECT: + add_compile_option(options, VKD3D_SHADER_COMPILE_OPTION_CHILD_EFFECT, 1); + break; + case OPTION_ENTRY: case 'e': options->entry_point = optarg;
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/fx.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index 14326c978..c1e5bebbb 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -64,6 +64,7 @@ struct fx_write_context_ops uint32_t (*write_type)(const struct hlsl_type *type, struct fx_write_context *fx); void (*write_technique)(struct hlsl_ir_var *var, struct fx_write_context *fx); void (*write_pass)(struct hlsl_ir_var *var, struct fx_write_context *fx); + bool are_child_effects_supported; };
struct fx_write_context @@ -84,9 +85,12 @@ struct fx_write_context uint32_t buffer_count; uint32_t numeric_variable_count; uint32_t object_variable_count; + uint32_t shared_object_count; uint32_t shader_variable_count; int status;
+ bool child_effect; + const struct fx_write_context_ops *ops; };
@@ -175,6 +179,8 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co
rb_init(&fx->strings, string_storage_compare); list_init(&fx->types); + + fx->child_effect = fx->ops->are_child_effects_supported && ctx->child_effect; }
static int fx_write_context_cleanup(struct fx_write_context *fx) @@ -687,6 +693,7 @@ static const struct fx_write_context_ops fx_4_ops = .write_type = write_fx_4_type, .write_technique = write_fx_4_technique, .write_pass = write_fx_4_pass, + .are_child_effects_supported = true, };
static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) @@ -741,6 +748,12 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ semantic_offset = put_u32(buffer, semantic_offset); /* Semantic */ put_u32(buffer, bind_point); /* Explicit bind point */
+ if (fx->child_effect && var->storage_modifiers & HLSL_STORAGE_SHARED) + { + ++fx->shared_object_count; + return; + } + /* Initializer */ switch (type->base_type) { @@ -856,15 +869,21 @@ static bool is_object_variable(const struct hlsl_ir_var *var) } }
-static void write_objects(struct fx_write_context *fx) +static void write_objects(struct fx_write_context *fx, bool shared) { struct hlsl_ir_var *var;
+ if (shared && !fx->child_effect) + return; + LIST_FOR_EACH_ENTRY(var, &fx->ctx->extern_vars, struct hlsl_ir_var, extern_entry) { if (!is_object_variable(var)) continue;
+ if (fx->child_effect && (shared != !!(var->storage_modifiers & HLSL_STORAGE_SHARED))) + continue; + write_fx_4_object_variable(var, fx); } } @@ -880,9 +899,9 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
write_buffers(&fx); - write_objects(&fx); + write_objects(&fx, false); /* TODO: shared buffers */ - /* TODO: shared objects */ + write_objects(&fx, true);
write_techniques(ctx->globals, &fx);
@@ -892,7 +911,7 @@ static int hlsl_fx_4_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&buffer, fx.object_variable_count); /* Object variable 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.shared_object_count); /* Shared object count. */ put_u32(&buffer, fx.technique_count); size_offset = put_u32(&buffer, 0); /* Unstructured size. */ put_u32(&buffer, 0); /* String count. */ @@ -939,7 +958,7 @@ static int hlsl_fx_5_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&fx.unstructured, 0); /* Empty string placeholder. */
write_buffers(&fx); - write_objects(&fx); + write_objects(&fx, false); /* TODO: interface variables */
write_groups(&fx);
On Thu Mar 7 18:41:50 2024 +0000, Nikolay Sivov wrote:
Would it be less dead if I had a test that runs through this path?
I fixed type name issue, and existing todos are passing now. I think it's useful to have uninitialized objects first, if only to make changes more incremental.
On Thu Mar 7 18:47:14 2024 +0000, Nikolay Sivov wrote:
Alright.
This is now adjusted to have a new top level option.
On Fri Mar 8 00:02:20 2024 +0000, Nikolay Sivov wrote:
I fixed type name issue, and existing todos are passing now. I think it's useful to have uninitialized objects first, if only to make changes more incremental.
I'm sorry, I'm being sloppy again. This is fine.
This merge request was approved by Zebediah Figura.
Could we get a couple of lines of --help text for --child-effect?