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(¶m->members[i], &vector[i]); + set_vector(¶m->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(¶m->members[i], &matrix[i]); + set_matrix(¶m->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(¶m->members[i], matrix[i]); + set_matrix(¶m->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(¶m->members[i], &matrix[i]); + set_matrix_transpose(¶m->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(¶m->members[i], matrix[i]); + set_matrix_transpose(¶m->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);