[PATCH 09/10] d3dx9: Implement recording parameters to parameter block.
Paul Gofman
gofmanp at gmail.com
Thu Nov 7 15:17:43 CST 2019
Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
dlls/d3dx9_36/effect.c | 111 +++++++++++++++++++++++++++++++++++
dlls/d3dx9_36/tests/effect.c | 6 +-
2 files changed, 114 insertions(+), 3 deletions(-)
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
index 4739b0cc0e..7a7fc336e1 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 buffer_size;
+ size_t current_size;
+ 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->current_size)
+ {
+ 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->current_size);
+
+ heap_free(block->buffer);
heap_free(block);
}
@@ -1293,6 +1319,46 @@ 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, const void *data,
+ 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;
+
+ if (!block)
+ return;
+
+ assert(bytes <= param->bytes);
+
+ new_record.param = param;
+ new_record.bytes = bytes;
+ new_size = block->current_size + get_recorded_parameter_size(&new_record);
+
+ if (new_size > block->buffer_size)
+ {
+ BYTE *new_alloc;
+
+ alloc_size = max(block->buffer_size * 2, max(new_size, INITIAL_PARAM_BLOCK_SIZE));
+ if (block->buffer_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;
+ }
+ block->buffer_size = alloc_size;
+ block->buffer = new_alloc;
+ }
+ record = (struct d3dx_recorded_parameter *)(block->buffer + block->current_size);
+ *record = new_record;
+ get_value(param, record + 1, data, bytes);
+ block->current_size = new_size;
+}
+
static void set_dirty(struct d3dx_parameter *param)
{
struct d3dx_shared_data *shared_data;
@@ -2411,6 +2477,7 @@ static HRESULT WINAPI d3dx_effect_SetValue(ID3DXEffect *iface, D3DXHANDLE parame
if (data && param->bytes <= bytes)
{
set_dirty(param);
+ record_parameter(effect, param, data, param->bytes);
return set_value(param, data, bytes);
}
@@ -2460,6 +2527,7 @@ 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);
+ record_parameter(effect, param, NULL, sizeof(int));
set_dirty(param);
return D3D_OK;
}
@@ -2511,6 +2579,7 @@ static HRESULT WINAPI d3dx_effect_SetBoolArray(ID3DXEffect *iface, D3DXHANDLE pa
/* don't crop the input, use D3DXPT_INT instead of D3DXPT_BOOL */
set_number((DWORD *)param->data + i, param->type, &b[i], D3DXPT_INT);
}
+ record_parameter(effect, param, NULL, count * sizeof(int));
set_dirty(param);
return D3D_OK;
@@ -2571,6 +2640,7 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete
set_number(&value, param->type, &n, D3DXPT_INT);
if (value != *(DWORD *)param->data)
set_dirty(param);
+ record_parameter(effect, param, &value, sizeof(int));
*(DWORD *)param->data = value;
return D3D_OK;
}
@@ -2587,6 +2657,7 @@ static HRESULT WINAPI d3dx_effect_SetInt(ID3DXEffect *iface, D3DXHANDLE paramete
((float *)param->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;
+ record_parameter(effect, param, NULL, 4 * sizeof(float));
set_dirty(param);
return D3D_OK;
}
@@ -2655,6 +2726,7 @@ static HRESULT WINAPI d3dx_effect_SetIntArray(ID3DXEffect *iface, D3DXHANDLE par
case D3DXPC_MATRIX_ROWS:
for (i = 0; i < size; ++i)
set_number((DWORD *)param->data + i, param->type, &n[i], D3DXPT_INT);
+ record_parameter(effect, param, NULL, size * sizeof(int));
set_dirty(param);
return D3D_OK;
@@ -2712,6 +2784,7 @@ static HRESULT WINAPI d3dx_effect_SetFloat(ID3DXEffect *iface, D3DXHANDLE parame
if (value != *(DWORD *)param->data)
set_dirty(param);
*(DWORD *)param->data = value;
+ record_parameter(effect, param, NULL, sizeof(float));
return D3D_OK;
}
@@ -2760,6 +2833,7 @@ static HRESULT WINAPI d3dx_effect_SetFloatArray(ID3DXEffect *iface, D3DXHANDLE p
case D3DXPC_MATRIX_ROWS:
for (i = 0; i < size; ++i)
set_number((DWORD *)param->data + i, param->type, &f[i], D3DXPT_FLOAT);
+ record_parameter(effect, param, NULL, size * sizeof(float));
set_dirty(param);
return D3D_OK;
@@ -2829,15 +2903,18 @@ static HRESULT WINAPI d3dx_effect_SetVector(ID3DXEffect *iface, D3DXHANDLE param
tmp += ((DWORD)(max(min(vector->w, 1.0f), 0.0f) * INT_FLOAT_MULTI)) << 24;
*(int *)param->data = tmp;
+ record_parameter(effect, param, NULL, sizeof(int));
return D3D_OK;
}
if (param->type == D3DXPT_FLOAT)
{
memcpy(param->data, vector, param->columns * sizeof(float));
+ record_parameter(effect, param, NULL, param->columns * sizeof(float));
return D3D_OK;
}
set_vector(param, vector);
+ record_parameter(effect, param, NULL, param->columns * sizeof(float));
return D3D_OK;
case D3DXPC_MATRIX_ROWS:
@@ -2920,16 +2997,23 @@ static HRESULT WINAPI d3dx_effect_SetVectorArray(ID3DXEffect *iface, D3DXHANDLE
if (param->type == D3DXPT_FLOAT)
{
if (param->columns == 4)
+ {
memcpy(param->data, vector, count * 4 * sizeof(float));
+ record_parameter(effect, param, NULL, count * 4 * sizeof(float));
+ }
else
+ {
for (i = 0; i < count; ++i)
memcpy((float *)param->data + param->columns * i, vector + i,
param->columns * sizeof(float));
+ record_parameter(effect, param, NULL, count * param->columns * sizeof(float));
+ }
return D3D_OK;
}
for (i = 0; i < count; ++i)
set_vector(¶m->members[i], &vector[i]);
+ record_parameter(effect, param, NULL, count * param->columns * sizeof(float));
return D3D_OK;
case D3DXPC_SCALAR:
@@ -3005,6 +3089,7 @@ static HRESULT WINAPI d3dx_effect_SetMatrix(ID3DXEffect *iface, D3DXHANDLE param
{
case D3DXPC_MATRIX_ROWS:
set_matrix(param, matrix);
+ record_parameter(effect, param, NULL, param->rows * param->columns * sizeof(float));
set_dirty(param);
return D3D_OK;
@@ -3078,7 +3163,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixArray(ID3DXEffect *iface, D3DXHANDLE
case D3DXPC_MATRIX_ROWS:
set_dirty(param);
for (i = 0; i < count; ++i)
+ {
set_matrix(¶m->members[i], &matrix[i]);
+ record_parameter(effect, ¶m->members[i], NULL, param->members[i].rows
+ * param->members[i].columns * sizeof(float));
+ }
return D3D_OK;
case D3DXPC_SCALAR:
@@ -3156,7 +3245,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixPointerArray(ID3DXEffect *iface, D3DX
case D3DXPC_MATRIX_ROWS:
set_dirty(param);
for (i = 0; i < count; ++i)
+ {
set_matrix(¶m->members[i], matrix[i]);
+ record_parameter(effect, ¶m->members[i], NULL, param->members[i].rows
+ * param->members[i].columns * sizeof(float));
+ }
return D3D_OK;
case D3DXPC_SCALAR:
@@ -3232,6 +3325,7 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTranspose(ID3DXEffect *iface, D3DXHAN
case D3DXPC_MATRIX_ROWS:
set_dirty(param);
set_matrix_transpose(param, matrix);
+ record_parameter(effect, param, NULL, param->rows * param->columns * sizeof(float));
return D3D_OK;
case D3DXPC_SCALAR:
@@ -3308,7 +3402,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposeArray(ID3DXEffect *iface, D3
case D3DXPC_MATRIX_ROWS:
set_dirty(param);
for (i = 0; i < count; ++i)
+ {
set_matrix_transpose(¶m->members[i], &matrix[i]);
+ record_parameter(effect, ¶m->members[i], NULL, param->members[i].rows
+ * param->members[i].columns * sizeof(float));
+ }
return D3D_OK;
case D3DXPC_SCALAR:
@@ -3386,7 +3484,11 @@ static HRESULT WINAPI d3dx_effect_SetMatrixTransposePointerArray(ID3DXEffect *if
case D3DXPC_MATRIX_ROWS:
set_dirty(param);
for (i = 0; i < count; ++i)
+ {
set_matrix_transpose(¶m->members[i], matrix[i]);
+ record_parameter(effect, ¶m->members[i], NULL, param->members[i].rows
+ * param->members[i].columns * sizeof(float));
+ }
return D3D_OK;
case D3DXPC_SCALAR:
@@ -3455,6 +3557,10 @@ static HRESULT WINAPI d3dx_effect_SetString(ID3DXEffect *iface, D3DXHANDLE param
if (param && param->type == D3DXPT_STRING)
{
set_dirty(param);
+
+ if (effect->current_parameter_block)
+ FIXME("Recording string parameters not supported.\n");
+
return set_string(param->data, string);
}
@@ -3507,6 +3613,7 @@ static HRESULT WINAPI d3dx_effect_SetTexture(ID3DXEffect *iface, D3DXHANDLE para
*(IDirect3DBaseTexture9 **)param->data = texture;
set_dirty(param);
+ record_parameter(effect, param, NULL, sizeof(void *));
return D3D_OK;
}
@@ -4148,6 +4255,10 @@ static D3DXHANDLE WINAPI d3dx_effect_EndParameterBlock(ID3DXEffect *iface)
return NULL;
}
ret = effect->current_parameter_block;
+
+ ret->buffer = heap_realloc(ret->buffer, ret->current_size);
+ ret->buffer_size = ret->current_size;
+
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 1732a77541..d24e04a753 100644
--- a/dlls/d3dx9_36/tests/effect.c
+++ b/dlls/d3dx9_36/tests/effect.c
@@ -8134,21 +8134,21 @@ static void test_effect_parameter_block(void)
* Maybe native d3dx is using some copy on write strategy. */
IDirect3DTexture9_AddRef(texture);
refcount = IDirect3DTexture9_Release(texture);
- ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+ todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
block = effect->lpVtbl->EndParameterBlock(effect);
ok(!!block, "Got unexpected block %p.\n", block);
IDirect3DTexture9_AddRef(texture);
refcount = IDirect3DTexture9_Release(texture);
- ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+ todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
hr = effect->lpVtbl->SetTexture(effect, "tex1", NULL);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
IDirect3DTexture9_AddRef(texture);
refcount = IDirect3DTexture9_Release(texture);
- todo_wine ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
+ ok(refcount == 2, "Got unexpected refcount %u.\n", refcount);
hr = effect->lpVtbl->SetFloat(effect, "arr2[0]", 0.0f);
ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
--
2.23.0
More information about the wine-devel
mailing list