[PATCH 1/2] d3dx9: Implement recording parameters to parameter block.

Matteo Bruni mbruni at codeweavers.com
Wed Nov 20 10:50:11 CST 2019


From: Paul Gofman <gofmanp at gmail.com>

Signed-off-by: Paul Gofman <gofmanp at gmail.com>
Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
After much deliberation, I renamed the "buffer accounting" fields in
struct d3dx_parameter_block and param_get_data_...(). I also got rid
of a bunch of unnecessary casts.

 dlls/d3dx9_36/effect.c       | 241 +++++++++++++++++++++++++----------
 dlls/d3dx9_36/tests/effect.c |  38 ++++--
 2 files changed, 204 insertions(+), 75 deletions(-)

diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
index a573d88fcf8..84e71cd1b71 100644
--- a/dlls/d3dx9_36/effect.c
+++ b/dlls/d3dx9_36/effect.c
@@ -36,6 +36,7 @@ static const char parameter_block_magic_string[4] = {'@', '!', '#', '\xFE'};
 #define PARAMETER_FLAG_SHARED 1
 
 #define INITIAL_POOL_SIZE 16
+#define INITIAL_PARAM_BLOCK_SIZE 1024
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
@@ -153,6 +154,15 @@ struct d3dx_parameter_block
 {
     char magic_string[ARRAY_SIZE(parameter_block_magic_string)];
     struct list entry;
+    size_t size;
+    size_t offset;
+    BYTE *buffer;
+};
+
+struct d3dx_recorded_parameter
+{
+    struct d3dx_parameter *param;
+    unsigned int bytes;
 };
 
 struct d3dx_effect
@@ -706,11 +716,27 @@ static void free_technique(struct d3dx_technique *technique)
     technique->name = NULL;
 }
 
+static unsigned int get_recorded_parameter_size(const struct d3dx_recorded_parameter *record)
+{
+    return sizeof(*record) + record->bytes;
+}
+
 static void free_parameter_block(struct d3dx_parameter_block *block)
 {
+    struct d3dx_recorded_parameter *record;
+
     if (!block)
         return;
 
+    record = (struct d3dx_recorded_parameter *)block->buffer;
+    while ((BYTE *)record < block->buffer + block->offset)
+    {
+        free_parameter_object_data(record->param, record + 1, record->bytes);
+        record = (struct d3dx_recorded_parameter *)((BYTE *)record + get_recorded_parameter_size(record));
+    }
+    assert((BYTE *)record == block->buffer + block->offset);
+
+    heap_free(block->buffer);
     heap_free(block);
 }
 
@@ -778,14 +804,12 @@ static void get_vector(struct d3dx_parameter *param, D3DXVECTOR4 *vector)
     }
 }
 
-static void set_vector(struct d3dx_parameter *param, const D3DXVECTOR4 *vector)
+static void set_vector(struct d3dx_parameter *param, const D3DXVECTOR4 *vector, void *dst_data)
 {
     UINT i;
 
     for (i = 0; i < param->columns; ++i)
-    {
-        set_number((FLOAT *)param->data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT);
-    }
+        set_number((FLOAT *)dst_data + i, param->type, (FLOAT *)vector + i, D3DXPT_FLOAT);
 }
 
 static void get_matrix(struct d3dx_parameter *param, D3DXMATRIX *matrix, BOOL transpose)
@@ -806,31 +830,33 @@ static void get_matrix(struct d3dx_parameter *param, D3DXMATRIX *matrix, BOOL tr
     }
 }
 
-static void set_matrix(struct d3dx_parameter *param, const D3DXMATRIX *matrix)
+static void set_matrix(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data)
 {
     UINT i, k;
 
     if (param->type == D3DXPT_FLOAT)
     {
         if (param->columns == 4)
-            memcpy(param->data, matrix->u.m, param->rows * 4 * sizeof(float));
+        {
+            memcpy(dst_data, matrix->u.m, param->rows * 4 * sizeof(float));
+        }
         else
+        {
             for (i = 0; i < param->rows; ++i)
-                memcpy((float *)param->data + i * param->columns, matrix->u.m + i, param->columns * sizeof(float));
+                memcpy((float *)dst_data + i * param->columns, matrix->u.m + i, param->columns * sizeof(float));
+        }
         return;
     }
 
     for (i = 0; i < param->rows; ++i)
     {
         for (k = 0; k < param->columns; ++k)
-        {
-            set_number((FLOAT *)param->data + i * param->columns + k, param->type,
+            set_number((FLOAT *)dst_data + i * param->columns + k, param->type,
                     &matrix->u.m[i][k], D3DXPT_FLOAT);
-        }
     }
 }
 
-static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX *matrix)
+static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX *matrix, void *dst_data)
 {
     UINT i, k;
 
@@ -838,7 +864,7 @@ static void set_matrix_transpose(struct d3dx_parameter *param, const D3DXMATRIX
     {
         for (k = 0; k < param->columns; ++k)
         {
-            set_number((FLOAT *)param->data + i * param->columns + k, param->type,
+            set_number((FLOAT *)dst_data + i * param->columns + k, param->type,
                     &matrix->u.m[k][i], D3DXPT_FLOAT);
         }
     }
@@ -857,7 +883,8 @@ static HRESULT set_string(char **param_data, const char *string)
     return D3D_OK;
 }
 
-static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigned int bytes)
+static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigned int bytes,
+        void *dst_data)
 {
     unsigned int i, count;
 
@@ -873,7 +900,7 @@ static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigne
         case D3DXPT_TEXTURECUBE:
             for (i = 0; i < count; ++i)
             {
-                IUnknown *old_texture = ((IUnknown **)param->data)[i];
+                IUnknown *old_texture = ((IUnknown **)dst_data)[i];
                 IUnknown *new_texture = ((IUnknown **)data)[i];
 
                 if (new_texture == old_texture)
@@ -890,7 +917,7 @@ static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigne
         case D3DXPT_INT:
         case D3DXPT_FLOAT:
             TRACE("Copy %u bytes.\n", bytes);
-            memcpy(param->data, data, bytes);
+            memcpy(dst_data, data, bytes);
             break;
 
         case D3DXPT_STRING:
@@ -898,7 +925,7 @@ static HRESULT set_value(struct d3dx_parameter *param, const void *data, unsigne
             HRESULT hr;
 
             for (i = 0; i < count; ++i)
-                if (FAILED(hr = set_string(&((char **)param->data)[i], ((const char **)data)[i])))
+                if (FAILED(hr = set_string(&((char **)dst_data)[i], ((const char **)data)[i])))
                     return hr;
             break;
         }
@@ -1248,6 +1275,43 @@ static ULONG64 next_effect_update_version(struct d3dx_effect *effect)
     return next_update_version(get_version_counter_ptr(effect));
 }
 
+static void *record_parameter(struct d3dx_effect *effect, struct d3dx_parameter *param, unsigned int bytes)
+{
+    struct d3dx_parameter_block *block = effect->current_parameter_block;
+    struct d3dx_recorded_parameter new_record, *record;
+    unsigned int new_size, alloc_size;
+
+    new_record.param = param;
+    new_record.bytes = bytes;
+    new_size = block->offset + get_recorded_parameter_size(&new_record);
+
+    if (new_size > block->size)
+    {
+        BYTE *new_alloc;
+
+        alloc_size = max(block->size * 2, max(new_size, INITIAL_PARAM_BLOCK_SIZE));
+        if (block->size)
+            new_alloc = heap_realloc(block->buffer, alloc_size);
+        else
+            new_alloc = heap_alloc(alloc_size);
+
+        if (!new_alloc)
+        {
+            ERR("Out of memory.\n");
+            return param->data;
+        }
+        /* Data update functions may want to free some references upon setting value. */
+        memset(new_alloc + block->size, 0, alloc_size - block->size);
+
+        block->size = alloc_size;
+        block->buffer = new_alloc;
+    }
+    record = (struct d3dx_recorded_parameter *)(block->buffer + block->offset);
+    *record = new_record;
+    block->offset = new_size;
+    return record + 1;
+}
+
 static void set_dirty(struct d3dx_parameter *param)
 {
     struct d3dx_shared_data *shared_data;
@@ -1260,6 +1324,17 @@ static void set_dirty(struct d3dx_parameter *param)
         top_param->update_version = new_update_version;
 }
 
+static void *param_get_data_and_dirtify(struct d3dx_effect *effect, struct d3dx_parameter *param,
+        unsigned int bytes, BOOL value_changed)
+{
+    assert(bytes <= param->bytes);
+
+    if (value_changed && !effect->current_parameter_block)
+        set_dirty(param);
+
+    return effect->current_parameter_block ? record_parameter(effect, param, bytes) : param->data;
+}
+
 static void d3dx9_set_light_parameter(enum LIGHT_TYPE op, D3DLIGHT9 *light, void *value)
 {
     static const struct
@@ -2364,10 +2439,7 @@ static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parame
     }
 
     if (data && param->bytes <= bytes)
-    {
-        set_dirty(param);
-        return set_value(param, data, bytes);
-    }
+        return set_value(param, data, bytes, param_get_data_and_dirtify(effect, param, param->bytes, TRUE));
 
     WARN("Invalid argument specified.\n");
 
@@ -2448,8 +2520,8 @@ static HRESULT WINAPI d3dx_effect_SetBool(ID3DXEffect *iface, D3DXHANDLE paramet
 
     if (param && !param->element_count && param->rows == 1 && param->columns == 1)
     {
-        set_number(param->data, param->type, &b, D3DXPT_BOOL);
-        set_dirty(param);
+        set_number(param_get_data_and_dirtify(effect, param, sizeof(int), TRUE),
+                param->type, &b, D3DXPT_BOOL);
         return D3D_OK;
     }
 
@@ -2481,6 +2553,7 @@ static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE pa
 {
     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
+    DWORD *data;
 
     TRACE("iface %p, parameter %p, b %p, count %u.\n", iface, parameter, b, count);
 
@@ -2495,12 +2568,12 @@ static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE pa
             case D3DXPC_SCALAR:
             case D3DXPC_VECTOR:
             case D3DXPC_MATRIX_ROWS:
+                data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
                 for (i = 0; i < size; ++i)
                 {
                     /* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */
-                    set_number((DWORD *)param->data + i, param->type, &b[i], D3DXPT_INT);
+                    set_number(data + i, param->type, &b[i], D3DXPT_INT);
                 }
-                set_dirty(param);
                 return D3D_OK;
 
             case D3DXPC_OBJECT:
@@ -2558,9 +2631,8 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete
             DWORD value;
 
             set_number(&value, param->type, &n, D3DXPT_INT);
-            if (value != *(DWORD *)param->data)
-                set_dirty(param);
-            *(DWORD *)param->data = value;
+            *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(int),
+                    value != *(DWORD *)param->data) = value;
             return D3D_OK;
         }
 
@@ -2569,14 +2641,19 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete
                 && ((param->class == D3DXPC_VECTOR && param->columns != 2)
                 || (param->class == D3DXPC_MATRIX_ROWS && param->rows != 2 && param->columns == 1)))
         {
+            float *data;
+
             TRACE("Vector fixup.\n");
 
-            *(float *)param->data = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
-            ((float *)param->data)[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
-            ((float *)param->data)[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
+            data = param_get_data_and_dirtify(effect, param,
+                    min(4, param->rows * param->columns) * sizeof(float), TRUE);
+
+            data[0] = ((n & 0xff0000) >> 16) * INT_FLOAT_MULTI_INVERSE;
+            data[1] = ((n & 0xff00) >> 8) * INT_FLOAT_MULTI_INVERSE;
+            data[2] = (n & 0xff) * INT_FLOAT_MULTI_INVERSE;
             if (param->rows * param->columns > 3)
-                ((float *)param->data)[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
-            set_dirty(param);
+                data[3] = ((n & 0xff000000) >> 24) * INT_FLOAT_MULTI_INVERSE;
+
             return D3D_OK;
         }
     }
@@ -2628,6 +2705,7 @@ static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE par
 {
     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
+    DWORD *data;
 
     TRACE("iface %p, parameter %p, n %p, count %u.\n", iface, parameter, n, count);
 
@@ -2642,9 +2720,9 @@ static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE par
             case D3DXPC_SCALAR:
             case D3DXPC_VECTOR:
             case D3DXPC_MATRIX_ROWS:
+                data = param_get_data_and_dirtify(effect, param, size * sizeof(int), TRUE);
                 for (i = 0; i < size; ++i)
-                    set_number((DWORD *)param->data + i, param->type, &n[i], D3DXPT_INT);
-                set_dirty(param);
+                    set_number(data + i, param->type, &n[i], D3DXPT_INT);
                 return D3D_OK;
 
             case D3DXPC_OBJECT:
@@ -2698,9 +2776,8 @@ static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parame
         DWORD value;
 
         set_number(&value, param->type, &f, D3DXPT_FLOAT);
-        if (value != *(DWORD *)param->data)
-            set_dirty(param);
-        *(DWORD *)param->data = value;
+        *(DWORD *)param_get_data_and_dirtify(effect, param, sizeof(float),
+                value != *(DWORD *)param->data) = value;
         return D3D_OK;
     }
 
@@ -2733,6 +2810,7 @@ static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE p
 {
     struct d3dx_effect *effect = impl_from_ID3DXEffect(iface);
     struct d3dx_parameter *param = get_valid_parameter(effect, parameter);
+    DWORD *data;
 
     TRACE("iface %p, parameter %p, f %p, count %u.\n", iface, parameter, f, count);
 
@@ -2747,9 +2825,9 @@ static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE p
             case D3DXPC_SCALAR:
             case D3DXPC_VECTOR:
             case D3DXPC_MATRIX_ROWS:
+                data = param_get_data_and_dirtify(effect, param, size * sizeof(float), TRUE);
                 for (i = 0; i < size; ++i)
-                    set_number((DWORD *)param->data + i, param->type, &f[i], D3DXPT_FLOAT);
-                set_dirty(param);
+                    set_number(data + i, param->type, &f[i], D3DXPT_FLOAT);
                 return D3D_OK;
 
             case D3DXPC_OBJECT:
@@ -2806,7 +2884,6 @@ static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE param
         {
             case D3DXPC_SCALAR:
             case D3DXPC_VECTOR:
-                set_dirty(param);
                 if (param->type == D3DXPT_INT && param->bytes == 4)
                 {
                     DWORD tmp;
@@ -2817,16 +2894,17 @@ static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE param
                     tmp += ((DWORD)(max(min(vector->x, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 16;
                     tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
 
-                    *(int *)param->data = tmp;
+                    *(int *)param_get_data_and_dirtify(effect, param, sizeof(int), TRUE) = tmp;
                     return D3D_OK;
                 }
                 if (param->type == D3DXPT_FLOAT)
                 {
-                    memcpy(param->data, vector, param->columns * sizeof(float));
+                    memcpy(param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE),
+                            vector, param->columns * sizeof(float));
                     return D3D_OK;
                 }
 
-                set_vector(param, vector);
+                set_vector(param, vector, param_get_data_and_dirtify(effect, param, param->columns * sizeof(float), TRUE));
                 return D3D_OK;
 
             case D3DXPC_MATRIX_ROWS:
@@ -2899,26 +2977,33 @@ static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE
     if (param && param->element_count && param->element_count >= count)
     {
         unsigned int i;
+        BYTE *data;
 
         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
 
         switch (param->class)
         {
             case D3DXPC_VECTOR:
-                set_dirty(param);
+                data = param_get_data_and_dirtify(effect, param, count * param->columns * sizeof(float), TRUE);
+
                 if (param->type == D3DXPT_FLOAT)
                 {
                     if (param->columns == 4)
-                        memcpy(param->data, vector, count * 4 * sizeof(float));
+                    {
+                        memcpy(data, vector, count * 4 * sizeof(float));
+                    }
                     else
+                    {
                         for (i = 0; i < count; ++i)
-                            memcpy((float *)param->data + param->columns * i, vector + i,
+                            memcpy((float *)data + param->columns * i, vector + i,
                                     param->columns * sizeof(float));
+                    }
                     return D3D_OK;
                 }
 
                 for (i = 0; i < count; ++i)
-                    set_vector(&param->members[i], &vector[i]);
+                    set_vector(&param->members[i], &vector[i], data + i * param->columns * sizeof(float));
+
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -2993,8 +3078,8 @@ static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE param
         switch (param->class)
         {
             case D3DXPC_MATRIX_ROWS:
-                set_matrix(param, matrix);
-                set_dirty(param);
+                set_matrix(param, matrix, param_get_data_and_dirtify(effect, param,
+                        param->rows * param->columns * sizeof(float), TRUE));
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3059,15 +3144,20 @@ static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE
     if (param && param->element_count >= count)
     {
         unsigned int i;
+        BYTE *data;
 
         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
 
         switch (param->class)
         {
             case D3DXPC_MATRIX_ROWS:
-                set_dirty(param);
+                data = param_get_data_and_dirtify(effect, param, count * param->rows
+                        * param->columns * sizeof(float), TRUE);
+
                 for (i = 0; i < count; ++i)
-                    set_matrix(&param->members[i], &matrix[i]);
+                    set_matrix(&param->members[i], &matrix[i],
+                            data + i * param->rows * param->columns * sizeof(float));
+
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3139,13 +3229,18 @@ static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DX
     if (param && count <= param->element_count)
     {
         unsigned int i;
+        BYTE *data;
 
         switch (param->class)
         {
             case D3DXPC_MATRIX_ROWS:
-                set_dirty(param);
+                data = param_get_data_and_dirtify(effect, param, count * param->rows
+                        * param->columns * sizeof(float), TRUE);
+
                 for (i = 0; i < count; ++i)
-                    set_matrix(&param->members[i], matrix[i]);
+                    set_matrix(&param->members[i], matrix[i], data + i * param->rows
+                            * param->columns * sizeof(float));
+
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3219,8 +3314,8 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHAN
         switch (param->class)
         {
             case D3DXPC_MATRIX_ROWS:
-                set_dirty(param);
-                set_matrix_transpose(param, matrix);
+                set_matrix_transpose(param, matrix, param_get_data_and_dirtify(effect, param,
+                        param->rows * param->columns * sizeof(float), TRUE));
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3289,15 +3384,20 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3
     if (param && param->element_count >= count)
     {
         unsigned int i;
+        BYTE *data;
 
         TRACE("Class %s.\n", debug_d3dxparameter_class(param->class));
 
         switch (param->class)
         {
             case D3DXPC_MATRIX_ROWS:
-                set_dirty(param);
+                data = param_get_data_and_dirtify(effect, param, count * param->rows
+                        * param->columns * sizeof(float), TRUE);
+
                 for (i = 0; i < count; ++i)
-                    set_matrix_transpose(&param->members[i], &matrix[i]);
+                    set_matrix_transpose(&param->members[i], &matrix[i], data
+                            + i * param->rows * param->columns * sizeof(float));
+
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3369,13 +3469,18 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *if
     if (param && count <= param->element_count)
     {
         unsigned int i;
+        BYTE *data;
 
         switch (param->class)
         {
             case D3DXPC_MATRIX_ROWS:
-                set_dirty(param);
+                data = param_get_data_and_dirtify(effect, param, count * param->rows
+                        * param->columns * sizeof(float), TRUE);
+
                 for (i = 0; i < count; ++i)
-                    set_matrix_transpose(&param->members[i], matrix[i]);
+                    set_matrix_transpose(&param->members[i], matrix[i], data
+                            + i * param->rows * param->columns * sizeof(float));
+
                 return D3D_OK;
 
             case D3DXPC_SCALAR:
@@ -3442,10 +3547,7 @@ static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE param
     TRACE("iface %p, parameter %p, string %s.\n", iface, parameter, debugstr_a(string));
 
     if (param && param->type == D3DXPT_STRING)
-    {
-        set_dirty(param);
-        return set_string(param->data, string);
-    }
+        return set_string(param_get_data_and_dirtify(effect, param, sizeof(void *), TRUE), string);
 
     WARN("Parameter not found.\n");
 
@@ -3484,7 +3586,11 @@ static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE para
             || param->type == D3DXPT_TEXTURE2D || param->type ==  D3DXPT_TEXTURE3D
             || param->type == D3DXPT_TEXTURECUBE))
     {
-        IDirect3DBaseTexture9 *old_texture = *(IDirect3DBaseTexture9 **)param->data;
+        IDirect3DBaseTexture9 **data = param_get_data_and_dirtify(effect, param,
+                sizeof(void *), texture != *(IDirect3DBaseTexture9 **)param->data);
+        IDirect3DBaseTexture9 *old_texture = *data;
+
+        *data = texture;
 
         if (texture == old_texture)
             return D3D_OK;
@@ -3494,9 +3600,6 @@ static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE para
         if (old_texture)
             IDirect3DBaseTexture9_Release(old_texture);
 
-        *(IDirect3DBaseTexture9 **)param->data = texture;
-        set_dirty(param);
-
         return D3D_OK;
     }
 
@@ -4137,6 +4240,10 @@ static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface)
         return NULL;
     }
     ret = effect->current_parameter_block;
+
+    ret->buffer = heap_realloc(ret->buffer, ret->offset);
+    ret->size = ret->offset;
+
     effect->current_parameter_block = NULL;
     list_add_tail(&effect->parameter_block_list, &ret->entry);
     return (D3DXHANDLE)ret;
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c
index f1cbe49287c..706ae126b82 100644
--- a/dlls/d3dx9_36/tests/effect.c
+++ b/dlls/d3dx9_36/tests/effect.c
@@ -8020,12 +8020,12 @@ static void test_effect_parameter_block(void)
     IDirect3DTexture9 *texture, *tex_test;
     D3DXHANDLE block, block2, handle;
     ID3DXEffect *effect, *effect2;
+    D3DXMATRIX mat, mat_arr[2];
     IDirect3DDevice9 *device;
     ID3DXEffectPool *pool;
     float float_array[4];
     float float_value;
     IDirect3D9 *d3d;
-    D3DXMATRIX mat;
     ULONG refcount;
     HWND window;
     HRESULT hr;
@@ -8115,9 +8115,7 @@ static void test_effect_parameter_block(void)
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
 
     hr = effect->lpVtbl->GetTexture(effect, "tex1", (IDirect3DBaseTexture9 **)&tex_test);
-    todo_wine ok(hr == D3D_OK && !tex_test, "Got unexpected hr %#x, tex_test %p.\n", hr, tex_test);
-    if (tex_test)
-        IDirect3DTexture9_Release(tex_test);
+    ok(hr == D3D_OK && !tex_test, "Got unexpected hr %#x, tex_test %p.\n", hr, tex_test);
 
     /* Child parameters and array members are recorded separately (the whole
      * parameter is not updated when parameter block is applied). */
@@ -8126,13 +8124,13 @@ static void test_effect_parameter_block(void)
     hr = effect->lpVtbl->SetFloat(effect, "ts1[0].fv", 28.0f);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     hr = effect->lpVtbl->GetFloat(effect, "ts1[0].fv", &float_value);
-    todo_wine ok(hr == D3D_OK && float_value == 12.0, "Got unexpected hr %#x, float_value %g.\n", hr, float_value);
+    ok(hr == D3D_OK && float_value == 12.0, "Got unexpected hr %#x, float_value %g.\n", hr, float_value);
 
     float_array[0] = -29.0f;
     hr = effect->lpVtbl->SetFloatArray(effect, "ts1[0].v2", float_array, 1);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     hr = effect->lpVtbl->GetFloatArray(effect, "ts1[0].v2", float_array, 1);
-    todo_wine ok(hr == D3D_OK && float_array[0] == 13.0, "Got unexpected hr %#x, float_array[0] %g.\n",
+    ok(hr == D3D_OK && float_array[0] == 13.0, "Got unexpected hr %#x, float_array[0] %g.\n",
             hr, float_array[0]);
 
     memset(&mat, 0, sizeof(mat));
@@ -8140,13 +8138,13 @@ static void test_effect_parameter_block(void)
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     hr = effect->lpVtbl->GetMatrix(effect, "m3x2row", &mat);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-    todo_wine ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n");
+    ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n");
 
     hr = effect->lpVtbl->SetMatrix(effect, "m3x2column", &test_mat);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
     hr = effect->lpVtbl->GetMatrix(effect, "m3x2column", &mat);
     ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
-    todo_wine ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n");
+    ok(!memcmp(&mat, &effect_orig_mat, sizeof(mat)), "Got unexpected matrix.\n");
 
     /* Setting shared parameter through effect2 is not recorded to effect
      * parameter block. */
@@ -8321,6 +8319,30 @@ static void test_effect_parameter_block(void)
     refcount = pool->lpVtbl->Release(pool);
     ok(!refcount, "Got unexpected refcount %u.\n", refcount);
 
+    hr = D3DXCreateEffect(device, test_effect_parameter_value_blob_float, sizeof(test_effect_parameter_value_blob_float),
+            NULL, NULL, 0, NULL, &effect, NULL);
+    hr = effect->lpVtbl->BeginParameterBlock(effect);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    mat_arr[0] = mat_arr[1] = test_mat;
+    hr = effect->lpVtbl->SetMatrixArray(effect, "f33_2", mat_arr, 2);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    block = effect->lpVtbl->EndParameterBlock(effect);
+    ok(!!block, "Got unexpected block %p.\n", block);
+
+    memset(mat_arr, 0, sizeof(mat_arr));
+    hr = effect->lpVtbl->SetMatrixArray(effect, "f33_2", mat_arr, 2);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = effect->lpVtbl->ApplyParameterBlock(effect, block);
+    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+
+    hr = effect->lpVtbl->GetMatrixArray(effect, "f33_2", mat_arr, 2);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    todo_wine ok(!memcmp(&mat_arr[0], &test_mat, sizeof(test_mat))
+            && !memcmp(&mat_arr[1], &test_mat, sizeof(test_mat)), "Got unexpected matrix array.\n");
+
+    refcount = effect->lpVtbl->Release(effect);
+    ok(!refcount, "Got unexpected refcount %u.\n", refcount);
+
     refcount = IDirect3DDevice9_Release(device);
     ok(!refcount, "Device has %u references left.\n", refcount);
     IDirect3D9_Release(d3d);
-- 
2.21.0




More information about the wine-devel mailing list