Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
-- v4: vkd3d-shader/fx: Fail effect writing on unsupported annotations. vkd3d-shader/fx: Remove newlines from fixme messages. vkd3d-shader/fx: Add initial support for writing fx_2_0 parameters. vkd3d-shader/fx: Populate global variables list during context initialization. vkd3d-shader/fx: Fix an instruction block leak. vkd3d-shader/fx: Use type writing helper only for fx_4+.
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/fx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index fdf132e9e..426826e3d 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -61,7 +61,6 @@ struct fx_write_context; struct fx_write_context_ops { uint32_t (*write_string)(const char *string, struct fx_write_context *fx); - 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; @@ -112,12 +111,16 @@ static void write_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) fx->ops->write_pass(var, fx); }
+static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_context *fx); + static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context *fx) { struct type_entry *type_entry; unsigned int elements_count; const char *name;
+ assert(fx->ctx->profile->major_version >= 4); + if (type->class == HLSL_CLASS_ARRAY) { name = hlsl_get_multiarray_element_type(type)->name; @@ -143,7 +146,7 @@ static uint32_t write_type(const struct hlsl_type *type, struct fx_write_context if (!(type_entry = hlsl_alloc(fx->ctx, sizeof(*type_entry)))) return 0;
- type_entry->offset = fx->ops->write_type(type, fx); + type_entry->offset = write_fx_4_type(type, fx); type_entry->name = name; type_entry->elements_count = elements_count;
@@ -692,7 +695,6 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) static const struct fx_write_context_ops fx_4_ops = { .write_string = write_fx_4_string, - .write_type = write_fx_4_type, .write_technique = write_fx_4_technique, .write_pass = write_fx_4_pass, .are_child_effects_supported = true,
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/fx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index 426826e3d..f68d38fa0 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -840,7 +840,7 @@ static void write_buffers(struct fx_write_context *fx)
hlsl_block_init(&block); hlsl_prepend_global_uniform_copy(fx->ctx, &block); - hlsl_block_init(&block); + hlsl_block_cleanup(&block); hlsl_calculate_buffer_offsets(fx->ctx);
LIST_FOR_EACH_ENTRY(buffer, &fx->ctx->buffers, struct hlsl_buffer, entry)
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/fx.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index f68d38fa0..aaa9f0155 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -159,6 +159,7 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co struct fx_write_context *fx) { unsigned int version = ctx->profile->major_version; + struct hlsl_block block;
memset(fx, 0, sizeof(*fx));
@@ -184,6 +185,11 @@ static void fx_write_context_init(struct hlsl_ctx *ctx, const struct fx_write_co list_init(&fx->types);
fx->child_effect = fx->ops->are_child_effects_supported && ctx->child_effect; + + hlsl_block_init(&block); + hlsl_prepend_global_uniform_copy(fx->ctx, &block); + hlsl_block_cleanup(&block); + hlsl_calculate_buffer_offsets(fx->ctx); }
static int fx_write_context_cleanup(struct fx_write_context *fx) @@ -836,12 +842,6 @@ static void write_fx_4_buffer(struct hlsl_buffer *b, struct fx_write_context *fx static void write_buffers(struct fx_write_context *fx) { struct hlsl_buffer *buffer; - struct hlsl_block block; - - hlsl_block_init(&block); - hlsl_prepend_global_uniform_copy(fx->ctx, &block); - hlsl_block_cleanup(&block); - hlsl_calculate_buffer_offsets(fx->ctx);
LIST_FOR_EACH_ENTRY(buffer, &fx->ctx->buffers, struct hlsl_buffer, entry) {
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/d3dbc.c | 8 +- libs/vkd3d-shader/fx.c | 155 +++++++++++++++++- libs/vkd3d-shader/hlsl.h | 2 + .../effect-shader-objects-fx_2.shader_test | 2 +- 4 files changed, 159 insertions(+), 8 deletions(-)
diff --git a/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d-shader/d3dbc.c index 9f153a1da..3b935b07d 100644 --- a/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d-shader/d3dbc.c @@ -1494,12 +1494,12 @@ static uint32_t sm1_version(enum vkd3d_shader_type type, unsigned int major, uns return D3DPS_VERSION(major, minor); }
-static D3DXPARAMETER_CLASS sm1_class(const struct hlsl_type *type) +D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type) { switch (type->class) { case HLSL_CLASS_ARRAY: - return sm1_class(type->e.array.type); + return hlsl_sm1_class(type->e.array.type); case HLSL_CLASS_MATRIX: assert(type->modifiers & HLSL_MODIFIERS_MAJORITY_MASK); if (type->modifiers & HLSL_MODIFIER_COLUMN_MAJOR) @@ -1520,7 +1520,7 @@ static D3DXPARAMETER_CLASS sm1_class(const struct hlsl_type *type) } }
-static D3DXPARAMETER_TYPE sm1_base_type(const struct hlsl_type *type) +D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type) { switch (type->base_type) { @@ -1615,7 +1615,7 @@ static void write_sm1_type(struct vkd3d_bytecode_buffer *buffer, struct hlsl_typ } }
- type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(sm1_class(type), sm1_base_type(array_type))); + type->bytecode_offset = put_u32(buffer, vkd3d_make_u32(hlsl_sm1_class(type), hlsl_sm1_base_type(array_type))); put_u32(buffer, vkd3d_make_u32(type->dimy, type->dimx)); put_u32(buffer, vkd3d_make_u32(array_size, field_count)); put_u32(buffer, fields_offset); diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index aaa9f0155..718ba8aaa 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -86,6 +86,7 @@ struct fx_write_context uint32_t object_variable_count; uint32_t shared_object_count; uint32_t shader_variable_count; + uint32_t parameter_count; int status;
bool child_effect; @@ -613,6 +614,73 @@ static uint32_t write_fx_2_string(const char *string, struct fx_write_context *f return offset; }
+static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, + struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; + uint32_t semantic_offset, offset, elements_count = 0, name_offset; + struct hlsl_ctx *ctx = fx->ctx; + size_t i; + + /* Resolve arrays to element type and number of elements. */ + if (type->class == HLSL_CLASS_ARRAY) + { + elements_count = hlsl_get_multiarray_size(type); + type = hlsl_get_multiarray_element_type(type); + } + + name_offset = write_string(name, fx); + semantic_offset = write_string(semantic->name, fx); + + switch (type->base_type) + { + case HLSL_TYPE_FLOAT: + case HLSL_TYPE_BOOL: + case HLSL_TYPE_INT: + case HLSL_TYPE_VOID: + break; + default: + hlsl_fixme(ctx, &ctx->location, "Writing parameter type %u is not implemented.", + type->base_type); + return 0; + }; + + offset = put_u32(buffer, hlsl_sm1_base_type(type)); + put_u32(buffer, hlsl_sm1_class(type)); + put_u32(buffer, name_offset); + put_u32(buffer, semantic_offset); + put_u32(buffer, elements_count); + + switch (type->class) + { + case HLSL_CLASS_VECTOR: + put_u32(buffer, type->dimx); + put_u32(buffer, type->dimy); + break; + case HLSL_CLASS_SCALAR: + case HLSL_CLASS_MATRIX: + put_u32(buffer, type->dimy); + put_u32(buffer, type->dimx); + break; + case HLSL_CLASS_STRUCT: + put_u32(buffer, type->e.record.field_count); + break; + default: + ; + } + + if (type->class == HLSL_CLASS_STRUCT) + { + for (i = 0; i < type->e.record.field_count; ++i) + { + const struct hlsl_struct_field *field = &type->e.record.fields[i]; + write_fx_2_parameter(field->type, field->name, &field->semantic, fx); + } + } + + return offset; +} + static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) { struct vkd3d_bytecode_buffer *buffer = &fx->structured; @@ -635,6 +703,86 @@ static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_contex set_u32(buffer, count_offset, count); }
+static uint32_t get_fx_2_type_size(const struct hlsl_type *type) +{ + uint32_t size = 0, elements_count; + size_t i; + + if (type->class == HLSL_CLASS_ARRAY) + { + elements_count = hlsl_get_multiarray_size(type); + type = hlsl_get_multiarray_element_type(type); + return get_fx_2_type_size(type) * elements_count; + } + else if (type->class == HLSL_CLASS_STRUCT) + { + for (i = 0; i < type->e.record.field_count; ++i) + { + const struct hlsl_struct_field *field = &type->e.record.fields[i]; + size += get_fx_2_type_size(field->type); + } + + return size; + } + + return type->dimx * type->dimy * sizeof(float); +} + +static uint32_t write_fx_2_initial_value(const struct hlsl_ir_var *var, struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; + const struct hlsl_type *type = var->data_type; + uint32_t i, offset, size, elements_count = 1; + + size = get_fx_2_type_size(type); + + if (type->class == HLSL_CLASS_ARRAY) + { + elements_count = hlsl_get_multiarray_size(type); + type = hlsl_get_multiarray_element_type(type); + } + + if (type->class == HLSL_CLASS_OBJECT) + { + /* Objects are given sequential ids. */ + offset = put_u32(buffer, fx->object_variable_count++); + for (i = 1; i < elements_count; ++i) + put_u32(buffer, fx->object_variable_count++); + } + else + { + /* FIXME: write actual initial value */ + offset = put_u32(buffer, 0); + + for (i = 1; i < size / sizeof(uint32_t); ++i) + put_u32(buffer, 0); + } + + return offset; +} + +static void write_fx_2_parameters(struct fx_write_context *fx) +{ + struct vkd3d_bytecode_buffer *buffer = &fx->structured; + uint32_t desc_offset, value_offset; + struct hlsl_ir_var *var; + + LIST_FOR_EACH_ENTRY(var, &fx->ctx->extern_vars, struct hlsl_ir_var, extern_entry) + { + desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, fx); + value_offset = write_fx_2_initial_value(var, fx); + + put_u32(buffer, desc_offset); /* Parameter description */ + put_u32(buffer, value_offset); /* Value */ + put_u32(buffer, 0); /* Flags */ + + put_u32(buffer, 0); /* Annotations count */ + /* FIXME: write annotations */ + + ++fx->parameter_count; + } +} + static const struct fx_write_context_ops fx_2_ops = { .write_string = write_fx_2_string, @@ -644,9 +792,9 @@ static const struct fx_write_context_ops fx_2_ops =
static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) { + uint32_t offset, size, technique_count, parameter_count; struct vkd3d_bytecode_buffer buffer = { 0 }; struct vkd3d_bytecode_buffer *structured; - uint32_t offset, size, technique_count; struct fx_write_context fx;
fx_write_context_init(ctx, &fx_2_ops, &fx); @@ -658,12 +806,13 @@ static int hlsl_fx_2_write(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out) put_u32(&buffer, 0xfeff0901); /* Version. */ offset = put_u32(&buffer, 0);
- put_u32(structured, 0); /* Parameter count */ + parameter_count = put_u32(structured, 0); /* Parameter count */ technique_count = put_u32(structured, 0); put_u32(structured, 0); /* Unknown */ put_u32(structured, 0); /* Object count */
- /* TODO: parameters */ + write_fx_2_parameters(&fx); + set_u32(structured, parameter_count, fx.parameter_count);
write_techniques(ctx->globals, &fx); set_u32(structured, technique_count, fx.technique_count); diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index fd6c4f16a..93ec67d0a 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d-shader/hlsl.h @@ -1363,6 +1363,8 @@ bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), struct hlsl_block *block, void *context);
+D3DXPARAMETER_CLASS hlsl_sm1_class(const struct hlsl_type *type); +D3DXPARAMETER_TYPE hlsl_sm1_base_type(const struct hlsl_type *type); bool hlsl_sm1_register_from_semantic(struct hlsl_ctx *ctx, const struct hlsl_semantic *semantic, bool output, D3DSHADER_PARAM_REGISTER_TYPE *type, unsigned int *reg); bool hlsl_sm1_usage_from_semantic(const struct hlsl_semantic *semantic, D3DDECLUSAGE *usage, uint32_t *usage_idx); diff --git a/tests/hlsl/effect-shader-objects-fx_2.shader_test b/tests/hlsl/effect-shader-objects-fx_2.shader_test index 7c6a8947a..8801ed1f7 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] +[effect todo] vertexshader vs1; verteXshadeR vs2; pixelshader ps1;
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/fx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index 718ba8aaa..fe1a350a2 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -312,7 +312,7 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, value |= numeric_type_class[type->class]; break; default: - hlsl_fixme(ctx, &ctx->location, "Not implemented for type class %u.\n", type->class); + hlsl_fixme(ctx, &ctx->location, "Not implemented for type class %u.", type->class); return 0; }
@@ -325,7 +325,7 @@ static uint32_t get_fx_4_numeric_type_description(const struct hlsl_type *type, value |= (numeric_base_type[type->base_type] << NUMERIC_BASE_TYPE_SHIFT); break; default: - hlsl_fixme(ctx, &ctx->location, "Not implemented for base type %u.\n", type->base_type); + hlsl_fixme(ctx, &ctx->location, "Not implemented for base type %u.", type->base_type); return 0; }
@@ -426,7 +426,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co put_u32_unaligned(buffer, variable_type[type->class]); break; default: - hlsl_fixme(ctx, &ctx->location, "Writing type class %u is not implemented.\n", type->class); + hlsl_fixme(ctx, &ctx->location, "Writing type class %u is not implemented.", type->class); return 0; }
@@ -508,7 +508,7 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co put_u32_unaligned(buffer, uav_type[type->sampler_dim]); break; default: - hlsl_fixme(ctx, &ctx->location, "Object type %u is not supported.\n", type->base_type); + hlsl_fixme(ctx, &ctx->location, "Object type %u is not supported.", type->base_type); return 0; } } @@ -928,7 +928,7 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ ++fx->shader_variable_count; break; default: - hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.\n", + hlsl_fixme(ctx, &ctx->location, "Writing initializer for object type %u is not implemented.", type->base_type); }
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/fx.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index fe1a350a2..f2be00da3 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -102,6 +102,11 @@ static void set_status(struct fx_write_context *fx, int status) fx->status = status; }
+static bool has_annotations(const struct hlsl_ir_var *var) +{ + return var->annotations && !list_empty(&var->annotations->vars); +} + static uint32_t write_string(const char *string, struct fx_write_context *fx) { return fx->ops->write_string(string, fx); @@ -765,9 +770,10 @@ static void write_fx_2_parameters(struct fx_write_context *fx) { struct vkd3d_bytecode_buffer *buffer = &fx->structured; uint32_t desc_offset, value_offset; + struct hlsl_ctx *ctx = fx->ctx; struct hlsl_ir_var *var;
- LIST_FOR_EACH_ENTRY(var, &fx->ctx->extern_vars, struct hlsl_ir_var, extern_entry) + LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry) { desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, fx); value_offset = write_fx_2_initial_value(var, fx); @@ -777,7 +783,8 @@ static void write_fx_2_parameters(struct fx_write_context *fx) put_u32(buffer, 0); /* Flags */
put_u32(buffer, 0); /* Annotations count */ - /* FIXME: write annotations */ + if (has_annotations(var)) + hlsl_fixme(ctx, &ctx->location, "Writing annotations for parameters is not implemented.");
++fx->parameter_count; } @@ -864,6 +871,7 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write { HAS_EXPLICIT_BIND_POINT = 0x4, }; + struct hlsl_ctx *ctx = fx->ctx;
/* Explicit bind point. */ if (var->reg_reservation.reg_type) @@ -882,7 +890,8 @@ static void write_fx_4_numeric_variable(struct hlsl_ir_var *var, struct fx_write put_u32(buffer, flags); /* Flags */
put_u32(buffer, 0); /* Annotations count */ - /* FIXME: write annotations */ + if (has_annotations(var)) + hlsl_fixme(ctx, &ctx->location, "Writing annotations for numeric variables is not implemented."); }
static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_context *fx) @@ -933,7 +942,8 @@ static void write_fx_4_object_variable(struct hlsl_ir_var *var, struct fx_write_ }
put_u32(buffer, 0); /* Annotations count */ - /* FIXME: write annotations */ + if (has_annotations(var)) + hlsl_fixme(ctx, &ctx->location, "Writing annotations for object variables is not implemented.");
++fx->object_variable_count; }
Giovanni Mascellani (@giomasce) commented about libs/vkd3d-shader/fx.c:
set_u32(buffer, count_offset, count);
}
+static uint32_t get_fx_2_type_size(const struct hlsl_type *type) +{
- uint32_t size = 0, elements_count;
- size_t i;
- if (type->class == HLSL_CLASS_ARRAY)
- {
elements_count = hlsl_get_multiarray_size(type);
type = hlsl_get_multiarray_element_type(type);
return get_fx_2_type_size(type) * elements_count;
- }
- else if (type->class == HLSL_CLASS_STRUCT)
I guess structs can only contain numeric types, right? Otherwise the following function doesn't look right.
This merge request was approved by Giovanni Mascellani.
On Fri Mar 15 13:40:07 2024 +0000, Giovanni Mascellani wrote:
I guess structs can only contain numeric types, right? Otherwise the following function doesn't look right.
Yes, that's a restriction of fx profiles, that otherwise is allowed for shaders. We don't enforce that yet.
On Thu Mar 14 12:31:46 2024 +0000, Nikolay Sivov wrote:
changed this line in [version 2 of the diff](/wine/vkd3d/-/merge_requests/717/diffs?diff_id=105060&start_sha=9fd8b11eb72030bd0492ae89d99c6d59c101162e#140d00528dad06c799fb568ae44d8f194391c4ae_192_192)
Ah right. That's icky, but I'll leave off figuring out how to improve it for now...
This merge request was approved by Zebediah Figura.
This merge request was approved by Henri Verbeet.