[PATCH 3/6] d3dx9: Match native out of bounds array selector index handling.

Paul Gofman gofmanp at gmail.com
Mon May 15 16:25:38 CDT 2017


On 05/15/2017 09:21 PM, Matteo Bruni wrote:
> 2017-05-12 14:24 GMT+02:00 Paul Gofman <gofmanp at gmail.com>:
>
>> diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
>> index 9c07f9c..21aa5d7 100644
>> --- a/dlls/d3dx9_36/effect.c
>> +++ b/dlls/d3dx9_36/effect.c
>> @@ -1051,7 +1051,9 @@ static HRESULT d3dx9_get_param_value_ptr(struct d3dx_pass *pass, struct d3dx_sta
>>                   FIXME("Preshader structure is null.\n");
>>                   return D3DERR_INVALIDCALL;
>>               }
>> -            if (update_all || is_param_eval_input_dirty(param->param_eval))
>> +            /* According to the tests, native d3dx handles the case of array index evaluated to -1
>> +             * in a specific way. */
>> +            if (state->index == 0xffffffffu || is_param_eval_input_dirty(param->param_eval, pass->update_version))
> Hmm, so that's the index value set at initialization, thus getting a
> -1 in the first evaluation ends up breaking the "selector changed"
> check in native? You might want to spell that out in some form in the
> comment.
     Well, it now looks like a leftover, it looks like now with the 
current version of the patch when parameter evaluation is fully 
transactional and actual recompute does not depend on update_all flag, 
this check 'state->index == 0xffffffffu' is redundant and I can just 
remove it, it does not break any test. I think it was needed on some of 
my previous versions of patches.

     Now this part can be removed, it should be just
if (is_param_eval_input_dirty(param->param_eval))
...

     The check for array_idx == 0xffffffffu below is required though to 
match a special behaviour on -1 index value handling.

>
> AFAIU there is no other way a -1 is stored in state->index, correct?
>
>
There is the other way to get -1 to index selector, it can be computed 
by preshader with corresponding parameters values set, and it is in the 
test.

     The overall logic I could "interpolate" from the tests is:

1. Whenever BeginPass or GetPassDesc return a success while the actual 
index value should be out of bound, they return the value for previously 
computed "good" index;

2. Unlike BeginPass and GetPassDesc, CommitChanges never returns failure 
on out of bound index, though still does not set a state in the case 
when BeginPass would return an error. BeginPass and GetPassDesc can 
either return failulre or not with the same actual index value to be 
computed, depending on what was happening before.

3. Whenever index recompute is required (based on updated parameters), 
the out of bound check is performed and error is returned from BeginPass 
or GetPassDesc. When the recomputed index is out of bound stored index 
value is never updated.

4. When the index recompute is not required (there was BeginPass or 
CommitChanges since last index parameter update, even if it computed out 
of bound index), the array element corresponding to the previous ever 
successfully selected is used.

5. If the index value is '-1', first array element is selected, and no 
errors are returned in this case.

6. GetPassDesc() does not 'reset' the modified parameters, multiple 
successive calls to it consistently return failure. If the 'modified 
state' of index was reset by BeginPass() or CommitChanges(), 
GetPassDesc() will also return success with previous good selection, 
just like BeginPass().

     All this looks a bit like dragon poker to me, but now with 
transactional update logic just a special treatment of '-1' value and 
allowing a sort of bug not modifying previous index on out of bound 
compute seems to match all this.




More information about the wine-devel mailing list