[PATCH 6/6] d3dx9: Merge constant setting for child parameters when possible.

Paul Gofman gofmanp at gmail.com
Wed May 24 04:46:56 CDT 2017


Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
 dlls/d3dx9_36/d3dx9_private.h |   1 +
 dlls/d3dx9_36/preshader.c     | 163 ++++++++++++++++++++++++++++++++----------
 2 files changed, 126 insertions(+), 38 deletions(-)

diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h
index ccb8e8a..8eb12b7 100644
--- a/dlls/d3dx9_36/d3dx9_private.h
+++ b/dlls/d3dx9_36/d3dx9_private.h
@@ -155,6 +155,7 @@ struct d3dx_const_param_eval_output
     unsigned int register_index;
     unsigned int register_count;
     BOOL direct_copy;
+    unsigned int element_count;
 };
 
 struct d3dx_const_tab
diff --git a/dlls/d3dx9_36/preshader.c b/dlls/d3dx9_36/preshader.c
index 55063b2..b77e83c 100644
--- a/dlls/d3dx9_36/preshader.c
+++ b/dlls/d3dx9_36/preshader.c
@@ -1035,10 +1035,11 @@ static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const
         unsigned int table = const_set->table;
         struct d3dx_parameter *param = const_set->param;
         enum pres_value_type table_type = table_info[table].type;
-        unsigned int i, j, n, start_offset;
+        unsigned int element, i, j, n, start_offset;
         unsigned int minor, major, major_stride, param_offset;
         BOOL transpose;
         unsigned int count;
+        unsigned int *data = param->data;
 
         if (!is_param_dirty(param, const_tab->update_version))
             continue;
@@ -1046,50 +1047,54 @@ static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const
         start_offset = get_offset_reg(table, const_set->register_index);
         if (const_set->direct_copy)
         {
-            regstore_set_values(rs, table, param->data, start_offset,
+            regstore_set_values(rs, table, data, start_offset,
                     get_offset_reg(table, const_set->register_count));
             continue;
         }
         get_constant_dimensions(const_set, &transpose, &major, &minor, &major_stride, &n, &count);
-
-        for (i = 0; i < n; ++i)
+        for (element = 0; element < const_set->element_count; ++element)
         {
-            for (j = 0; j < minor; ++j)
+            for (i = 0; i < n; ++i)
             {
-                unsigned int out;
-                unsigned int *in;
-                unsigned int offset;
-
-                offset = start_offset + i * major_stride + j;
-                if (get_reg_offset(table, offset) >= rs->table_sizes[table])
-                {
-                    if (table != PRES_REGTAB_OBCONST)
-                        FIXME("Output offset exceeds table size, name %s, component %u.\n",
-                                debugstr_a(param->name), i);
-                    break;
-                }
-                if (transpose)
-                    param_offset = i + j * major;
-                else
-                    param_offset = i * minor + j;
-                if (param_offset * sizeof(unsigned int) >= param->bytes)
-                {
-                    WARN("Parameter data is too short, name %s, component %u.\n", debugstr_a(param->name), i);
-                    break;
-                }
-
-                in = (unsigned int *)param->data + param_offset;
-                switch (table_type)
+                for (j = 0; j < minor; ++j)
                 {
-                    case PRES_VT_FLOAT: set_number(&out, D3DXPT_FLOAT, in, param->type); break;
-                    case PRES_VT_INT: set_number(&out, D3DXPT_INT, in, param->type); break;
-                    case PRES_VT_BOOL: set_number(&out, D3DXPT_BOOL, in, param->type); break;
-                    default:
-                        FIXME("Unexpected type %#x.\n", table_info[table].type);
+                    unsigned int out;
+                    unsigned int *in;
+                    unsigned int offset;
+
+                    offset = start_offset + i * major_stride + j;
+                    if (get_reg_offset(table, offset) >= rs->table_sizes[table])
+                    {
+                        if (table != PRES_REGTAB_OBCONST)
+                            FIXME("Output offset exceeds table size, name %s, component %u.\n",
+                                    debugstr_a(param->name), i);
+                        break;
+                    }
+                    if (transpose)
+                        param_offset = i + j * major;
+                    else
+                        param_offset = i * minor + j;
+                    if (param_offset * sizeof(unsigned int) >= param->bytes)
+                    {
+                        WARN("Parameter data is too short, name %s, component %u.\n", debugstr_a(param->name), i);
                         break;
+                    }
+
+                    in = (unsigned int *)data + param_offset;
+                    switch (table_type)
+                    {
+                        case PRES_VT_FLOAT: set_number(&out, D3DXPT_FLOAT, in, param->type); break;
+                        case PRES_VT_INT: set_number(&out, D3DXPT_INT, in, param->type); break;
+                        case PRES_VT_BOOL: set_number(&out, D3DXPT_BOOL, in, param->type); break;
+                        default:
+                            FIXME("Unexpected type %#x.\n", table_info[table].type);
+                            break;
+                    }
+                    regstore_set_values(rs, table, &out, offset, 1);
                 }
-                regstore_set_values(rs, table, &out, offset, 1);
             }
+            start_offset += get_offset_reg(table, const_set->register_count);
+            data += param->rows * param->columns;
         }
     }
     const_tab->update_version = new_update_version;
@@ -1132,6 +1137,85 @@ static HRESULT append_const_set(struct d3dx_const_tab *const_tab, struct d3dx_co
     return D3D_OK;
 }
 
+static HRESULT merge_const_set_entries(struct d3dx_const_tab *const_tab,
+        struct d3dx_parameter *param, unsigned int index)
+{
+    unsigned int i, start_index = index;
+    DWORD *current_data;
+    enum pres_reg_tables current_table;
+    unsigned int current_start_offset, element_count;
+    struct d3dx_const_param_eval_output *first_const;
+
+    if (!const_tab->const_set_count)
+        return D3D_OK;
+
+    while (index < const_tab->const_set_count - 1)
+    {
+        first_const = &const_tab->const_set[index];
+        current_data = first_const->param->data;
+        current_table = first_const->table;
+        current_start_offset = get_offset_reg(current_table, first_const->register_index);
+        element_count = 0;
+        for (i = index; i < const_tab->const_set_count; ++i)
+        {
+            struct d3dx_const_param_eval_output *const_set = &const_tab->const_set[i];
+            unsigned int count = get_offset_reg(const_set->table,
+                    const_set->register_count * const_set->element_count);
+            unsigned int start_offset = get_offset_reg(const_set->table, const_set->register_index);
+
+            if (!(const_set->table == current_table && current_start_offset == start_offset
+                    && const_set->direct_copy == first_const->direct_copy
+                    && current_data == const_set->param->data
+                    && (const_set->direct_copy || (first_const->param->type == const_set->param->type
+                    && first_const->param->class == const_set->param->class
+                    && first_const->param->columns == const_set->param->columns
+                    && first_const->param->rows == const_set->param->rows
+                    && first_const->register_count == const_set->register_count
+                    && (i == const_tab->const_set_count - 1
+                    || first_const->param->element_count == const_set->param->element_count)))))
+            {
+                TRACE("direct_copy %u, i %u, index %u, param %s.%s, current_data %p, const_set->param->data %p, "\
+                        "current_start_offset %u, start_offset %u, const_set->table %u, current_table %u.\n",
+                        const_set->direct_copy, i, index, debugstr_a(param->name),
+                        debugstr_a(const_set->param->name), current_data, const_set->param->data,
+                        current_start_offset, start_offset, const_set->table, current_table);
+                break;
+            }
+
+            current_start_offset += count;
+            current_data += const_set->direct_copy ? count : const_set->param->rows
+                    * const_set->param->columns * const_set->element_count;
+            element_count += const_set->element_count;
+        }
+
+        TRACE("Merging %u child parameters for %s, not merging %u, direct_copy %u.\n", i - index,
+                debugstr_a(param->name), const_tab->const_set_count - i, first_const->direct_copy);
+
+        if (i > index + 1)
+        {
+            first_const->element_count = element_count;
+            if (first_const->direct_copy)
+            {
+                first_const->element_count = 1;
+                if (index == start_index
+                        && !(param->type == D3DXPT_VOID && param->class == D3DXPC_STRUCT))
+                {
+                    if (param_type_to_table_type(param->type) == PRES_VT_MAX)
+                        return D3DERR_INVALIDCALL;
+                    first_const->param = param;
+                }
+                first_const->register_count = get_reg_offset(current_table, current_start_offset)
+                        - first_const->register_index;
+            }
+            memmove(&const_tab->const_set[index + 1], &const_tab->const_set[i],
+                    sizeof(*const_tab->const_set) * (const_tab->const_set_count - i));
+            const_tab->const_set_count -= i - index - 1;
+        }
+        index = i;
+    }
+    return D3D_OK;
+}
+
 static HRESULT init_set_constants_param(struct d3dx_const_tab *const_tab, ID3DXConstantTable *ctab,
         D3DXHANDLE hc, struct d3dx_parameter *param)
 {
@@ -1172,10 +1256,10 @@ static HRESULT init_set_constants_param(struct d3dx_const_tab *const_tab, ID3DXC
     }
     if (const_count)
     {
-        HRESULT ret;
+        HRESULT ret = D3D_OK;
         D3DXHANDLE hc_element;
+        unsigned int index = const_tab->const_set_count;
 
-        ret = D3D_OK;
         for (i = 0; i < const_count; ++i)
         {
             if (get_element)
@@ -1194,7 +1278,9 @@ static HRESULT init_set_constants_param(struct d3dx_const_tab *const_tab, ID3DXC
             if (FAILED(hr))
                 ret = hr;
         }
-        return ret;
+        if (FAILED(ret))
+            return ret;
+        return merge_const_set_entries(const_tab, param, index);
     }
 
     TRACE("Constant %s, rows %u, columns %u, class %u, bytes %u.\n",
@@ -1203,6 +1289,7 @@ static HRESULT init_set_constants_param(struct d3dx_const_tab *const_tab, ID3DXC
             debugstr_a(param->name), param->rows, param->columns, param->class,
             param->flags, param->bytes);
 
+    const_set.element_count = 1;
     const_set.param = param;
     const_set.constant_class = desc.Class;
     if (desc.RegisterSet >= ARRAY_SIZE(shad_regset2table))
-- 
2.9.3




More information about the wine-patches mailing list