[PATCH 2/2] d3dx9: Get rid of constants modification bitmasks.

Matteo Bruni matteo.mystral at gmail.com
Mon Aug 28 13:00:26 CDT 2017


2017-08-10 12:02 GMT+02:00 Paul Gofman <gofmanp at gmail.com>:
> Signed-off-by: Paul Gofman <gofmanp at gmail.com>

The patch is fine overall, I only have a few questions / nitpicks.
I'll skip the part about the delay with the review because it's old
news by now... :/

> ---
>  dlls/d3dx9_36/d3dx9_private.h |   3 +-
>  dlls/d3dx9_36/preshader.c     | 312 ++++++++++++++++++------------------------
>  2 files changed, 135 insertions(+), 180 deletions(-)
>
> diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h
> index 2727463a18..5ac5e63aeb 100644
> --- a/dlls/d3dx9_36/d3dx9_private.h
> +++ b/dlls/d3dx9_36/d3dx9_private.h
> @@ -230,7 +230,7 @@ enum pres_reg_tables
>  struct d3dx_const_param_eval_output
>  {
>      struct d3dx_parameter *param;
> -    unsigned int table;
> +    enum pres_reg_tables table;

The change is good but (unrelated to this patch) the enum type should
really use the singular form.

>  static void dump_bytecode(void *data, unsigned int size)
> @@ -674,6 +614,40 @@ static HRESULT append_const_set(struct d3dx_const_tab *const_tab, struct d3dx_co
>      return D3D_OK;
>  }
>
> +static void append_pres_const_set(struct d3dx_const_tab *const_tab, struct d3dx_preshader *pres)

Nitpick: this function appends all the struct
d3dx_const_param_eval_output from the preshader so calling it
"append_pres_const_sets" (or even something more explicit to that
effect, e.g. clarifying that you're appending entries about the
preshader outputs, which are shader inputs) would be preferable.

> +{
> +    unsigned int i;
> +    struct d3dx_const_param_eval_output const_set;
> +
> +    memset(&const_set, 0, sizeof(const_set));

You could initialize const_set in the definition instead, like:

struct d3dx_const_param_eval_output const_set = {NULL};

which looks slightly better to me. It doesn't matter much of course.

> @@ -971,10 +946,30 @@ static HRESULT get_constants_desc(unsigned int *byte_code, struct d3dx_const_tab
>          if (FAILED(hr = init_set_constants_param(out, ctab, hc, inputs_param[index])))
>              goto cleanup;
>      }
> +    if (pres)
> +        append_pres_const_set(out, pres);
>      if (out->const_set_count)
>      {
>          struct d3dx_const_param_eval_output *new_alloc;
>
> +        qsort(out->const_set, out->const_set_count, sizeof(*out->const_set), compare_const_set);
> +        for (i = 0; i < out->const_set_count - 1; ++i)
> +        {
> +            if (out->const_set[i].constant_class == D3DXPC_FORCE_DWORD
> +                    && out->const_set[i + 1].constant_class == D3DXPC_FORCE_DWORD
> +                    && out->const_set[i].table == out->const_set[i + 1].table
> +                    && out->const_set[i].register_index + out->const_set[i].register_count
> +                    >= out->const_set[i + 1].register_index)
> +            {
> +                out->const_set[i].register_count = out->const_set[i + 1].register_index
> +                        + out->const_set[i + 1].register_count - out->const_set[i].register_index;

I think this might lose account of some registers. E.g. consider the
case where const_set[i] has register_index == 0 and register_count ==
4 while const_set[i + 1] has register_index == 1 and register_count ==
1. This would seem to lose track of the last two components.

I know that preshaders found in the wild seem not to overwrite already
written output registers but I wouldn't feel safe with (silently)
depending on it.

> +                memmove(&out->const_set[i + 1], &out->const_set[i + 2], sizeof(out->const_set[i])
> +                        * (out->const_set_count - i - 2));
> +                --out->const_set_count;
> +                --i;

Mostly matter of personal preference but rather than decrementing the
for counter in the if when coalescing I'd write this as a while and
increment "i" only in the (currently absent) else case.

> @@ -1529,22 +1534,56 @@ static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const
>              data += param->rows * param->columns;
>          }
>          start_offset = get_offset_reg(table, const_set->register_index);
> -        if (table_info[table].type == param_type)
> -            regstore_set_modified(rs, table, start_offset,
> -                    get_offset_reg(table, const_set->register_count) * const_set->element_count);
> -        else
> +        if (table_info[table].type != param_type)
>              regstore_set_data(rs, table, start_offset, (unsigned int *)rs->tables[table] + start_offset,
>                      get_offset_reg(table, const_set->register_count) * const_set->element_count, param_type);
>      }
> +
> +
>      const_tab->update_version = new_update_version;

One blank line too many.

> -}
> +    if (!update_device)
> +        return D3D_OK;
>
> +    for (const_idx = 0; const_idx < const_tab->const_set_count; ++const_idx)
> +    {
> +        struct d3dx_const_param_eval_output *const_set = &const_tab->const_set[const_idx];
> +
> +        if (device_update_all || (const_set->param
> +                ? is_param_dirty(const_set->param, update_version) : pres_dirty))
> +        {
> +            enum pres_reg_tables table = const_set->table;
> +
> +            if (table == device_table && device_start + device_count == const_set->register_index)

Again nitpicking: are there better names for those variables? Maybe
use the "current_" prefix instead? It's pretty clear what's going on
either way, so up to you.



More information about the wine-devel mailing list