vkd3d-shader/fx: Fix writing fx_2_0 structure parameters.

Currently structure type descriptions get interleaved with variable
length string data. The solution is to write all fixed length fields
first, then append strings.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
This commit is contained in:
Nikolay Sivov
2025-05-26 19:40:00 +02:00
committed by Henri Verbeet
parent bb50117747
commit 87ec2d9897
Notes: Henri Verbeet 2025-05-27 21:09:49 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1519

View File

@@ -1547,12 +1547,33 @@ static uint32_t get_fx_2_type_class(const struct hlsl_type *type)
return hlsl_sm1_class(type); return hlsl_sm1_class(type);
} }
static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *name, struct fx_2_write_type_context
const struct hlsl_semantic *semantic, bool is_combined_sampler, struct fx_write_context *fx)
{ {
struct vkd3d_bytecode_buffer *buffer = &fx->unstructured; uint32_t *names;
uint32_t semantic_offset, offset, elements_count = 0, name_offset; uint32_t *semantics;
size_t i; uint32_t count;
uint32_t offset;
bool is_combined_sampler;
struct fx_write_context *fx;
};
static void count_type_iter(const struct hlsl_type *type, const char *name,
const struct hlsl_semantic *semantic, void *context)
{
struct fx_2_write_type_context *ctx = context;
++ctx->count;
}
static void write_fx_2_type_iter(const struct hlsl_type *type, const char *name,
const struct hlsl_semantic *semantic, void *context)
{
struct fx_2_write_type_context *ctx = context;
struct fx_write_context *fx = ctx->fx;
struct vkd3d_bytecode_buffer *buffer;
uint32_t offset, elements_count = 0;
/* Resolve arrays to element type and number of elements. */ /* Resolve arrays to element type and number of elements. */
if (type->class == HLSL_CLASS_ARRAY) if (type->class == HLSL_CLASS_ARRAY)
@@ -1561,13 +1582,11 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n
type = hlsl_get_multiarray_element_type(type); type = hlsl_get_multiarray_element_type(type);
} }
name_offset = write_string(name, fx); buffer = &fx->unstructured;
semantic_offset = semantic->raw_name ? write_string(semantic->raw_name, fx) : 0; offset = put_u32(buffer, hlsl_sm1_base_type(type, ctx->is_combined_sampler));
offset = put_u32(buffer, hlsl_sm1_base_type(type, is_combined_sampler));
put_u32(buffer, get_fx_2_type_class(type)); put_u32(buffer, get_fx_2_type_class(type));
put_u32(buffer, name_offset); *ctx->names++ = put_u32(buffer, 0);
put_u32(buffer, semantic_offset); *ctx->semantics++ = put_u32(buffer, 0);
put_u32(buffer, elements_count); put_u32(buffer, elements_count);
switch (type->class) switch (type->class)
@@ -1592,19 +1611,68 @@ static uint32_t write_fx_2_parameter(const struct hlsl_type *type, const char *n
; ;
} }
/* Save the offset of the top level type. */
if (!ctx->offset)
ctx->offset = offset;
}
static void write_fx_2_type_strings_iter(const struct hlsl_type *type, const char *name,
const struct hlsl_semantic *semantic, void *context)
{
struct fx_2_write_type_context *ctx = context;
struct fx_write_context *fx = ctx->fx;
struct vkd3d_bytecode_buffer *buffer;
buffer = &fx->unstructured;
set_u32(buffer, *ctx->names++, write_string(name, fx));
set_u32(buffer, *ctx->semantics++, semantic->raw_name ? write_string(semantic->raw_name, fx) : 0);
}
static void foreach_type(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic,
void (*iter_func)(const struct hlsl_type *type, const char *name, const struct hlsl_semantic *semantic, void *context),
void *context)
{
iter_func(type, name, semantic, context);
type = hlsl_get_multiarray_element_type(type);
if (type->class == HLSL_CLASS_STRUCT) if (type->class == HLSL_CLASS_STRUCT)
{ {
for (i = 0; i < type->e.record.field_count; ++i) for (size_t i = 0; i < type->e.record.field_count; ++i)
{ {
const struct hlsl_struct_field *field = &type->e.record.fields[i]; const struct hlsl_struct_field *field = &type->e.record.fields[i];
foreach_type(field->type, field->name, &field->semantic, iter_func, context);
/* Validated in check_invalid_object_fields(). */
VKD3D_ASSERT(hlsl_is_numeric_type(field->type));
write_fx_2_parameter(field->type, field->name, &field->semantic, false, fx);
} }
} }
}
return offset; static uint32_t write_fx_2_parameter(const struct hlsl_ir_var *var, struct fx_write_context *fx)
{
struct fx_2_write_type_context ctx = { .fx = fx, .is_combined_sampler = var->is_combined_sampler };
uint32_t *offsets;
/* Parameter type information has to be stored in a contiguous segment, so
* that any structure fields come right after each other. To achieve that
* the variable length string data is written after the type data. */
/* Calculate the number of string entries needed for this type. */
foreach_type(var->data_type, var->name, &var->semantic, count_type_iter, &ctx);
if (!(offsets = calloc(ctx.count, 2 * sizeof(*offsets))))
return 0;
/* Writing type information also sets string offsets. */
ctx.names = offsets;
ctx.semantics = &offsets[ctx.count];
foreach_type(var->data_type, var->name, &var->semantic, write_fx_2_type_iter, &ctx);
/* Now the final pass to write the string data. */
ctx.names = offsets;
ctx.semantics = &offsets[ctx.count];
foreach_type(var->data_type, var->name, &var->semantic, write_fx_2_type_strings_iter, &ctx);
free(offsets);
return ctx.offset;
} }
static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx) static void write_fx_2_technique(struct hlsl_ir_var *var, struct fx_write_context *fx)
@@ -1876,7 +1944,7 @@ static void write_fx_2_parameters(struct fx_write_context *fx)
if (!is_type_supported_fx_2(ctx, var->data_type, &var->loc)) if (!is_type_supported_fx_2(ctx, var->data_type, &var->loc))
continue; continue;
desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx); desc_offset = write_fx_2_parameter(var, fx);
value_offset = write_fx_2_initial_value(var, fx); value_offset = write_fx_2_initial_value(var, fx);
flags = 0; flags = 0;
@@ -1899,7 +1967,7 @@ static void write_fx_2_annotation(struct hlsl_ir_var *var, struct fx_write_conte
struct vkd3d_bytecode_buffer *buffer = &fx->structured; struct vkd3d_bytecode_buffer *buffer = &fx->structured;
uint32_t desc_offset, value_offset; uint32_t desc_offset, value_offset;
desc_offset = write_fx_2_parameter(var->data_type, var->name, &var->semantic, var->is_combined_sampler, fx); desc_offset = write_fx_2_parameter(var, fx);
value_offset = write_fx_2_initial_value(var, fx); value_offset = write_fx_2_initial_value(var, fx);
put_u32(buffer, desc_offset); put_u32(buffer, desc_offset);