[PATCH 2/6] d3dx9: Use versioned parameter updates instead of 'dirty' flags.
Paul Gofman
gofmanp at gmail.com
Fri May 12 07:24:13 CDT 2017
Looping through shared parameters in set_dirty() which is removed by this patch
has a major performance impact on parameter update for applications creating a
lot of effects and sharing parameters between them, which is a common case.
Using versioned scheme also allows for some further optimization.
Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
dlls/d3dx9_36/d3dx9_private.h | 36 +++++++++++++++++-----
dlls/d3dx9_36/effect.c | 72 +++++++++++++++++++++++--------------------
dlls/d3dx9_36/preshader.c | 29 +++++++++++------
3 files changed, 86 insertions(+), 51 deletions(-)
diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h
index 49c351f..587ffff 100644
--- a/dlls/d3dx9_36/d3dx9_private.h
+++ b/dlls/d3dx9_36/d3dx9_private.h
@@ -163,6 +163,7 @@ struct d3dx_const_tab
unsigned int const_set_size;
struct d3dx_const_param_eval_output *const_set;
const enum pres_reg_tables *regset2table;
+ ULONG64 update_version;
};
struct d3dx_regstore
@@ -190,9 +191,9 @@ struct d3dx_param_eval
struct d3dx_preshader pres;
struct d3dx_const_tab shader_inputs;
-};
-#define PARAMETER_FLAG_DIRTY 0x1u
+ ULONG64 *update_version_counter;
+};
struct d3dx_shared_data;
@@ -213,6 +214,8 @@ struct d3dx_parameter
UINT bytes;
DWORD runtime_flags;
DWORD object_id;
+ ULONG64 update_version;
+ ULONG64 *update_version_counter;
struct d3dx_parameter *annotations;
struct d3dx_parameter *members;
@@ -227,13 +230,31 @@ struct d3dx_parameter
} u;
};
-static inline BOOL is_param_dirty(struct d3dx_parameter *param)
+struct d3dx_shared_data
{
- return param->top_level_param->runtime_flags & PARAMETER_FLAG_DIRTY;
-}
+ void *data;
+ struct d3dx_parameter **parameters;
+ unsigned int size, count;
+ ULONG64 update_version;
+};
struct d3dx9_base_effect;
+static inline ULONG64 get_update_version_counter(ULONG64 *update_version_counter)
+{
+ return ++*update_version_counter;
+}
+
+static inline BOOL is_param_dirty(struct d3dx_parameter *param, ULONG64 update_version)
+{
+ struct d3dx_shared_data *shared_data;
+
+ if ((shared_data = param->top_level_param->u.shared_data))
+ return update_version < shared_data->update_version;
+ else
+ return update_version < param->top_level_param->update_version;
+}
+
struct d3dx_parameter *get_parameter_by_name(struct d3dx9_base_effect *base,
struct d3dx_parameter *parameter, const char *name) DECLSPEC_HIDDEN;
@@ -242,10 +263,11 @@ struct d3dx_parameter *get_parameter_by_name(struct d3dx9_base_effect *base,
#define SET_D3D_STATE(base_effect, args...) SET_D3D_STATE_(base_effect->manager, base_effect->device, args)
void d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte_code,
- unsigned int byte_code_size, D3DXPARAMETER_TYPE type, struct d3dx_param_eval **peval) DECLSPEC_HIDDEN;
+ unsigned int byte_code_size, D3DXPARAMETER_TYPE type,
+ struct d3dx_param_eval **peval, ULONG64 *update_version_counter) DECLSPEC_HIDDEN;
void d3dx_free_param_eval(struct d3dx_param_eval *peval) DECLSPEC_HIDDEN;
HRESULT d3dx_evaluate_parameter(struct d3dx_param_eval *peval,
- const struct d3dx_parameter *param, void *param_value, BOOL update_all) DECLSPEC_HIDDEN;
+ const struct d3dx_parameter *param, void *param_value) DECLSPEC_HIDDEN;
HRESULT d3dx_param_eval_set_shader_constants(ID3DXEffectStateManager *manager, struct IDirect3DDevice9 *device,
struct d3dx_param_eval *peval, BOOL update_all) DECLSPEC_HIDDEN;
BOOL is_param_eval_input_dirty(struct d3dx_param_eval *peval) DECLSPEC_HIDDEN;
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
index 30855a6..9c07f9c 100644
--- a/dlls/d3dx9_36/effect.c
+++ b/dlls/d3dx9_36/effect.c
@@ -127,6 +127,8 @@ struct d3dx_pass
struct d3dx_state *states;
struct d3dx_parameter *annotations;
+
+ ULONG64 update_version;
};
struct d3dx_technique
@@ -155,6 +157,8 @@ struct d3dx9_base_effect
struct d3dx_effect_pool *pool;
DWORD flags;
+
+ ULONG64 update_version_counter;
};
struct ID3DXEffectImpl
@@ -180,13 +184,6 @@ struct ID3DXEffectImpl
#define INITIAL_SHARED_DATA_SIZE 4
-struct d3dx_shared_data
-{
- void *data;
- struct d3dx_parameter **parameters;
- unsigned int size, count;
-};
-
struct d3dx_effect_pool
{
ID3DXEffectPool ID3DXEffectPool_iface;
@@ -194,6 +191,8 @@ struct d3dx_effect_pool
struct d3dx_shared_data *shared_data;
unsigned int size;
+
+ ULONG64 update_version_counter;
};
struct ID3DXEffectCompilerImpl
@@ -1033,7 +1032,7 @@ static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_sta
{
case ST_PARAMETER:
param = param->u.referenced_param;
- *param_dirty = is_param_dirty(param);
+ *param_dirty = is_param_dirty(param, pass->update_version);
/* fallthrough */
case ST_CONSTANT:
*out_param = param;
@@ -1054,8 +1053,7 @@ static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_sta
}
if (update_all || is_param_eval_input_dirty(param->param_eval))
{
- if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param,
- &array_idx, update_all)))
+ if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param, &array_idx)))
return hr;
}
else
@@ -1073,7 +1071,7 @@ static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_sta
return E_FAIL;
}
selected_param = &ref_param->members[array_idx];
- *param_dirty = state->index != array_idx || is_param_dirty(selected_param);
+ *param_dirty = state->index != array_idx || is_param_dirty(selected_param, pass->update_version);
state->index = array_idx;
*param_value = selected_param->data;
@@ -1088,7 +1086,7 @@ static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_sta
if (update_all || is_param_eval_input_dirty(param->param_eval))
{
*param_dirty = TRUE;
- return d3dx_evaluate_parameter(param->param_eval, param, *param_value, update_all);
+ return d3dx_evaluate_parameter(param->param_eval, param, *param_value);
}
else
return D3D_OK;
@@ -1473,28 +1471,26 @@ static BOOL walk_parameter_tree(struct d3dx_parameter *param, walk_parameter_dep
return FALSE;
}
-static void set_dirty(struct d3dx_parameter *param)
+static ULONG64 *get_update_version_counter_ptr(struct d3dx9_base_effect *base)
{
- struct d3dx_shared_data *shared_data;
- unsigned int i;
+ return base->pool ? &base->pool->update_version_counter : &base->update_version_counter;
+}
- if ((shared_data = param->top_level_param->u.shared_data))
- {
- for (i = 0; i < shared_data->count; ++i)
- shared_data->parameters[i]->runtime_flags |= PARAMETER_FLAG_DIRTY;
- }
- else
- {
- param->top_level_param->runtime_flags |= PARAMETER_FLAG_DIRTY;
- }
+static ULONG64 get_effect_update_version_counter(struct d3dx9_base_effect *base)
+{
+ return get_update_version_counter(get_update_version_counter_ptr(base));
}
-static void clear_dirty_params(struct d3dx9_base_effect *base)
+static void set_dirty(struct d3dx_parameter *param)
{
- unsigned int i;
+ struct d3dx_shared_data *shared_data;
+ struct d3dx_parameter *top_param = param->top_level_param;
+ ULONG64 new_update_version = get_update_version_counter(top_param->update_version_counter);
- for (i = 0; i < base->parameter_count; ++i)
- base->parameters[i].runtime_flags &= ~PARAMETER_FLAG_DIRTY;
+ if ((shared_data = top_param->u.shared_data))
+ shared_data->update_version = new_update_version;
+ else
+ top_param->update_version = new_update_version;
}
static HRESULT set_string(char **param_data, const char *string)
@@ -3078,6 +3074,7 @@ static HRESULT d3dx9_apply_pass_states(struct ID3DXEffectImpl *effect, struct d3
unsigned int i;
HRESULT ret;
HRESULT hr;
+ ULONG64 new_update_version = get_effect_update_version_counter(&effect->base_effect);
TRACE("effect %p, pass %p, state_count %u.\n", effect, pass, pass->state_count);
@@ -3109,7 +3106,7 @@ static HRESULT d3dx9_apply_pass_states(struct ID3DXEffectImpl *effect, struct d3
}
effect->material_updated = FALSE;
- clear_dirty_params(&effect->base_effect);
+ pass->update_version = new_update_version;
return ret;
}
@@ -5944,7 +5941,7 @@ static HRESULT d3dx9_parse_array_selector(struct d3dx9_base_effect *base, struct
if (string_size % sizeof(DWORD))
FIXME("Unaligned string_size %u.\n", string_size);
d3dx_create_param_eval(base, (DWORD *)(ptr + string_size) + 1, object->size - (string_size + sizeof(DWORD)),
- D3DXPT_INT, ¶m->param_eval);
+ D3DXPT_INT, ¶m->param_eval, get_update_version_counter_ptr(base));
ret = D3D_OK;
param = param->u.referenced_param;
if (param->type == D3DXPT_VERTEXSHADER || param->type == D3DXPT_PIXELSHADER)
@@ -5962,7 +5959,8 @@ static HRESULT d3dx9_parse_array_selector(struct d3dx9_base_effect *base, struct
{
TRACE("Creating preshader for object %u.\n", param->members[i].object_id);
object = &base->objects[param->members[i].object_id];
- d3dx_create_param_eval(base, object->data, object->size, param->type, ¶m->members[i].param_eval);
+ d3dx_create_param_eval(base, object->data, object->size, param->type,
+ ¶m->members[i].param_eval, get_update_version_counter_ptr(base));
}
}
}
@@ -6075,7 +6073,8 @@ static HRESULT d3dx9_parse_resource(struct d3dx9_base_effect *base, const char *
{
if (FAILED(hr = d3dx9_create_object(base, object)))
return hr;
- d3dx_create_param_eval(base, object->data, object->size, param->type, ¶m->param_eval);
+ d3dx_create_param_eval(base, object->data, object->size, param->type,
+ ¶m->param_eval, get_update_version_counter_ptr(base));
}
break;
@@ -6086,7 +6085,8 @@ static HRESULT d3dx9_parse_resource(struct d3dx9_base_effect *base, const char *
state->type = ST_FXLC;
if (FAILED(hr = d3dx9_copy_data(base, param->object_id, ptr)))
return hr;
- d3dx_create_param_eval(base, object->data, object->size, param->type, ¶m->param_eval);
+ d3dx_create_param_eval(base, object->data, object->size, param->type,
+ ¶m->param_eval, get_update_version_counter_ptr(base));
break;
default:
@@ -6113,7 +6113,7 @@ static HRESULT d3dx9_parse_resource(struct d3dx9_base_effect *base, const char *
if (!refpar->param_eval)
d3dx_create_param_eval(base, refobj->data, refobj->size,
- refpar->type, &refpar->param_eval);
+ refpar->type, &refpar->param_eval, get_update_version_counter_ptr(base));
}
}
else
@@ -6257,6 +6257,10 @@ static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *da
goto err_out;
walk_parameter_tree(&base->parameters[i], param_set_top_level_param,
&base->parameters[i]);
+ base->parameters[i].update_version_counter = base->pool
+ ? &base->pool->update_version_counter
+ : &base->update_version_counter;
+ set_dirty(&base->parameters[i]);
}
return D3D_OK;
diff --git a/dlls/d3dx9_36/preshader.c b/dlls/d3dx9_36/preshader.c
index fbd99ac..a35111b 100644
--- a/dlls/d3dx9_36/preshader.c
+++ b/dlls/d3dx9_36/preshader.c
@@ -809,7 +809,7 @@ static HRESULT parse_preshader(struct d3dx_preshader *pres, unsigned int *ptr, u
}
void d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte_code, unsigned int byte_code_size,
- D3DXPARAMETER_TYPE type, struct d3dx_param_eval **peval_out)
+ D3DXPARAMETER_TYPE type, struct d3dx_param_eval **peval_out, ULONG64 *update_version_counter)
{
struct d3dx_param_eval *peval;
unsigned int *ptr;
@@ -832,6 +832,8 @@ void d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte_co
if (!peval)
goto err_out;
+ peval->update_version_counter = update_version_counter;
+
peval->param_type = type;
switch (type)
{
@@ -930,7 +932,8 @@ void d3dx_free_param_eval(struct d3dx_param_eval *peval)
HeapFree(GetProcessHeap(), 0, peval);
}
-static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const_tab, BOOL update_all)
+static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const_tab,
+ BOOL update_all, ULONG64 new_update_version)
{
unsigned int const_idx;
@@ -945,7 +948,7 @@ static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const
BOOL transpose;
unsigned int count;
- if (!(update_all || is_param_dirty(param)))
+ if (!(update_all || is_param_dirty(param, const_tab->update_version)))
continue;
transpose = (const_set->constant_class == D3DXPC_MATRIX_COLUMNS && param->class == D3DXPC_MATRIX_ROWS)
@@ -1016,6 +1019,7 @@ static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const
}
}
}
+ const_tab->update_version = new_update_version;
}
#define INITIAL_CONST_SET_SIZE 16
@@ -1290,7 +1294,7 @@ static BOOL is_const_tab_input_dirty(struct d3dx_const_tab *ctab)
for (i = 0; i < ctab->const_set_count; ++i)
{
- if (is_param_dirty(ctab->const_set[i].param))
+ if (is_param_dirty(ctab->const_set[i].param, ctab->update_version))
return TRUE;
}
return FALSE;
@@ -1303,7 +1307,7 @@ BOOL is_param_eval_input_dirty(struct d3dx_param_eval *peval)
}
HRESULT d3dx_evaluate_parameter(struct d3dx_param_eval *peval, const struct d3dx_parameter *param,
- void *param_value, BOOL update_all)
+ void *param_value)
{
HRESULT hr;
unsigned int i;
@@ -1312,10 +1316,14 @@ HRESULT d3dx_evaluate_parameter(struct d3dx_param_eval *peval, const struct d3dx
TRACE("peval %p, param %p, param_value %p.\n", peval, param, param_value);
- set_constants(&peval->pres.regs, &peval->pres.inputs, update_all);
+ if (is_const_tab_input_dirty(&peval->pres.inputs))
+ {
+ set_constants(&peval->pres.regs, &peval->pres.inputs, FALSE,
+ get_update_version_counter(peval->update_version_counter));
- if (FAILED(hr = execute_preshader(&peval->pres)))
- return hr;
+ if (FAILED(hr = execute_preshader(&peval->pres)))
+ return hr;
+ }
elements_table = table_info[PRES_REGTAB_OCONST].reg_component_count
* peval->pres.regs.table_sizes[PRES_REGTAB_OCONST];
@@ -1410,17 +1418,18 @@ HRESULT d3dx_param_eval_set_shader_constants(ID3DXEffectStateManager *manager, s
struct d3dx_preshader *pres = &peval->pres;
struct d3dx_regstore *rs = &pres->regs;
unsigned int i;
+ ULONG64 new_update_version = get_update_version_counter(peval->update_version_counter);
TRACE("device %p, peval %p, param_type %u.\n", device, peval, peval->param_type);
if (update_all || is_const_tab_input_dirty(&pres->inputs))
{
- set_constants(rs, &pres->inputs, update_all);
+ set_constants(rs, &pres->inputs, update_all, new_update_version);
if (FAILED(hr = execute_preshader(pres)))
return hr;
}
- set_constants(rs, &peval->shader_inputs, update_all);
+ set_constants(rs, &peval->shader_inputs, update_all, new_update_version);
result = D3D_OK;
for (i = 0; i < ARRAY_SIZE(set_tables); ++i)
{
--
2.9.3
More information about the wine-patches
mailing list