2017-04-20 13:26 GMT+02:00 Paul Gofman <gofmanp(a)gmail.com>:
> Signed-off-by: Paul Gofman <gofmanp(a)gmail.com>
> ---
> dlls/d3dx9_36/d3dx9_private.h | 11 ++-
> dlls/d3dx9_36/effect.c | 197 +++++++++++++++++++++++++++++++++++++++++-
> dlls/d3dx9_36/tests/effect.c | 17 ++--
> 3 files changed, 211 insertions(+), 14 deletions(-)
>
> diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h
> index da4564d..d6d4280 100644
> --- a/dlls/d3dx9_36/d3dx9_private.h
> +++ b/dlls/d3dx9_36/d3dx9_private.h
> @@ -215,15 +215,22 @@ struct d3dx_parameter
> struct d3dx_parameter *annotations;
> struct d3dx_parameter *members;
>
> - struct d3dx_parameter *referenced_param;
> struct d3dx_param_eval *param_eval;
>
> struct d3dx_parameter *top_level_param;
> + union
> + {
> + struct d3dx_parameter *referenced_param;
> + struct d3dx_parameter *shared_param;
> + };
> + LONG shared_refcount;
> };
I think you mentioned this before but it shouldn't be necessary to
store the whole parameter structure in the pool.
I guess it could be improved after the fact but it shouldn't be too
complicated to do it right away. Probably it could just be
shared_param_list[] from patch 8/8 and shared_refcount (which at that
point won't need to be in struct d3dx_parameter anymore), in addition
to data. You could access the other parameter fields through
shared_param_list[0].
> +static void d3dx_pool_sync_shared_parameter(struct ID3DXEffectPoolImpl *pool, struct d3dx_parameter *param)
> +{
> + unsigned int i, free_entry_index;
> + LONG new_refcount;
> +
> + if (!(param->flags & PARAMETER_FLAG_SHARED) || !pool
> + || is_param_type_sampler(param->type))
> + return;
> +
> + free_entry_index = pool->parameter_count;
> + for (i = 0; i < pool->parameter_count; ++i)
> + {
> + if (!pool->parameters[i]->shared_refcount)
> + free_entry_index = i;
> + else if (is_same_parameter(param, pool->parameters[i]))
> + break;
> + }
> + if (i == pool->parameter_count)
> + {
> + i = free_entry_index;
> + if (i >= pool->table_size)
> + {
> + struct d3dx_parameter ** new_alloc;
No whitespace after "**", please.
> + else
> + {
> + new_size = pool->table_size * 2;
> + new_alloc = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pool->parameters,
> + sizeof(*pool->parameters) * new_size);
> + if (!new_alloc)
> + {
> + ERR("Out of memory.\n");
> + return;
> + }
> + }
> + pool->parameters = new_alloc;
> + pool->table_size = new_size;
> + }
> + pool->parameters[i] = HeapAlloc(GetProcessHeap(),
> + HEAP_ZERO_MEMORY, sizeof(*pool->parameters[i]));
> + copy_parameter_structure(param, pool->parameters[i], NULL, FALSE);
> + param_set_data_pointer(pool->parameters[i], (unsigned char *)param->data, FALSE, FALSE);
> + if (i == pool->parameter_count)
> + pool->parameter_count++;
> + }
I don't think this works. HeapReAlloc might move the memory block and
that would break the preexisting effects using the pool (and also the
previous parameters of the new effect). HEAP_REALLOC_IN_PLACE_ONLY
would avoid that but it also makes it easier for the reallocation to
fail.
I see two ways to fix this:
- refresh all the parameters of the effects that are in the pool when
you have to reallocate (shared_param_list[] might help here)
- allocate the memory in chunks, keeping an array (or list) of chunks
which you allocate (but never resize) as needed