d3dx9: Use versioned parameter updates instead of 'dirty' flags.

Signed-off-by: Paul Gofman <gofmanp@gmail.com>
Signed-off-by: Matteo Bruni <mbruni@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2017-05-16 19:49:17 +03:00 committed by Alexandre Julliard
parent a100d6a7a5
commit a179584844
3 changed files with 87 additions and 53 deletions

View File

@ -163,6 +163,7 @@ struct d3dx_const_tab
unsigned int const_set_size; unsigned int const_set_size;
struct d3dx_const_param_eval_output *const_set; struct d3dx_const_param_eval_output *const_set;
const enum pres_reg_tables *regset2table; const enum pres_reg_tables *regset2table;
ULONG64 update_version;
}; };
struct d3dx_regstore struct d3dx_regstore
@ -190,9 +191,9 @@ struct d3dx_param_eval
struct d3dx_preshader pres; struct d3dx_preshader pres;
struct d3dx_const_tab shader_inputs; struct d3dx_const_tab shader_inputs;
};
#define PARAMETER_FLAG_DIRTY 0x1u ULONG64 *version_counter;
};
struct d3dx_shared_data; struct d3dx_shared_data;
@ -211,8 +212,9 @@ struct d3dx_parameter
UINT member_count; UINT member_count;
DWORD flags; DWORD flags;
UINT bytes; UINT bytes;
DWORD runtime_flags;
DWORD object_id; DWORD object_id;
ULONG64 update_version;
ULONG64 *version_counter;
struct d3dx_parameter *annotations; struct d3dx_parameter *annotations;
struct d3dx_parameter *members; struct d3dx_parameter *members;
@ -227,13 +229,31 @@ struct d3dx_parameter
} u; } 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; struct d3dx9_base_effect;
static inline ULONG64 next_update_version(ULONG64 *version_counter)
{
return ++*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 *get_parameter_by_name(struct d3dx9_base_effect *base,
struct d3dx_parameter *parameter, const char *name) DECLSPEC_HIDDEN; struct d3dx_parameter *parameter, const char *name) DECLSPEC_HIDDEN;
@ -242,10 +262,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) #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, 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 *version_counter) DECLSPEC_HIDDEN;
void d3dx_free_param_eval(struct d3dx_param_eval *peval) DECLSPEC_HIDDEN; void d3dx_free_param_eval(struct d3dx_param_eval *peval) DECLSPEC_HIDDEN;
HRESULT d3dx_evaluate_parameter(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) DECLSPEC_HIDDEN; const struct d3dx_parameter *param, void *param_value) DECLSPEC_HIDDEN;
HRESULT d3dx_param_eval_set_shader_constants(ID3DXEffectStateManager *manager, struct IDirect3DDevice9 *device, HRESULT d3dx_param_eval_set_shader_constants(ID3DXEffectStateManager *manager, struct IDirect3DDevice9 *device,
struct d3dx_param_eval *peval, BOOL update_all) DECLSPEC_HIDDEN; struct d3dx_param_eval *peval, BOOL update_all) DECLSPEC_HIDDEN;
BOOL is_param_eval_input_dirty(struct d3dx_param_eval *peval) DECLSPEC_HIDDEN; BOOL is_param_eval_input_dirty(struct d3dx_param_eval *peval) DECLSPEC_HIDDEN;

View File

@ -127,6 +127,8 @@ struct d3dx_pass
struct d3dx_state *states; struct d3dx_state *states;
struct d3dx_parameter *annotations; struct d3dx_parameter *annotations;
ULONG64 update_version;
}; };
struct d3dx_technique struct d3dx_technique
@ -155,6 +157,8 @@ struct d3dx9_base_effect
struct d3dx_effect_pool *pool; struct d3dx_effect_pool *pool;
DWORD flags; DWORD flags;
ULONG64 version_counter;
}; };
struct ID3DXEffectImpl struct ID3DXEffectImpl
@ -180,13 +184,6 @@ struct ID3DXEffectImpl
#define INITIAL_SHARED_DATA_SIZE 4 #define INITIAL_SHARED_DATA_SIZE 4
struct d3dx_shared_data
{
void *data;
struct d3dx_parameter **parameters;
unsigned int size, count;
};
struct d3dx_effect_pool struct d3dx_effect_pool
{ {
ID3DXEffectPool ID3DXEffectPool_iface; ID3DXEffectPool ID3DXEffectPool_iface;
@ -194,6 +191,8 @@ struct d3dx_effect_pool
struct d3dx_shared_data *shared_data; struct d3dx_shared_data *shared_data;
unsigned int size; unsigned int size;
ULONG64 version_counter;
}; };
struct ID3DXEffectCompilerImpl struct ID3DXEffectCompilerImpl
@ -1033,7 +1032,7 @@ static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_sta
{ {
case ST_PARAMETER: case ST_PARAMETER:
param = param->u.referenced_param; param = param->u.referenced_param;
*param_dirty = is_param_dirty(param); *param_dirty = is_param_dirty(param, pass->update_version);
/* fallthrough */ /* fallthrough */
case ST_CONSTANT: case ST_CONSTANT:
*out_param = param; *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 (update_all || is_param_eval_input_dirty(param->param_eval))
{ {
if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param, if (FAILED(hr = d3dx_evaluate_parameter(param->param_eval, &array_idx_param, &array_idx)))
&array_idx, update_all)))
return hr; return hr;
} }
else else
@ -1073,7 +1071,7 @@ static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_sta
return E_FAIL; return E_FAIL;
} }
selected_param = &ref_param->members[array_idx]; 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; state->index = array_idx;
*param_value = selected_param->data; *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)) if (update_all || is_param_eval_input_dirty(param->param_eval))
{ {
*param_dirty = TRUE; *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 else
return D3D_OK; return D3D_OK;
@ -1473,28 +1471,26 @@ static BOOL walk_parameter_tree(struct d3dx_parameter *param, walk_parameter_dep
return FALSE; return FALSE;
} }
static ULONG64 *get_version_counter_ptr(struct d3dx9_base_effect *base)
{
return base->pool ? &base->pool->version_counter : &base->version_counter;
}
static ULONG64 next_effect_update_version(struct d3dx9_base_effect *base)
{
return next_update_version(get_version_counter_ptr(base));
}
static void set_dirty(struct d3dx_parameter *param) static void set_dirty(struct d3dx_parameter *param)
{ {
struct d3dx_shared_data *shared_data; struct d3dx_shared_data *shared_data;
unsigned int i; struct d3dx_parameter *top_param = param->top_level_param;
ULONG64 new_update_version = next_update_version(top_param->version_counter);
if ((shared_data = param->top_level_param->u.shared_data)) if ((shared_data = top_param->u.shared_data))
{ shared_data->update_version = new_update_version;
for (i = 0; i < shared_data->count; ++i)
shared_data->parameters[i]->runtime_flags |= PARAMETER_FLAG_DIRTY;
}
else else
{ top_param->update_version = new_update_version;
param->top_level_param->runtime_flags |= PARAMETER_FLAG_DIRTY;
}
}
static void clear_dirty_params(struct d3dx9_base_effect *base)
{
unsigned int i;
for (i = 0; i < base->parameter_count; ++i)
base->parameters[i].runtime_flags &= ~PARAMETER_FLAG_DIRTY;
} }
static HRESULT set_string(char **param_data, const char *string) 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; unsigned int i;
HRESULT ret; HRESULT ret;
HRESULT hr; HRESULT hr;
ULONG64 new_update_version = next_effect_update_version(&effect->base_effect);
TRACE("effect %p, pass %p, state_count %u.\n", effect, pass, pass->state_count); 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; effect->material_updated = FALSE;
clear_dirty_params(&effect->base_effect); pass->update_version = new_update_version;
return ret; return ret;
} }
@ -5944,7 +5941,7 @@ static HRESULT d3dx9_parse_array_selector(struct d3dx9_base_effect *base, struct
if (string_size % sizeof(DWORD)) if (string_size % sizeof(DWORD))
FIXME("Unaligned string_size %u.\n", string_size); FIXME("Unaligned string_size %u.\n", string_size);
d3dx_create_param_eval(base, (DWORD *)(ptr + string_size) + 1, object->size - (string_size + sizeof(DWORD)), d3dx_create_param_eval(base, (DWORD *)(ptr + string_size) + 1, object->size - (string_size + sizeof(DWORD)),
D3DXPT_INT, &param->param_eval); D3DXPT_INT, &param->param_eval, get_version_counter_ptr(base));
ret = D3D_OK; ret = D3D_OK;
param = param->u.referenced_param; param = param->u.referenced_param;
if (param->type == D3DXPT_VERTEXSHADER || param->type == D3DXPT_PIXELSHADER) 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); TRACE("Creating preshader for object %u.\n", param->members[i].object_id);
object = &base->objects[param->members[i].object_id]; object = &base->objects[param->members[i].object_id];
d3dx_create_param_eval(base, object->data, object->size, param->type, &param->members[i].param_eval); d3dx_create_param_eval(base, object->data, object->size, param->type,
&param->members[i].param_eval, get_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))) if (FAILED(hr = d3dx9_create_object(base, object)))
return hr; return hr;
d3dx_create_param_eval(base, object->data, object->size, param->type, &param->param_eval); d3dx_create_param_eval(base, object->data, object->size, param->type,
&param->param_eval, get_version_counter_ptr(base));
} }
break; break;
@ -6086,7 +6085,8 @@ static HRESULT d3dx9_parse_resource(struct d3dx9_base_effect *base, const char *
state->type = ST_FXLC; state->type = ST_FXLC;
if (FAILED(hr = d3dx9_copy_data(base, param->object_id, ptr))) if (FAILED(hr = d3dx9_copy_data(base, param->object_id, ptr)))
return hr; return hr;
d3dx_create_param_eval(base, object->data, object->size, param->type, &param->param_eval); d3dx_create_param_eval(base, object->data, object->size, param->type,
&param->param_eval, get_version_counter_ptr(base));
break; break;
default: default:
@ -6113,7 +6113,7 @@ static HRESULT d3dx9_parse_resource(struct d3dx9_base_effect *base, const char *
if (!refpar->param_eval) if (!refpar->param_eval)
d3dx_create_param_eval(base, refobj->data, refobj->size, d3dx_create_param_eval(base, refobj->data, refobj->size,
refpar->type, &refpar->param_eval); refpar->type, &refpar->param_eval, get_version_counter_ptr(base));
} }
} }
else else
@ -6257,6 +6257,10 @@ static HRESULT d3dx9_parse_effect(struct d3dx9_base_effect *base, const char *da
goto err_out; goto err_out;
walk_parameter_tree(&base->parameters[i], param_set_top_level_param, walk_parameter_tree(&base->parameters[i], param_set_top_level_param,
&base->parameters[i]); &base->parameters[i]);
base->parameters[i].version_counter = base->pool
? &base->pool->version_counter
: &base->version_counter;
set_dirty(&base->parameters[i]);
} }
return D3D_OK; return D3D_OK;

View File

@ -813,7 +813,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, 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 *version_counter)
{ {
struct d3dx_param_eval *peval; struct d3dx_param_eval *peval;
unsigned int *ptr; unsigned int *ptr;
@ -836,6 +836,8 @@ void d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte_co
if (!peval) if (!peval)
goto err_out; goto err_out;
peval->version_counter = version_counter;
peval->param_type = type; peval->param_type = type;
switch (type) switch (type)
{ {
@ -934,7 +936,8 @@ void d3dx_free_param_eval(struct d3dx_param_eval *peval)
HeapFree(GetProcessHeap(), 0, 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; unsigned int const_idx;
@ -949,7 +952,7 @@ static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const
BOOL transpose; BOOL transpose;
unsigned int count; unsigned int count;
if (!(update_all || is_param_dirty(param))) if (!(update_all || is_param_dirty(param, const_tab->update_version)))
continue; continue;
transpose = (const_set->constant_class == D3DXPC_MATRIX_COLUMNS && param->class == D3DXPC_MATRIX_ROWS) transpose = (const_set->constant_class == D3DXPC_MATRIX_COLUMNS && param->class == D3DXPC_MATRIX_ROWS)
@ -1020,6 +1023,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 #define INITIAL_CONST_SET_SIZE 16
@ -1294,7 +1298,7 @@ static BOOL is_const_tab_input_dirty(struct d3dx_const_tab *ctab)
for (i = 0; i < ctab->const_set_count; ++i) 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 TRUE;
} }
return FALSE; return FALSE;
@ -1307,7 +1311,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, 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; HRESULT hr;
unsigned int i; unsigned int i;
@ -1316,10 +1320,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); 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,
next_update_version(peval->version_counter));
if (FAILED(hr = execute_preshader(&peval->pres))) if (FAILED(hr = execute_preshader(&peval->pres)))
return hr; return hr;
}
elements_table = table_info[PRES_REGTAB_OCONST].reg_component_count elements_table = table_info[PRES_REGTAB_OCONST].reg_component_count
* peval->pres.regs.table_sizes[PRES_REGTAB_OCONST]; * peval->pres.regs.table_sizes[PRES_REGTAB_OCONST];
@ -1414,17 +1422,18 @@ HRESULT d3dx_param_eval_set_shader_constants(ID3DXEffectStateManager *manager, s
struct d3dx_preshader *pres = &peval->pres; struct d3dx_preshader *pres = &peval->pres;
struct d3dx_regstore *rs = &pres->regs; struct d3dx_regstore *rs = &pres->regs;
unsigned int i; unsigned int i;
ULONG64 new_update_version = next_update_version(peval->version_counter);
TRACE("device %p, peval %p, param_type %u.\n", device, peval, peval->param_type); TRACE("device %p, peval %p, param_type %u.\n", device, peval, peval->param_type);
if (update_all || is_const_tab_input_dirty(&pres->inputs)) 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))) if (FAILED(hr = execute_preshader(pres)))
return hr; return hr;
} }
set_constants(rs, &peval->shader_inputs, update_all); set_constants(rs, &peval->shader_inputs, update_all, new_update_version);
result = D3D_OK; result = D3D_OK;
for (i = 0; i < ARRAY_SIZE(set_tables); ++i) for (i = 0; i < ARRAY_SIZE(set_tables); ++i)
{ {