[v2 2/2] d3dx9: Get rid of constants modification bitmasks.
Paul Gofman
gofmanp at gmail.com
Tue Aug 29 09:54:02 CDT 2017
Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
v2:
- renamed 'append_pres_const_set()' to 'append_pres_const_sets_for_shader_input()';
- initialized 'const_set' definition instead of memset();
- used 'while' loop instead of decrementing counter value inside the loop;
- removed extra blank lines;
- renamed 'device_table, device_...' variables to 'current_table, ...',
- check that preshader output const_set register range end is lower than next preshader
output register range.
---
dlls/d3dx9_36/d3dx9_private.h | 3 +-
dlls/d3dx9_36/preshader.c | 325 +++++++++++++++++++-----------------------
2 files changed, 148 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;
enum D3DXPARAMETER_CLASS constant_class;
unsigned int register_index;
unsigned int register_count;
@@ -254,7 +254,6 @@ struct d3dx_regstore
{
void *tables[PRES_REGTAB_COUNT];
unsigned int table_sizes[PRES_REGTAB_COUNT]; /* registers count */
- unsigned int *table_value_set[PRES_REGTAB_COUNT];
};
struct d3dx_pres_ins;
diff --git a/dlls/d3dx9_36/preshader.c b/dlls/d3dx9_36/preshader.c
index f38f875f5e..58b8d62df6 100644
--- a/dlls/d3dx9_36/preshader.c
+++ b/dlls/d3dx9_36/preshader.c
@@ -313,10 +313,7 @@ static HRESULT regstore_alloc_table(struct d3dx_regstore *rs, unsigned int table
if (size)
{
rs->tables[table] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
- rs->table_value_set[table] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
- sizeof(*rs->table_value_set[table]) *
- ((rs->table_sizes[table] + PRES_BITMASK_BLOCK_SIZE - 1) / PRES_BITMASK_BLOCK_SIZE));
- if (!rs->tables[table] || !rs->table_value_set[table])
+ if (!rs->tables[table])
return E_OUTOFMEMORY;
}
return D3D_OK;
@@ -329,45 +326,9 @@ static void regstore_free_tables(struct d3dx_regstore *rs)
for (i = 0; i < PRES_REGTAB_COUNT; ++i)
{
HeapFree(GetProcessHeap(), 0, rs->tables[i]);
- HeapFree(GetProcessHeap(), 0, rs->table_value_set[i]);
}
}
-static void regstore_set_modified_reg(struct d3dx_regstore *rs, unsigned int table,
- unsigned int start, unsigned int end)
-{
- unsigned int block_idx, start_block, end_block;
-
- start_block = start / PRES_BITMASK_BLOCK_SIZE;
- start -= start_block * PRES_BITMASK_BLOCK_SIZE;
- end_block = end / PRES_BITMASK_BLOCK_SIZE;
- end = (end_block + 1) * PRES_BITMASK_BLOCK_SIZE - 1 - end;
-
- if (start_block == end_block)
- {
- rs->table_value_set[table][start_block] |= (~0u << start) & (~0u >> end);
- }
- else
- {
- rs->table_value_set[table][start_block] |= ~0u << start;
-
- for (block_idx = start_block + 1; block_idx < end_block; ++block_idx)
- rs->table_value_set[table][block_idx] = ~0u;
-
- rs->table_value_set[table][end_block] |= ~0u >> end;
- }
-}
-
-static void regstore_set_modified(struct d3dx_regstore *rs, unsigned int table,
- unsigned int start_offset, unsigned int count)
-{
- if (!count)
- return;
-
- regstore_set_modified_reg(rs, table, get_reg_offset(table, start_offset),
- get_reg_offset(table, start_offset + count - 1));
-}
-
static void regstore_set_values(struct d3dx_regstore *rs, unsigned int table, const void *data,
unsigned int start_offset, unsigned int count)
{
@@ -375,20 +336,10 @@ static void regstore_set_values(struct d3dx_regstore *rs, unsigned int table, co
const BYTE *src = data;
unsigned int size;
- if (!count)
- return;
-
dst += start_offset * table_info[table].component_size;
size = count * table_info[table].component_size;
assert((src < dst && size <= dst - src) || (src > dst && size <= src - dst));
memcpy(dst, src, size);
- regstore_set_modified(rs, table, start_offset, count);
-}
-
-static unsigned int regstore_is_val_set_reg(struct d3dx_regstore *rs, unsigned int table, unsigned int reg_idx)
-{
- return rs->table_value_set[table][reg_idx / PRES_BITMASK_BLOCK_SIZE] &
- (1u << (reg_idx % PRES_BITMASK_BLOCK_SIZE));
}
static double regstore_get_double(struct d3dx_regstore *rs, unsigned int table, unsigned int offset)
@@ -411,7 +362,6 @@ static double regstore_get_double(struct d3dx_regstore *rs, unsigned int table,
static void regstore_set_double(struct d3dx_regstore *rs, unsigned int table, unsigned int offset, double v)
{
BYTE *p;
- unsigned int reg_idx;
p = (BYTE *)rs->tables[table] + table_info[table].component_size * offset;
switch (table_info[table].type)
@@ -424,16 +374,6 @@ static void regstore_set_double(struct d3dx_regstore *rs, unsigned int table, un
FIXME("Bad type %u.\n", table_info[table].type);
break;
}
- reg_idx = get_reg_offset(table, offset);
- rs->table_value_set[table][reg_idx / PRES_BITMASK_BLOCK_SIZE] |=
- 1u << (reg_idx % PRES_BITMASK_BLOCK_SIZE);
-}
-
-static void regstore_reset_modified(struct d3dx_regstore *rs, unsigned int table)
-{
- memset(rs->table_value_set[table], 0,
- sizeof(*rs->table_value_set[table]) *
- ((rs->table_sizes[table] + PRES_BITMASK_BLOCK_SIZE - 1) / PRES_BITMASK_BLOCK_SIZE));
}
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_sets_for_shader_input(struct d3dx_const_tab *const_tab,
+ struct d3dx_preshader *pres)
+{
+ unsigned int i;
+ struct d3dx_const_param_eval_output const_set = {NULL};
+
+ for (i = 0; i < pres->ins_count; ++i)
+ {
+ const struct d3dx_pres_ins *ins = &pres->ins[i];
+ const struct d3dx_pres_reg *reg = &ins->output.reg;
+
+ if (reg->table == PRES_REGTAB_TEMP)
+ continue;
+
+ const_set.register_index = get_reg_offset(reg->table, reg->offset);
+ const_set.register_count = max(get_reg_offset(reg->table,
+ pres_op_info[ins->op].func_all_comps ? 1 : ins->component_count), 1);
+ const_set.table = reg->table;
+ const_set.constant_class = D3DXPC_FORCE_DWORD;
+ const_set.element_count = 1;
+ append_const_set(const_tab, &const_set);
+ }
+}
+
+static int compare_const_set(const void *a, const void *b)
+{
+ const struct d3dx_const_param_eval_output *r1 = a;
+ const struct d3dx_const_param_eval_output *r2 = b;
+
+ if (r1->table != r2->table)
+ return r1->table - r2->table;
+ return r1->register_index - r2->register_index;
+}
+
static HRESULT merge_const_set_entries(struct d3dx_const_tab *const_tab,
struct d3dx_parameter *param, unsigned int index)
{
@@ -874,7 +848,8 @@ static HRESULT init_set_constants_param(struct d3dx_const_tab *const_tab, ID3DXC
}
static HRESULT get_constants_desc(unsigned int *byte_code, struct d3dx_const_tab *out,
- struct d3dx9_base_effect *base, const char **skip_constants, unsigned int skip_constants_count)
+ struct d3dx9_base_effect *base, const char **skip_constants,
+ unsigned int skip_constants_count, struct d3dx_preshader *pres)
{
ID3DXConstantTable *ctab;
D3DXCONSTANT_DESC *cdesc;
@@ -971,10 +946,45 @@ 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_sets_for_shader_input(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);
+
+ i = 0;
+ while (i < out->const_set_count - 1)
+ {
+ 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)
+ {
+ if (out->const_set[i].register_index + out->const_set[i].register_count
+ > out->const_set[i + 1].register_index + out->const_set[i + 1].register_count)
+ {
+ WARN("Unexpected preshader register count %u, register index %u, "
+ "next register count %u, register index %u, i %u.\n",
+ out->const_set[i].register_count, out->const_set[i].register_index,
+ out->const_set[i + 1].register_count, out->const_set[i + 1].register_index, i);
+ hr = D3DERR_INVALIDCALL;
+ goto cleanup;
+ }
+ 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;
+ 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;
+ }
+ else
+ {
+ ++i;
+ }
+ }
+
new_alloc = HeapReAlloc(GetProcessHeap(), 0, out->const_set,
sizeof(*out->const_set) * out->const_set_count);
if (new_alloc)
@@ -1163,7 +1173,7 @@ static HRESULT parse_preshader(struct d3dx_preshader *pres, unsigned int *ptr, u
saved_word = *ptr;
*ptr = 0xfffe0000;
- hr = get_constants_desc(ptr, &pres->inputs, base, NULL, 0);
+ hr = get_constants_desc(ptr, &pres->inputs, base, NULL, 0, NULL);
*ptr = saved_word;
if (FAILED(hr))
return hr;
@@ -1221,7 +1231,7 @@ HRESULT d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte
const char **skip_constants, unsigned int skip_constants_count)
{
struct d3dx_param_eval *peval;
- unsigned int *ptr;
+ unsigned int *ptr, *shader_ptr = NULL;
unsigned int i;
BOOL shader;
unsigned int count, pres_size;
@@ -1268,14 +1278,7 @@ HRESULT d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte
goto err_out;
}
TRACE("Shader version %#x.\n", *ptr & 0xffff);
-
- if (FAILED(ret = get_constants_desc(ptr, &peval->shader_inputs, base_effect,
- skip_constants, skip_constants_count)))
- {
- WARN("Could not get shader constant table, ret %#x.\n", ret);
- goto err_out;
- }
- update_table_sizes_consts(peval->pres.regs.table_sizes, &peval->shader_inputs);
+ shader_ptr = ptr;
ptr = find_bytecode_comment(ptr + 1, count - 1, FOURCC_PRES, &pres_size);
if (!ptr)
TRACE("No preshader found.\n");
@@ -1292,6 +1295,17 @@ HRESULT d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte
goto err_out;
}
+ if (shader)
+ {
+ if (FAILED(ret = get_constants_desc(shader_ptr, &peval->shader_inputs, base_effect,
+ skip_constants, skip_constants_count, &peval->pres)))
+ {
+ TRACE("Could not get shader constant table, hr %#x.\n", ret);
+ goto err_out;
+ }
+ update_table_sizes_consts(peval->pres.regs.table_sizes, &peval->shader_inputs);
+ }
+
for (i = PRES_REGTAB_FIRST_SHADER; i < PRES_REGTAB_COUNT; ++i)
{
if (FAILED(ret = regstore_alloc_table(&peval->pres.regs, i)))
@@ -1416,7 +1430,6 @@ static void regstore_set_data(struct d3dx_regstore *rs, unsigned int table,
}
set_const_funcs[param_type][table_type]((unsigned int *)rs->tables[table] + offset, in, count);
- regstore_set_modified(rs, table, offset, count);
}
static HRESULT set_constants_device(ID3DXEffectStateManager *manager, struct IDirect3DDevice9 *device,
@@ -1460,24 +1473,31 @@ static HRESULT set_constants_device(ID3DXEffectStateManager *manager, struct IDi
}
}
-static void set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const_tab,
- ULONG64 new_update_version)
+static HRESULT set_constants(struct d3dx_regstore *rs, struct d3dx_const_tab *const_tab,
+ ULONG64 new_update_version, ID3DXEffectStateManager *manager, struct IDirect3DDevice9 *device,
+ D3DXPARAMETER_TYPE type, BOOL device_update_all, BOOL pres_dirty)
{
unsigned int const_idx;
+ unsigned int current_start = 0, current_count = 0;
+ enum pres_reg_tables current_table = PRES_REGTAB_COUNT;
+ BOOL update_device = manager || device;
+ HRESULT hr, result = D3D_OK;
+ ULONG64 update_version = const_tab->update_version;
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];
- unsigned int table = const_set->table;
+ enum pres_reg_tables table = const_set->table;
struct d3dx_parameter *param = const_set->param;
unsigned int element, i, j, start_offset;
struct const_upload_info info;
- unsigned int *data = param->data;
+ unsigned int *data;
enum pres_value_type param_type;
- if (!is_param_dirty(param, const_tab->update_version))
+ if (!(param && is_param_dirty(param, update_version)))
continue;
+ data = param->data;
start_offset = get_offset_reg(table, const_set->register_index);
if (const_set->direct_copy)
{
@@ -1529,22 +1549,54 @@ 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;
-}
+ 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 == current_table && current_start + current_count == const_set->register_index)
+ {
+ current_count += const_set->register_count * const_set->element_count;
+ }
+ else
+ {
+ if (current_count)
+ {
+ if (FAILED(hr = set_constants_device(manager, device, type, current_table,
+ (DWORD *)rs->tables[current_table]
+ + get_offset_reg(current_table, current_start), current_start, current_count)))
+ result = hr;
+ }
+ current_table = table;
+ current_start = const_set->register_index;
+ current_count = const_set->register_count * const_set->element_count;
+ }
+ }
+ }
+ if (current_count)
+ {
+ if (FAILED(hr = set_constants_device(manager, device, type, current_table,
+ (DWORD *)rs->tables[current_table]
+ + get_offset_reg(current_table, current_start), current_start, current_count)))
+ result = hr;
+ }
+ return result;
+}
static double exec_get_reg_value(struct d3dx_regstore *rs, enum pres_reg_tables table, unsigned int offset)
{
- if (!regstore_is_val_set_reg(rs, table, get_reg_offset(table, offset)))
- WARN("Using uninitialized input, table %u, offset %u.\n", table, offset);
-
return regstore_get_double(rs, table, offset);
}
@@ -1640,23 +1692,6 @@ static HRESULT execute_preshader(struct d3dx_preshader *pres)
return D3D_OK;
}
-static void set_preshader_modified(struct d3dx_preshader *pres)
-{
- unsigned int i;
-
- for (i = 0; i < pres->ins_count; ++i)
- {
- const struct d3dx_pres_ins *ins = &pres->ins[i];
- const struct d3dx_pres_reg *reg = &ins->output.reg;
-
- if (reg->table == PRES_REGTAB_TEMP)
- continue;
-
- regstore_set_modified(&pres->regs, reg->table, reg->offset,
- pres_op_info[ins->op].func_all_comps ? 1 : ins->component_count);
- }
-}
-
static BOOL is_const_tab_input_dirty(struct d3dx_const_tab *ctab, ULONG64 update_version)
{
unsigned int i;
@@ -1691,7 +1726,8 @@ HRESULT d3dx_evaluate_parameter(struct d3dx_param_eval *peval, const struct d3dx
if (is_const_tab_input_dirty(&peval->pres.inputs, ULONG64_MAX))
{
set_constants(&peval->pres.regs, &peval->pres.inputs,
- next_update_version(peval->version_counter));
+ next_update_version(peval->version_counter),
+ NULL, NULL, peval->param_type, FALSE, FALSE);
if (FAILED(hr = execute_preshader(&peval->pres)))
return hr;
@@ -1706,93 +1742,26 @@ HRESULT d3dx_evaluate_parameter(struct d3dx_param_eval *peval, const struct d3dx
return D3D_OK;
}
-static HRESULT set_shader_constants_device(ID3DXEffectStateManager *manager, struct IDirect3DDevice9 *device,
- struct d3dx_regstore *rs, D3DXPARAMETER_TYPE type, enum pres_reg_tables table)
-{
- unsigned int start, count;
- void *ptr;
- HRESULT hr, result;
-
- result = D3D_OK;
- start = 0;
- while (start < rs->table_sizes[table])
- {
- count = 0;
- while (start < rs->table_sizes[table] && !regstore_is_val_set_reg(rs, table, start))
- ++start;
- while (start + count < rs->table_sizes[table] && regstore_is_val_set_reg(rs, table, start + count))
- ++count;
- if (!count)
- break;
- TRACE("Setting %u constants at %u.\n", count, start);
- ptr = (BYTE *)rs->tables[table] + get_offset_reg(table, start)
- * table_info[table].component_size;
-
- if (FAILED(hr = set_constants_device(manager, device, type, table, ptr, start, count)))
- {
- ERR("Setting constants failed, type %u, table %u, hr %#x.\n", type, table, hr);
- result = hr;
- }
- start += count;
- }
- regstore_reset_modified(rs, table);
- return result;
-}
-
HRESULT d3dx_param_eval_set_shader_constants(ID3DXEffectStateManager *manager, struct IDirect3DDevice9 *device,
struct d3dx_param_eval *peval, BOOL update_all)
{
- static const enum pres_reg_tables set_tables[] =
- {PRES_REGTAB_OCONST, PRES_REGTAB_OICONST, PRES_REGTAB_OBCONST};
- HRESULT hr, result;
+ HRESULT hr;
struct d3dx_preshader *pres = &peval->pres;
struct d3dx_regstore *rs = &pres->regs;
- unsigned int i;
ULONG64 new_update_version = next_update_version(peval->version_counter);
- BOOL update_device = update_all;
+ BOOL pres_dirty = FALSE;
TRACE("device %p, peval %p, param_type %u.\n", device, peval, peval->param_type);
if (is_const_tab_input_dirty(&pres->inputs, ULONG64_MAX))
{
- set_constants(rs, &pres->inputs, new_update_version);
+ set_constants(rs, &pres->inputs, new_update_version,
+ NULL, NULL, peval->param_type, FALSE, FALSE);
if (FAILED(hr = execute_preshader(pres)))
return hr;
- update_device = TRUE;
+ pres_dirty = TRUE;
}
- if (is_const_tab_input_dirty(&peval->shader_inputs, ULONG64_MAX))
- {
- set_constants(rs, &peval->shader_inputs, new_update_version);
- update_device = TRUE;
- }
- result = D3D_OK;
-
- if (update_device)
- {
- if (update_all)
- {
- for (i = 0; i < peval->shader_inputs.input_count; ++i)
- {
- unsigned int table;
-
- if (!peval->shader_inputs.inputs[i].RegisterCount)
- continue;
- table = peval->shader_inputs.regset2table[peval->shader_inputs.inputs[i].RegisterSet];
- if (table < PRES_REGTAB_COUNT)
- regstore_set_modified_reg(rs, table,
- peval->shader_inputs.inputs[i].RegisterIndex,
- peval->shader_inputs.inputs[i].RegisterIndex
- + peval->shader_inputs.inputs[i].RegisterCount - 1);
- }
- set_preshader_modified(pres);
- }
-
- for (i = 0; i < ARRAY_SIZE(set_tables); ++i)
- {
- if (FAILED(hr = set_shader_constants_device(manager, device, rs, peval->param_type, set_tables[i])))
- result = hr;
- }
- }
- return result;
+ return set_constants(rs, &peval->shader_inputs, new_update_version,
+ manager, device, peval->param_type, update_all, pres_dirty);
}
--
2.13.5
More information about the wine-patches
mailing list