diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h index 49c351f7be7..88914d84c15 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 *version_counter; +}; struct d3dx_shared_data; @@ -211,8 +212,9 @@ struct d3dx_parameter UINT member_count; DWORD flags; UINT bytes; - DWORD runtime_flags; DWORD object_id; + ULONG64 update_version; + ULONG64 *version_counter; struct d3dx_parameter *annotations; struct d3dx_parameter *members; @@ -227,13 +229,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 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 *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) 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; 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 30855a6320d..3b821a41935 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 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 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 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) { 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)) - { - for (i = 0; i < shared_data->count; ++i) - shared_data->parameters[i]->runtime_flags |= PARAMETER_FLAG_DIRTY; - } + if ((shared_data = top_param->u.shared_data)) + shared_data->update_version = new_update_version; else - { - 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; + 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 = next_effect_update_version(&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_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_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_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_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_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].version_counter = base->pool + ? &base->pool->version_counter + : &base->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 bd934af4b5a..5de74db7f05 100644 --- a/dlls/d3dx9_36/preshader.c +++ b/dlls/d3dx9_36/preshader.c @@ -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, - 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; unsigned int *ptr; @@ -836,6 +836,8 @@ void d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte_co if (!peval) goto err_out; + peval->version_counter = version_counter; + peval->param_type = type; switch (type) { @@ -934,7 +936,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; @@ -949,7 +952,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) @@ -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 @@ -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) { - 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; @@ -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, - void *param_value, BOOL update_all) + void *param_value) { HRESULT hr; 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); - 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))) - 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]; @@ -1414,17 +1422,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 = next_update_version(peval->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) {