From 1de043d1dac621d9f476dc941980843b1612ed40 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov <nsivov@codeweavers.com> Date: Mon, 10 Mar 2025 17:58:18 +0100 Subject: [PATCH 1/3] vkd3d-shader/fx: Add support for parsing fx_2_0 sampler states. Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- libs/vkd3d-shader/fx.c | 114 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 13 deletions(-) diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index 4fbce3937..d60620e72 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -725,6 +725,28 @@ static const struct rhs_named_value fx_2_lighttype_values[] = { NULL } }; +static const struct rhs_named_value fx_2_address_values[] = +{ + { "WRAP", 1 }, + { "MIRROR", 2 }, + { "CLAMP", 3 }, + { "BORDER", 4 }, + { "MIRROR_ONCE", 5 }, + { NULL } +}; + +static const struct rhs_named_value fx_2_filter_values[] = +{ + { "NONE", 0 }, + { "POINT", 1 }, + { "LINEAR", 2 }, + { "ANISOTROPIC", 3 }, + { "PYRAMIDALQUAD", 6 }, + { "GAUSSIANQUAD", 7 }, + { "CONVOLUTIONMONO", 8 }, + { NULL } +}; + static const struct fx_2_state { const char *name; @@ -895,6 +917,38 @@ fx_2_states[] = { "VertexShader", HLSL_CLASS_SCALAR, FX_VERTEXSHADER, 1, 1, 146 }, { "PixelShader", HLSL_CLASS_SCALAR, FX_PIXELSHADER, 1, 1, 147 }, + + { "VertexShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 148 }, + { "VertexShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u-1, 149 }, + { "VertexShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u-1, 150 }, + { "VertexShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 151 }, + { "VertexShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 152 }, + { "VertexShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 153 }, + { "VertexShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 154 }, + { "VertexShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 155 }, + + { "PixelShaderConstantF", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 156 }, + { "PixelShaderConstantB", HLSL_CLASS_SCALAR, FX_BOOL, 1, ~0u-1, 157 }, + { "PixelShaderConstantI", HLSL_CLASS_SCALAR, FX_UINT, 1, ~0u-1, 158 }, + { "PixelShaderConstant", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 159 }, + { "PixelShaderConstant1", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 160 }, + { "PixelShaderConstant2", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 161 }, + { "PixelShaderConstant3", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 162 }, + { "PixelShaderConstant4", HLSL_CLASS_SCALAR, FX_FLOAT, 1, ~0u-1, 163 }, + + { "Texture", HLSL_CLASS_SCALAR, FX_TEXTURE, 1, 1, 164 }, + { "AddressU", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 165, fx_2_address_values }, + { "AddressV", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 166, fx_2_address_values }, + { "AddressW", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 167, fx_2_address_values }, + { "BorderColor", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 168 }, + { "MagFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 169, fx_2_filter_values }, + { "MinFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 170, fx_2_filter_values }, + { "MipFilter", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 171, fx_2_filter_values }, + { "MipMapLodBias", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 172 }, + { "MaxMipLevel", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 173 }, + { "MaxAnisotropy", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 174 }, + { "SRBTexture", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 175 }, + { "ElementIndex", HLSL_CLASS_SCALAR, FX_UINT, 1, 1, 176 }, }; static void write_fx_2_pass(struct hlsl_ir_var *var, struct fx_write_context *fx) @@ -3644,6 +3698,40 @@ static bool is_fx_2_sampler(uint32_t type) || type == D3DXPT_SAMPLERCUBE; } +static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_assignment *entry); + +static void parse_fx_2_sampler(struct fx_parser *parser, uint32_t element_count, + uint32_t offset) +{ + struct fx_assignment entry; + uint32_t count; + + element_count = max(element_count, 1); + + vkd3d_string_buffer_printf(&parser->buffer, "\n"); + for (uint32_t i = 0; i < element_count; ++i) + { + fx_parser_read_unstructured(parser, &count, offset, sizeof(count)); + offset += sizeof(count); + + parse_fx_start_indent(parser); + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "{\n"); + parse_fx_start_indent(parser); + for (uint32_t j = 0; j < count; ++j, offset += sizeof(entry)) + { + fx_parser_read_unstructured(parser, &entry, offset, sizeof(entry)); + + parse_fx_print_indent(parser); + fx_parse_fx_2_assignment(parser, &entry); + } + parse_fx_end_indent(parser); + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "},\n"); + parse_fx_end_indent(parser); + } +} + static void fx_parse_fx_2_initial_value(struct fx_parser *parser, uint32_t param, uint32_t value) { struct fx_2_var @@ -3672,8 +3760,7 @@ static void fx_parse_fx_2_initial_value(struct fx_parser *parser, uint32_t param if (var.class == D3DXPC_OBJECT) { if (is_fx_2_sampler(var.type)) - fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, - "Parsing sampler initializers is not supported."); + parse_fx_2_sampler(parser, var.element_count, value); else parse_fx_2_object_value(parser, var.element_count, var.type, value); } @@ -3714,24 +3801,22 @@ static void fx_parse_fx_2_annotations(struct fx_parser *parser, uint32_t count) vkd3d_string_buffer_printf(&parser->buffer, ">"); } -static void fx_parse_fx_2_assignment(struct fx_parser *parser) +static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_assignment *entry) { const struct rhs_named_value *named_value = NULL; const struct fx_2_state *state = NULL; - struct fx_assignment entry; - fx_parser_read_u32s(parser, &entry, sizeof(entry)); - if (entry.id <= ARRAY_SIZE(fx_2_states)) + if (entry->id <= ARRAY_SIZE(fx_2_states)) { - state = &fx_2_states[entry.id]; + state = &fx_2_states[entry->id]; vkd3d_string_buffer_printf(&parser->buffer, "%s", state->name); if (state->array_size > 1) - vkd3d_string_buffer_printf(&parser->buffer, "[%u]", entry.lhs_index); + vkd3d_string_buffer_printf(&parser->buffer, "[%u]", entry->lhs_index); } else { - vkd3d_string_buffer_printf(&parser->buffer, "<unrecognized state %u>", entry.id); + vkd3d_string_buffer_printf(&parser->buffer, "<unrecognized state %u>", entry->id); } vkd3d_string_buffer_printf(&parser->buffer, " = "); @@ -3740,7 +3825,7 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser) const struct rhs_named_value *ptr = state->values; uint32_t value; - fx_parser_read_unstructured(parser, &value, entry.value, sizeof(value)); + fx_parser_read_unstructured(parser, &value, entry->value, sizeof(value)); while (ptr->name) { @@ -3759,11 +3844,11 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser) } else if (state && (state->type == FX_UINT || state->type == FX_FLOAT)) { - uint32_t offset = entry.type; + uint32_t offset = entry->type; unsigned int size; size = fx_get_fx_2_type_size(parser, &offset); - parse_fx_2_numeric_value(parser, entry.value, size, entry.type); + parse_fx_2_numeric_value(parser, entry->value, size, entry->type); } else { @@ -3820,8 +3905,11 @@ static void fx_parse_fx_2_technique(struct fx_parser *parser) parse_fx_start_indent(parser); for (uint32_t j = 0; j < pass.assignment_count; ++j) { + struct fx_assignment entry; + parse_fx_print_indent(parser); - fx_parse_fx_2_assignment(parser); + fx_parser_read_u32s(parser, &entry, sizeof(entry)); + fx_parse_fx_2_assignment(parser, &entry); } parse_fx_end_indent(parser); -- GitLab From 0a3a2d5b9575945fc4ed36a4ae1afc6e89f27844 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov <nsivov@codeweavers.com> Date: Mon, 10 Mar 2025 23:05:27 +0100 Subject: [PATCH 2/3] vkd3d-shader/fx: Add support for dumping fx_2_0 shader blobs. Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- libs/vkd3d-shader/fx.c | 97 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 12 deletions(-) diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index d60620e72..abad06ef3 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -3842,13 +3842,27 @@ static void fx_parse_fx_2_assignment(struct fx_parser *parser, const struct fx_a { vkd3d_string_buffer_printf(&parser->buffer, "%s /* %u */", named_value->name, named_value->value); } - else if (state && (state->type == FX_UINT || state->type == FX_FLOAT)) + else if (state) { - uint32_t offset = entry->type; - unsigned int size; + if (state->type == FX_UINT || state->type == FX_FLOAT) + { + uint32_t offset = entry->type; + unsigned int size; - size = fx_get_fx_2_type_size(parser, &offset); - parse_fx_2_numeric_value(parser, entry->value, size, entry->type); + size = fx_get_fx_2_type_size(parser, &offset); + parse_fx_2_numeric_value(parser, entry->value, size, entry->type); + } + else if (state->type == FX_VERTEXSHADER || state->type == FX_PIXELSHADER) + { + uint32_t id; + + fx_parser_read_unstructured(parser, &id, entry->value, sizeof(id)); + vkd3d_string_buffer_printf(&parser->buffer, "<object id %u>", id); + } + else + { + vkd3d_string_buffer_printf(&parser->buffer, "<ignored>"); + } } else { @@ -3946,10 +3960,59 @@ static void fx_2_parse_parameters(struct fx_parser *parser, uint32_t count) vkd3d_string_buffer_printf(&parser->buffer, "\n"); } +static void fx_2_parse_shader_blob(struct fx_parser *parser, const void *data, uint32_t data_size) +{ + struct vkd3d_shader_compile_info info = { 0 }; + struct vkd3d_shader_code output; + const char *p, *q, *end; + int ret; + + static const struct vkd3d_shader_compile_option options[] = + { + {VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_15}, + }; + + info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO; + info.source.code = data; + info.source.size = data_size; + info.source_type = VKD3D_SHADER_SOURCE_D3D_BYTECODE; + info.target_type = VKD3D_SHADER_TARGET_D3D_ASM; + info.options = options; + info.option_count = ARRAY_SIZE(options); + info.log_level = VKD3D_SHADER_LOG_INFO; + + if ((ret = vkd3d_shader_compile(&info, &output, NULL)) < 0) + { + fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA, + "Failed to disassemble shader blob."); + return; + } + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "asm {\n"); + + parse_fx_start_indent(parser); + + end = (const char *)output.code + output.size; + for (p = output.code; p < end; p = q) + { + if (!(q = memchr(p, '\n', end - p))) + q = end; + else + ++q; + + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "%.*s", (int)(q - p), p); + } + + parse_fx_end_indent(parser); + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "}"); +} + static void fx_parse_fx_2_data_blob(struct fx_parser *parser) { uint32_t id, size; - const char *str; + const void *data; id = fx_parser_read_u32(parser); size = fx_parser_read_u32(parser); @@ -3970,13 +4033,23 @@ static void fx_parse_fx_2_data_blob(struct fx_parser *parser) case D3DXPT_VERTEXSHADER: vkd3d_string_buffer_printf(&parser->buffer, "%s object %u size %u bytes%s\n", fx_2_types[type], id, size, size ? ":" : ","); - if (size && type == D3DXPT_STRING) + + if (size) { - parse_fx_start_indent(parser); - parse_fx_print_indent(parser); - str = fx_parser_get_ptr(parser, size); - vkd3d_string_buffer_printf(&parser->buffer, "\"%.*s\"\n", size, str); - parse_fx_end_indent(parser); + data = fx_parser_get_ptr(parser, size); + + if (type == D3DXPT_STRING) + { + parse_fx_start_indent(parser); + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "\"%.*s\"", size, (const char *)data); + parse_fx_end_indent(parser); + } + else if (type == D3DXPT_PIXELSHADER || type == D3DXPT_VERTEXSHADER) + { + fx_2_parse_shader_blob(parser, data, size); + } + vkd3d_string_buffer_printf(&parser->buffer, "\n"); } break; default: -- GitLab From e9cdbdd58c1bee08fca252a3c19ebec11a362182 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov <nsivov@codeweavers.com> Date: Tue, 11 Mar 2025 00:11:01 +0100 Subject: [PATCH 3/3] vkd3d-shader/fx: Dump complex state values blobs for fx_2_0. Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> --- libs/vkd3d-shader/fx.c | 64 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index abad06ef3..d4e612c9d 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -4064,9 +4064,62 @@ static void fx_parse_fx_2_data_blob(struct fx_parser *parser) fx_parser_skip(parser, align(size, 4)); } +static void fx_dump_blob(struct fx_parser *parser, const void *blob, uint32_t size) +{ + const uint32_t *data = (const uint32_t *)blob; + unsigned int i, j, n; + + size /= sizeof(*data); + i = 0; + while (i < size) + { + parse_fx_print_indent(parser); + n = min(size - i, 8); + for (j = 0; j < n; ++j) + vkd3d_string_buffer_printf(&parser->buffer, "0x%08x,", data[i + j]); + i += n; + vkd3d_string_buffer_printf(&parser->buffer, "\n"); + } +} + +static void fx_parse_fx_2_complex_state(struct fx_parser *parser) +{ + struct + { + uint32_t technique; + uint32_t index; + uint32_t element; + uint32_t state; + uint32_t value_type; + } state; + const void *data; + uint32_t size; + + fx_parser_read_u32s(parser, &state, sizeof(state)); + + if (state.technique == ~0u) + { + vkd3d_string_buffer_printf(&parser->buffer, "parameter %u[%u], state %u =\n", + state.index, state.element, state.state); + } + else + { + vkd3d_string_buffer_printf(&parser->buffer, "technique %u, pass %u, state %u =\n", + state.technique, state.index, state.state); + } + + size = fx_parser_read_u32(parser); + data = fx_parser_get_ptr(parser, size); + + parse_fx_print_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "blob size %u\n", size); + fx_dump_blob(parser, data, size); + fx_parser_skip(parser, align(size, 4)); +} + static void fx_2_parse(struct fx_parser *parser) { - uint32_t i, size, parameter_count, technique_count, blob_count; + uint32_t i, size, parameter_count, technique_count, blob_count, state_count; fx_parser_skip(parser, sizeof(uint32_t)); /* Version */ size = fx_parser_read_u32(parser); @@ -4092,13 +4145,20 @@ static void fx_2_parse(struct fx_parser *parser) fx_parse_fx_2_technique(parser); blob_count = fx_parser_read_u32(parser); - fx_parser_read_u32(parser); /* Resource count */ + state_count = fx_parser_read_u32(parser); vkd3d_string_buffer_printf(&parser->buffer, "object data {\n"); parse_fx_start_indent(parser); for (i = 0; i < blob_count; ++i) fx_parse_fx_2_data_blob(parser); parse_fx_end_indent(parser); + vkd3d_string_buffer_printf(&parser->buffer, "}\n\n"); + + vkd3d_string_buffer_printf(&parser->buffer, "state data {\n"); + parse_fx_start_indent(parser); + for (i = 0; i < state_count; ++i) + fx_parse_fx_2_complex_state(parser); + parse_fx_end_indent(parser); vkd3d_string_buffer_printf(&parser->buffer, "}\n"); } -- GitLab