From 37491716565a94b335b71b10e0e49edf0e793d67 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Fri, 7 Mar 2025 12:45:24 +0100
Subject: [PATCH 1/2] vkd3d-shader/fx: Output object initialiser IDs for
 fx_2_0.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
---
 libs/vkd3d-shader/fx.c | 37 ++++++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c
index 303a63a42..379f5f64a 100644
--- a/libs/vkd3d-shader/fx.c
+++ b/libs/vkd3d-shader/fx.c
@@ -3543,6 +3543,21 @@ static void fx_parse_fx_2_type(struct fx_parser *parser, uint32_t offset)
     }
 }
 
+static void parse_fx_2_object_value(struct fx_parser *parser, uint32_t element_count, uint32_t offset)
+{
+    uint32_t id;
+
+    element_count = max(element_count, 1);
+
+    for (uint32_t i = 0; i < element_count; ++i, offset += 4)
+    {
+        fx_parser_read_unstructured(parser, &id, offset, sizeof(id));
+        vkd3d_string_buffer_printf(&parser->buffer, "<object id %u>", id);
+        if (element_count > 1)
+            vkd3d_string_buffer_printf(&parser->buffer, ", ");
+    }
+}
+
 static void parse_fx_2_numeric_value(struct fx_parser *parser, uint32_t offset,
         unsigned int size, uint32_t base_type)
 {
@@ -3595,6 +3610,15 @@ static void fx_parse_fx_2_parameter(struct fx_parser *parser, uint32_t offset)
         vkd3d_string_buffer_printf(&parser->buffer, "[%u]", var.element_count);
 }
 
+static bool is_fx_2_sampler(uint32_t type)
+{
+    return type == D3DXPT_SAMPLER
+            || type == D3DXPT_SAMPLER1D
+            || type == D3DXPT_SAMPLER2D
+            || type == D3DXPT_SAMPLER3D
+            || type == D3DXPT_SAMPLERCUBE;
+}
+
 static void fx_parse_fx_2_initial_value(struct fx_parser *parser, uint32_t param, uint32_t value)
 {
     struct fx_2_var
@@ -3620,11 +3644,18 @@ static void fx_parse_fx_2_initial_value(struct fx_parser *parser, uint32_t param
     if (var.element_count)
         vkd3d_string_buffer_printf(&parser->buffer, "{ ");
 
-    if (var.type == D3DXPT_STRING)
-        fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED,
-                "Only numeric initial values are supported.");
+    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.");
+        else
+            parse_fx_2_object_value(parser, var.element_count, value);
+    }
     else
+    {
         parse_fx_2_numeric_value(parser, value, size, var.type);
+    }
 
     if (var.element_count)
         vkd3d_string_buffer_printf(&parser->buffer, " }");
-- 
GitLab


From 553e37314a289f5e5e768c6f3a960f060b5443b2 Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Fri, 7 Mar 2025 13:50:03 +0100
Subject: [PATCH 2/2] vkd3d-shader/fx: Print string object entries for fx_2_0.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
---
 libs/vkd3d-shader/fx.c                   | 169 ++++++++++++++++++-----
 libs/vkd3d-shader/vkd3d_shader_private.h |   1 +
 2 files changed, 134 insertions(+), 36 deletions(-)

diff --git a/libs/vkd3d-shader/fx.c b/libs/vkd3d-shader/fx.c
index 379f5f64a..4fbce3937 100644
--- a/libs/vkd3d-shader/fx.c
+++ b/libs/vkd3d-shader/fx.c
@@ -3344,6 +3344,11 @@ struct fx_parser
     uint32_t buffer_count;
     uint32_t object_count;
     uint32_t group_count;
+    struct
+    {
+        uint32_t count;
+        uint32_t *types;
+    } objects;
     bool failed;
 };
 
@@ -3409,6 +3414,17 @@ static const void *fx_parser_get_unstructured_ptr(struct fx_parser *parser, uint
     return &ptr[offset];
 }
 
+static const void *fx_parser_get_ptr(struct fx_parser *parser, size_t size)
+{
+    if (parser->end - parser->ptr < size)
+    {
+        parser->failed = true;
+        return NULL;
+    }
+
+    return parser->ptr;
+}
+
 static uint32_t fx_parser_read_unstructured(struct fx_parser *parser, void *dst, uint32_t offset, size_t size)
 {
     const uint8_t *ptr;
@@ -3492,32 +3508,33 @@ static unsigned int fx_get_fx_2_type_size(struct fx_parser *parser, uint32_t *of
     return size;
 }
 
+static const char *const fx_2_types[] =
+{
+    [D3DXPT_VOID]           = "void",
+    [D3DXPT_BOOL]           = "bool",
+    [D3DXPT_INT]            = "int",
+    [D3DXPT_FLOAT]          = "float",
+    [D3DXPT_STRING]         = "string",
+    [D3DXPT_TEXTURE]        = "texture",
+    [D3DXPT_TEXTURE1D]      = "texture1D",
+    [D3DXPT_TEXTURE2D]      = "texture2D",
+    [D3DXPT_TEXTURE3D]      = "texture3D",
+    [D3DXPT_TEXTURECUBE]    = "textureCUBE",
+    [D3DXPT_SAMPLER]        = "sampler",
+    [D3DXPT_SAMPLER1D]      = "sampler1D",
+    [D3DXPT_SAMPLER2D]      = "sampler2D",
+    [D3DXPT_SAMPLER3D]      = "sampler3D",
+    [D3DXPT_SAMPLERCUBE]    = "samplerCUBE",
+    [D3DXPT_PIXELSHADER]    = "PixelShader",
+    [D3DXPT_VERTEXSHADER]   = "VertexShader",
+    [D3DXPT_PIXELFRAGMENT]  = "<pixel-fragment>",
+    [D3DXPT_VERTEXFRAGMENT] = "<vertex-fragment>",
+    [D3DXPT_UNSUPPORTED]    = "<unsupported>",
+};
+
 static void fx_parse_fx_2_type(struct fx_parser *parser, uint32_t offset)
 {
     uint32_t type, class, rows, columns;
-    static const char *const types[] =
-    {
-        [D3DXPT_VOID]           = "void",
-        [D3DXPT_BOOL]           = "bool",
-        [D3DXPT_INT]            = "int",
-        [D3DXPT_FLOAT]          = "float",
-        [D3DXPT_STRING]         = "string",
-        [D3DXPT_TEXTURE]        = "texture",
-        [D3DXPT_TEXTURE1D]      = "texture1D",
-        [D3DXPT_TEXTURE2D]      = "texture2D",
-        [D3DXPT_TEXTURE3D]      = "texture3D",
-        [D3DXPT_TEXTURECUBE]    = "textureCUBE",
-        [D3DXPT_SAMPLER]        = "sampler",
-        [D3DXPT_SAMPLER1D]      = "sampler1D",
-        [D3DXPT_SAMPLER2D]      = "sampler2D",
-        [D3DXPT_SAMPLER3D]      = "sampler3D",
-        [D3DXPT_SAMPLERCUBE]    = "samplerCUBE",
-        [D3DXPT_PIXELSHADER]    = "PixelShader",
-        [D3DXPT_VERTEXSHADER]   = "VertexShader",
-        [D3DXPT_PIXELFRAGMENT]  = "<pixel-fragment>",
-        [D3DXPT_VERTEXFRAGMENT] = "<vertex-fragment>",
-        [D3DXPT_UNSUPPORTED]    = "<unsupported>",
-    };
     const char *name;
 
     fx_parser_read_unstructured(parser, &type, offset, sizeof(type));
@@ -3526,7 +3543,7 @@ static void fx_parse_fx_2_type(struct fx_parser *parser, uint32_t offset)
     if (class == D3DXPC_STRUCT)
         name = "struct";
     else
-        name = type < ARRAY_SIZE(types) ? types[type] : "<unknown>";
+        name = type < ARRAY_SIZE(fx_2_types) ? fx_2_types[type] : "<unknown>";
 
     vkd3d_string_buffer_printf(&parser->buffer, "%s", name);
     if (class == D3DXPC_VECTOR)
@@ -3543,7 +3560,8 @@ static void fx_parse_fx_2_type(struct fx_parser *parser, uint32_t offset)
     }
 }
 
-static void parse_fx_2_object_value(struct fx_parser *parser, uint32_t element_count, uint32_t offset)
+static void parse_fx_2_object_value(struct fx_parser *parser, uint32_t element_count,
+        uint32_t type, uint32_t offset)
 {
     uint32_t id;
 
@@ -3555,7 +3573,14 @@ static void parse_fx_2_object_value(struct fx_parser *parser, uint32_t element_c
         vkd3d_string_buffer_printf(&parser->buffer, "<object id %u>", id);
         if (element_count > 1)
             vkd3d_string_buffer_printf(&parser->buffer, ", ");
+        if (id < parser->objects.count)
+            parser->objects.types[id] = type;
+        else
+            fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_INVALID_DATA,
+                    "Initializer object id exceeds the number of objects in the effect.");
     }
+
+
 }
 
 static void parse_fx_2_numeric_value(struct fx_parser *parser, uint32_t offset,
@@ -3650,7 +3675,7 @@ static void fx_parse_fx_2_initial_value(struct fx_parser *parser, uint32_t param
             fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_NOT_IMPLEMENTED,
                     "Parsing sampler initializers is not supported.");
         else
-            parse_fx_2_object_value(parser, var.element_count, value);
+            parse_fx_2_object_value(parser, var.element_count, var.type, value);
     }
     else
     {
@@ -3833,9 +3858,54 @@ static void fx_2_parse_parameters(struct fx_parser *parser, uint32_t count)
         vkd3d_string_buffer_printf(&parser->buffer, "\n");
 }
 
+static void fx_parse_fx_2_data_blob(struct fx_parser *parser)
+{
+    uint32_t id, size;
+    const char *str;
+
+    id = fx_parser_read_u32(parser);
+    size = fx_parser_read_u32(parser);
+
+    parse_fx_print_indent(parser);
+    if (id < parser->objects.count)
+    {
+        uint32_t type = parser->objects.types[id];
+        switch (type)
+        {
+            case D3DXPT_STRING:
+            case D3DXPT_TEXTURE:
+            case D3DXPT_TEXTURE1D:
+            case D3DXPT_TEXTURE2D:
+            case D3DXPT_TEXTURE3D:
+            case D3DXPT_TEXTURECUBE:
+            case D3DXPT_PIXELSHADER:
+            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)
+                {
+                    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);
+                }
+                break;
+            default:
+                vkd3d_string_buffer_printf(&parser->buffer, "<type%u> object %u size %u bytes\n", type, id, size);
+        }
+    }
+    else
+    {
+        vkd3d_string_buffer_printf(&parser->buffer, "object %u - out-of-range id\n", id);
+    }
+
+    fx_parser_skip(parser, align(size, 4));
+}
+
 static void fx_2_parse(struct fx_parser *parser)
 {
-    uint32_t i, size, parameter_count, technique_count;
+    uint32_t i, size, parameter_count, technique_count, blob_count;
 
     fx_parser_skip(parser, sizeof(uint32_t)); /* Version */
     size = fx_parser_read_u32(parser);
@@ -3848,11 +3918,27 @@ static void fx_2_parse(struct fx_parser *parser)
     parameter_count = fx_parser_read_u32(parser);
     technique_count = fx_parser_read_u32(parser);
     fx_parser_read_u32(parser); /* Shader count */
-    fx_parser_read_u32(parser); /* Object count */
+    parser->objects.count = fx_parser_read_u32(parser);
+
+    if (!(parser->objects.types = calloc(parser->objects.count, sizeof(*parser->objects.types))))
+    {
+        fx_parser_error(parser, VKD3D_SHADER_ERROR_FX_OUT_OF_MEMORY, "Out of memory.");
+        return;
+    }
 
     fx_2_parse_parameters(parser, parameter_count);
     for (i = 0; i < technique_count; ++i)
         fx_parse_fx_2_technique(parser);
+
+    blob_count = fx_parser_read_u32(parser);
+    fx_parser_read_u32(parser); /* Resource count */
+
+    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");
 }
 
 static const char *fx_4_get_string(struct fx_parser *parser, uint32_t offset)
@@ -4982,19 +5068,29 @@ static void fx_5_parse(struct fx_parser *parser)
     fx_parse_groups(parser);
 }
 
+static void fx_parser_init(struct fx_parser *parser, const struct vkd3d_shader_compile_info *compile_info,
+        struct vkd3d_shader_message_context *message_context)
+{
+    memset(parser, 0, sizeof(*parser));
+    parser->start = compile_info->source.code;
+    parser->ptr = compile_info->source.code;
+    parser->end = (uint8_t *)compile_info->source.code + compile_info->source.size;
+    parser->message_context = message_context;
+    vkd3d_string_buffer_init(&parser->buffer);
+}
+
+static void fx_parser_cleanup(struct fx_parser *parser)
+{
+    free(parser->objects.types);
+}
+
 int fx_parse(const struct vkd3d_shader_compile_info *compile_info,
         struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
 {
-    struct fx_parser parser =
-    {
-        .start = compile_info->source.code,
-        .ptr = compile_info->source.code,
-        .end = (uint8_t *)compile_info->source.code + compile_info->source.size,
-        .message_context = message_context,
-    };
+    struct fx_parser parser;
     uint32_t version;
 
-    vkd3d_string_buffer_init(&parser.buffer);
+    fx_parser_init(&parser, compile_info, message_context);
 
     if (parser.end - parser.start < sizeof(version))
     {
@@ -5023,6 +5119,7 @@ int fx_parse(const struct vkd3d_shader_compile_info *compile_info,
     }
 
     vkd3d_shader_code_from_string_buffer(out, &parser.buffer);
+    fx_parser_cleanup(&parser);
 
     if (parser.failed)
         return VKD3D_ERROR_INVALID_SHADER;
diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h
index 3fe5959f2..0c21a41af 100644
--- a/libs/vkd3d-shader/vkd3d_shader_private.h
+++ b/libs/vkd3d-shader/vkd3d_shader_private.h
@@ -264,6 +264,7 @@ enum vkd3d_shader_error
     VKD3D_SHADER_ERROR_FX_INVALID_VERSION               = 11001,
     VKD3D_SHADER_ERROR_FX_INVALID_DATA                  = 11002,
     VKD3D_SHADER_ERROR_FX_INVALID_SIZE                  = 11003,
+    VKD3D_SHADER_ERROR_FX_OUT_OF_MEMORY                 = 11004,
 };
 
 enum vkd3d_shader_opcode
-- 
GitLab