[PATCH 01/10] d3dx9: Introduce a parameter rbtree to speed up get_parameter_by_name().
Matteo Bruni
mbruni at codeweavers.com
Tue Mar 20 17:37:26 CDT 2018
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
dlls/d3dx9_36/d3dx9_private.h | 12 ++++
dlls/d3dx9_36/effect.c | 156 ++++++++++++++++++++++++++++++++++++++----
2 files changed, 155 insertions(+), 13 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h
index 5ac5e63aeb6..2044b2af448 100644
--- a/dlls/d3dx9_36/d3dx9_private.h
+++ b/dlls/d3dx9_36/d3dx9_private.h
@@ -24,6 +24,8 @@
#define NONAMELESSUNION
#include "wine/debug.h"
+#include "wine/heap.h"
+#include "wine/rbtree.h"
#define COBJMACROS
#include "d3dx9.h"
@@ -278,6 +280,13 @@ struct d3dx_param_eval
ULONG64 *version_counter;
};
+struct param_rb_entry
+{
+ struct wine_rb_entry entry;
+ char *full_name;
+ struct d3dx_parameter *param;
+};
+
struct d3dx_shared_data;
struct d3dx_top_level_parameter;
@@ -300,6 +309,9 @@ struct d3dx_parameter
struct d3dx_parameter *members;
char *semantic;
+
+ char *full_name;
+ struct wine_rb_entry rb_entry;
};
struct d3dx_top_level_parameter
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
index 87eaf8684a9..340f3d3fd00 100644
--- a/dlls/d3dx9_36/effect.c
+++ b/dlls/d3dx9_36/effect.c
@@ -20,6 +20,8 @@
#include "config.h"
#include "wine/port.h"
+#include <stdio.h>
+
#include "d3dx9_private.h"
#include "d3dcompiler.h"
@@ -161,6 +163,10 @@ struct d3dx9_base_effect
DWORD flags;
ULONG64 version_counter;
+
+ struct wine_rb_tree param_tree;
+ char *full_name_tmp;
+ unsigned int full_name_tmp_size;
};
struct ID3DXEffectImpl
@@ -205,8 +211,8 @@ struct ID3DXEffectCompilerImpl
struct d3dx9_base_effect base_effect;
};
-static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_parameter *parameters,
- const char *name);
+static struct d3dx_parameter *get_annotation_by_name(struct d3dx9_base_effect *base,
+ unsigned int count, struct d3dx_parameter *parameters, const char *name);
static HRESULT d3dx9_parse_state(struct d3dx9_base_effect *base, struct d3dx_state *state,
const char *data, const char **ptr, struct d3dx_object *objects);
static void free_parameter(struct d3dx_parameter *param, BOOL element, BOOL child);
@@ -682,6 +688,8 @@ static void d3dx9_base_effect_cleanup(struct d3dx9_base_effect *base)
TRACE("base %p.\n", base);
+ heap_free(base->full_name_tmp);
+
if (base->parameters)
{
for (i = 0; i < base->parameter_count; ++i)
@@ -814,7 +822,8 @@ static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX
}
}
-static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_parameter *parameter, const char *name)
+static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx9_base_effect *base,
+ struct d3dx_parameter *parameter, const char *name)
{
UINT element;
struct d3dx_parameter *temp_parameter;
@@ -835,7 +844,7 @@ static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_paramete
switch (*part++)
{
case '.':
- return get_parameter_by_name(NULL, temp_parameter, part);
+ return get_parameter_by_name(base, temp_parameter, part);
case '\0':
TRACE("Returning parameter %p\n", temp_parameter);
@@ -851,8 +860,8 @@ static struct d3dx_parameter *get_parameter_element_by_name(struct d3dx_paramete
return NULL;
}
-static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_parameter *annotations,
- const char *name)
+static struct d3dx_parameter *get_annotation_by_name(struct d3dx9_base_effect *base,
+ unsigned int count, struct d3dx_parameter *annotations, const char *name)
{
UINT i, length;
struct d3dx_parameter *temp_parameter;
@@ -879,10 +888,10 @@ static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_par
switch (*part++)
{
case '.':
- return get_parameter_by_name(NULL, temp_parameter, part);
+ return get_parameter_by_name(base, temp_parameter, part);
case '[':
- return get_parameter_element_by_name(temp_parameter, part);
+ return get_parameter_element_by_name(base, temp_parameter, part);
default:
FIXME("Unhandled case \"%c\"\n", *--part);
@@ -898,15 +907,57 @@ static struct d3dx_parameter *get_annotation_by_name(UINT count, struct d3dx_par
struct d3dx_parameter *get_parameter_by_name(struct d3dx9_base_effect *base,
struct d3dx_parameter *parameter, const char *name)
{
- UINT i, count, length;
struct d3dx_parameter *temp_parameter;
+ unsigned int name_len, param_name_len;
+ unsigned int i, count, length;
+ struct wine_rb_entry *entry;
+ unsigned int full_name_size;
const char *part;
+ char *full_name;
TRACE("base %p, parameter %p, name %s\n", base, parameter, debugstr_a(name));
if (!name || !*name) return NULL;
+ if (!parameter)
+ {
+ if ((entry = wine_rb_get(&base->param_tree, name)))
+ return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
+ return NULL;
+ }
+
+ /* Pass / technique annotations are not in the parameters tree. */
+ if (parameter->full_name)
+ {
+ name_len = strlen(name);
+ param_name_len = strlen(parameter->full_name);
+ full_name_size = name_len + param_name_len + 2;
+ if (base->full_name_tmp_size < full_name_size)
+ {
+ if (!(full_name = heap_realloc(base->full_name_tmp, full_name_size)))
+ {
+ ERR("Out of memory.\n");
+ return NULL;
+ }
+ base->full_name_tmp = full_name;
+ base->full_name_tmp_size = full_name_size;
+ }
+ else
+ {
+ full_name = base->full_name_tmp;
+ }
+ memcpy(full_name, parameter->full_name, param_name_len);
+ full_name[param_name_len] = '.';
+ memcpy(full_name + param_name_len + 1, name, name_len);
+ full_name[param_name_len + 1 + name_len] = 0;
+
+ if ((entry = wine_rb_get(&base->param_tree, full_name)))
+ return WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
+ return NULL;
+ }
+
count = parameter ? parameter->member_count : base->parameter_count;
+
length = strcspn( name, "[.@" );
part = name + length;
@@ -925,18 +976,18 @@ struct d3dx_parameter *get_parameter_by_name(struct d3dx9_base_effect *base,
switch (*part++)
{
case '.':
- return get_parameter_by_name(NULL, temp_parameter, part);
+ return get_parameter_by_name(base, temp_parameter, part);
case '@':
{
struct d3dx_top_level_parameter *top_param
= top_level_parameter_from_parameter(temp_parameter);
- return parameter ? NULL : get_annotation_by_name(top_param->annotation_count,
+ return parameter ? NULL : get_annotation_by_name(base, top_param->annotation_count,
top_param->annotations, part);
}
case '[':
- return get_parameter_element_by_name(temp_parameter, part);
+ return get_parameter_element_by_name(base, temp_parameter, part);
default:
FIXME("Unhandled case \"%c\"\n", *--part);
@@ -1460,7 +1511,7 @@ static D3DXHANDLE d3dx9_base_effect_get_annotation_by_name(struct d3dx9_base_eff
annotation_count = get_annotation_from_object(base, object, &annotations);
- annotation = get_annotation_by_name(annotation_count, annotations, name);
+ annotation = get_annotation_by_name(base, annotation_count, annotations, name);
if (annotation)
{
TRACE("Returning parameter %p\n", annotation);
@@ -5436,6 +5487,83 @@ static void param_set_magic_number(struct d3dx_parameter *param)
memcpy(param->magic_string, parameter_magic_string, sizeof(parameter_magic_string));
}
+static int param_rb_compare(const void *key, const struct wine_rb_entry *entry)
+{
+ const char *name = key;
+ struct d3dx_parameter *param = WINE_RB_ENTRY_VALUE(entry, struct d3dx_parameter, rb_entry);
+
+ return strcmp(name, param->full_name);
+}
+
+static void add_param_to_tree(struct d3dx9_base_effect *base, struct d3dx_parameter *param,
+ struct d3dx_parameter *parent, char separator, unsigned int element)
+{
+ const char *parent_name = parent ? parent->full_name : NULL;
+ unsigned int i;
+
+ TRACE("Adding parameter %p (%s - parent %p, element %u) to the rbtree.\n",
+ param, debugstr_a(param->name), parent, element);
+
+ if (parent_name)
+ {
+ unsigned int parent_name_len = strlen(parent_name);
+ unsigned int name_len = strlen(param->name);
+ unsigned int part_str_len;
+ unsigned int len;
+ char part_str[16];
+
+ if (separator == '[')
+ {
+ sprintf(part_str, "[%u]", element);
+ part_str_len = strlen(part_str);
+ name_len = 0;
+ }
+ else
+ {
+ part_str[0] = separator;
+ part_str[1] = 0;
+ part_str_len = 1;
+ }
+ len = parent_name_len + part_str_len + name_len + 1;
+
+ if (!(param->full_name = heap_alloc(len)))
+ {
+ ERR("Out of memory.\n");
+ return;
+ }
+
+ memcpy(param->full_name, parent_name, parent_name_len);
+ memcpy(param->full_name + parent_name_len, part_str, part_str_len);
+ memcpy(param->full_name + parent_name_len + part_str_len, param->name, name_len);
+ param->full_name[len - 1] = 0;
+ }
+ else
+ {
+ unsigned int len = strlen(param->name) + 1;
+
+ if (!(param->full_name = heap_alloc(len)))
+ {
+ ERR("Out of memory.\n");
+ return;
+ }
+
+ memcpy(param->full_name, param->name, len);
+ }
+ TRACE("Full name is %s.\n", param->full_name);
+ wine_rb_put(&base->param_tree, param->full_name, ¶m->rb_entry);
+
+ if (is_top_level_parameter(param))
+ for (i = 0; i < param->top_level_param->annotation_count; ++i)
+ add_param_to_tree(base, ¶m->top_level_param->annotations[i], param, '@', 0);
+
+ if (param->element_count)
+ for (i = 0; i < param->element_count; ++i)
+ add_param_to_tree(base, ¶m->members[i], param, '[', i);
+ else
+ for (i = 0; i < param->member_count; ++i)
+ add_param_to_tree(base, ¶m->members[i], param, '.', 0);
+}
+
static HRESULT d3dx9_parse_effect_typedef(struct d3dx9_base_effect *base, struct d3dx_parameter *param,
const char *data, const char **ptr, struct d3dx_parameter *parent, UINT flags)
{
@@ -6281,6 +6409,7 @@ static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *da
goto err_out;
}
+ wine_rb_init(&base->param_tree, param_rb_compare);
if (base->parameter_count)
{
base->parameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
@@ -6303,6 +6432,7 @@ static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *da
}
walk_parameter_tree(&base->parameters[i].param, param_set_top_level_param,
&base->parameters[i]);
+ add_param_to_tree(base, &base->parameters[i].param, NULL, 0, 0);
}
}
--
2.13.6
More information about the wine-devel
mailing list