From 1a8e9ff94e9355154656c5c7128e0ed5d3dd9fc8 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Mon, 28 Oct 2024 00:38:28 +0100 Subject: [PATCH] vkd3d-shader/fx: Implement parsing shader objects. Signed-off-by: Nikolay Sivov --- libs/vkd3d-shader/fx.c | 167 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 157 insertions(+), 10 deletions(-) diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c index b4a7b347..ce55e9f7 100644 --- a/libs/vkd3d-shader/fx.c +++ b/libs/vkd3d-shader/fx.c @@ -499,7 +499,15 @@ enum fx_4_type_constants FX_4_NUMERIC_COLUMN_MAJOR_MASK = 0x4000, /* Object types */ - FX_4_OBJECT_TYPE_STRING = 1, + FX_4_OBJECT_TYPE_STRING = 0x1, + FX_4_OBJECT_TYPE_PIXEL_SHADER = 0x5, + FX_4_OBJECT_TYPE_VERTEX_SHADER = 0x6, + FX_4_OBJECT_TYPE_GEOMETRY_SHADER = 0x7, + FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO = 0x8, + FX_5_OBJECT_TYPE_GEOMETRY_SHADER = 0x1b, + FX_5_OBJECT_TYPE_COMPUTE_SHADER = 0x1c, + FX_5_OBJECT_TYPE_HULL_SHADER = 0x1d, + FX_5_OBJECT_TYPE_DOMAIN_SHADER = 0x1e, /* Types */ FX_4_TYPE_CLASS_NUMERIC = 1, @@ -807,11 +815,11 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co } else if (element_type->class == HLSL_CLASS_PIXEL_SHADER) { - put_u32_unaligned(buffer, 5); + put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_PIXEL_SHADER); } else if (element_type->class == HLSL_CLASS_VERTEX_SHADER) { - put_u32_unaligned(buffer, 6); + put_u32_unaligned(buffer, FX_4_OBJECT_TYPE_VERTEX_SHADER); } else if (element_type->class == HLSL_CLASS_RASTERIZER_STATE) { @@ -836,15 +844,15 @@ static uint32_t write_fx_4_type(const struct hlsl_type *type, struct fx_write_co } else if (element_type->class == HLSL_CLASS_COMPUTE_SHADER) { - put_u32_unaligned(buffer, 28); + put_u32_unaligned(buffer, FX_5_OBJECT_TYPE_COMPUTE_SHADER); } else if (element_type->class == HLSL_CLASS_HULL_SHADER) { - put_u32_unaligned(buffer, 29); + put_u32_unaligned(buffer, FX_5_OBJECT_TYPE_HULL_SHADER); } else if (element_type->class == HLSL_CLASS_DOMAIN_SHADER) { - put_u32_unaligned(buffer, 30); + put_u32_unaligned(buffer, FX_5_OBJECT_TYPE_DOMAIN_SHADER); } else { @@ -2919,19 +2927,28 @@ static int fx_2_parse(struct fx_parser *parser) return -1; } -static void fx_parser_read_unstructured(struct fx_parser *parser, void *dst, uint32_t offset, size_t size) +static const void *fx_parser_get_unstructured_ptr(struct fx_parser *parser, uint32_t offset, size_t size) { const uint8_t *ptr = parser->unstructured.ptr; - memset(dst, 0, size); if (offset >= parser->unstructured.size || size > parser->unstructured.size - offset) { parser->failed = true; - return; + return NULL; } - ptr += offset; + return &ptr[offset]; +} + +static void fx_parser_read_unstructured(struct fx_parser *parser, void *dst, uint32_t offset, size_t size) +{ + const uint8_t *ptr; + + memset(dst, 0, size); + if (!(ptr = fx_parser_get_unstructured_ptr(parser, offset, size))) + return; + memcpy(dst, ptr, size); } @@ -3161,6 +3178,123 @@ static void fx_parse_buffers(struct fx_parser *parser) } } +static void fx_4_parse_shader_initializer(struct fx_parser *parser, unsigned int object_type) +{ + struct vkd3d_shader_compile_info info = { 0 }; + struct vkd3d_shader_code output; + uint32_t data_size, offset; + const void *data = NULL; + const char *p, *q, *end; + struct fx_5_shader + { + uint32_t offset; + uint32_t sodecl[4]; + uint32_t sodecl_count; + uint32_t rast_stream; + uint32_t iface_bindings_count; + uint32_t iface_bindings; + } shader5; + struct fx_4_gs_so + { + uint32_t offset; + uint32_t sodecl; + } gs_so; + int ret; + + static const struct vkd3d_shader_compile_option options[] = + { + {VKD3D_SHADER_COMPILE_OPTION_API_VERSION, VKD3D_SHADER_API_VERSION_1_13}, + }; + + switch (object_type) + { + case FX_4_OBJECT_TYPE_PIXEL_SHADER: + case FX_4_OBJECT_TYPE_VERTEX_SHADER: + case FX_4_OBJECT_TYPE_GEOMETRY_SHADER: + offset = fx_parser_read_u32(parser); + break; + + case FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO: + fx_parser_read_u32s(parser, &gs_so, sizeof(gs_so)); + offset = gs_so.offset; + break; + + case FX_5_OBJECT_TYPE_GEOMETRY_SHADER: + case FX_5_OBJECT_TYPE_COMPUTE_SHADER: + case FX_5_OBJECT_TYPE_HULL_SHADER: + case FX_5_OBJECT_TYPE_DOMAIN_SHADER: + fx_parser_read_u32s(parser, &shader5, sizeof(shader5)); + offset = shader5.offset; + break; + + default: + parser->failed = true; + return; + } + + fx_parser_read_unstructured(parser, &data_size, offset, sizeof(data_size)); + if (data_size) + data = fx_parser_get_unstructured_ptr(parser, offset + 4, data_size); + + if (!data) + return; + + info.type = VKD3D_SHADER_STRUCTURE_TYPE_COMPILE_INFO; + info.source.code = data; + info.source.size = data_size; + info.source_type = VKD3D_SHADER_SOURCE_DXBC_TPF; + 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.\n"); + 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, "}"); + if (object_type == FX_4_OBJECT_TYPE_GEOMETRY_SHADER && gs_so.sodecl) + { + vkd3d_string_buffer_printf(&parser->buffer, "\n/* Stream output declaration: \"%s\" */", + fx_4_get_string(parser, gs_so.sodecl)); + } + else if (object_type == FX_5_OBJECT_TYPE_GEOMETRY_SHADER) + { + for (unsigned int i = 0; i < ARRAY_SIZE(shader5.sodecl); ++i) + { + if (shader5.sodecl[i]) + vkd3d_string_buffer_printf(&parser->buffer, "\n/* Stream output %u declaration: \"%s\" */", + i, fx_4_get_string(parser, shader5.sodecl[i])); + } + if (shader5.sodecl_count) + vkd3d_string_buffer_printf(&parser->buffer, "\n/* Rasterized stream %u */", shader5.rast_stream); + } + + vkd3d_shader_free_shader_code(&output); +} + static void fx_4_parse_objects(struct fx_parser *parser) { struct fx_4_object_variable @@ -3199,6 +3333,18 @@ static void fx_4_parse_objects(struct fx_parser *parser) value = fx_parser_read_u32(parser); fx_4_parse_string_initializer(parser, value); break; + case FX_4_OBJECT_TYPE_PIXEL_SHADER: + case FX_4_OBJECT_TYPE_VERTEX_SHADER: + case FX_4_OBJECT_TYPE_GEOMETRY_SHADER: + case FX_4_OBJECT_TYPE_GEOMETRY_SHADER_SO: + case FX_5_OBJECT_TYPE_GEOMETRY_SHADER: + case FX_5_OBJECT_TYPE_COMPUTE_SHADER: + case FX_5_OBJECT_TYPE_HULL_SHADER: + case FX_5_OBJECT_TYPE_DOMAIN_SHADER: + parse_fx_start_indent(parser); + fx_4_parse_shader_initializer(parser, type.typeinfo); + parse_fx_end_indent(parser); + break; default: fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED, "Parsing object type %u is not implemented.\n", type.typeinfo); @@ -3207,6 +3353,7 @@ static void fx_4_parse_objects(struct fx_parser *parser) vkd3d_string_buffer_printf(&parser->buffer, ",\n"); } vkd3d_string_buffer_printf(&parser->buffer, "};\n"); + fx_parse_fx_4_annotations(parser); } }