[v2 1/2] d3dx9: Support relative addressing in preshader.

Matteo Bruni matteo.mystral at gmail.com
Mon Apr 3 10:35:03 CDT 2017


2017-03-29 20:17 GMT+02:00 Matteo Bruni <matteo.mystral at gmail.com>:
> Yeah and temporaries are supposed to be written before being read so
> in theory you can entirely skip the update_table_size() calls for
> source arguments.

I haven't looked in detail but this still works for me (i.e.
commenting out those calls doesn't break the tests here, on 32 bits at
least). How does the accidental CTAB overwriting you mention happen
exactly?

> Hmm, I've never seen any effect with a number of immediates not
> multiple of 4. Can you point me to one?

Do you have one of those?

For reference, I'm attaching a patch with some hacks regarding these
two points above and various debug stuff.
-------------- next part --------------
From 932cfccd6de6f774bbde7babe1eb83d6280f2801 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <mbruni at codeweavers.com>
Date: Tue, 28 Mar 2017 21:11:47 +0200
Subject: [PATCH] d3dx9: Make PRES_REGTAB_IMMED 4-components, comment out
 update_table_size() calls for inputs, various debug stuff...

---
 dlls/d3dx9_36/preshader.c    | 73 ++++++++++++++++++++++++++++----------------
 dlls/d3dx9_36/tests/effect.c |  1 +
 2 files changed, 48 insertions(+), 26 deletions(-)

diff --git a/dlls/d3dx9_36/preshader.c b/dlls/d3dx9_36/preshader.c
index 6cd1d60..e7228f6 100644
--- a/dlls/d3dx9_36/preshader.c
+++ b/dlls/d3dx9_36/preshader.c
@@ -155,7 +155,7 @@ static const struct
 }
 table_info[] =
 {
-    {sizeof(double), 1, PRES_VT_DOUBLE}, /* PRES_REGTAB_IMMED */
+    {sizeof(double), 4, PRES_VT_DOUBLE}, /* PRES_REGTAB_IMMED */
     {sizeof(float),  4, PRES_VT_FLOAT }, /* PRES_REGTAB_CONST */
     {sizeof(float),  4, PRES_VT_FLOAT }, /* PRES_REGTAB_OCONST */
     {sizeof(BOOL),   1, PRES_VT_BOOL  }, /* PRES_REGTAB_OBCONST */
@@ -223,17 +223,23 @@ static HRESULT init_set_constants(struct d3dx_const_tab *const_tab, ID3DXConstan
 
 static HRESULT regstore_alloc_table(struct d3dx_regstore *rs, unsigned int table)
 {
-    unsigned int size;
+    unsigned int size, tvs_size;
 
     size = rs->table_sizes[table] * table_info[table].reg_component_count * table_info[table].component_size;
+    tvs_size = sizeof(*rs->table_value_set[table]) *
+            ((rs->table_sizes[table] + PRES_BITMASK_BLOCK_SIZE - 1) / PRES_BITMASK_BLOCK_SIZE);
+    TRACE("size %u, tvs_size %u.\n", size, tvs_size);
     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));
+        rs->table_value_set[table] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, tvs_size);
         if (!rs->tables[table] || !rs->table_value_set[table])
+        {
+            WARN("Out of memory!\n");
+            TRACE("rs->tables[table] %p, rs->table_value_set[table] %p.\n",
+                    rs->tables[table], rs->table_value_set[table]);
             return E_OUTOFMEMORY;
+        }
     }
     return D3D_OK;
 }
@@ -598,6 +604,7 @@ static void dump_arg(struct d3dx_regstore *rs, const struct d3dx_pres_operand *a
     table = arg->reg.table;
     if (table == PRES_REGTAB_IMMED && arg->index_reg.table == PRES_REGTAB_COUNT)
     {
+        TRACE("imm%u", arg->reg.offset);
         TRACE("(");
         for (i = 0; i < component_count; ++i)
             TRACE(i < component_count - 1 ? "%.16e, " : "%.16e",
@@ -653,7 +660,7 @@ static void dump_ins(struct d3dx_regstore *rs, const struct d3dx_pres_ins *ins)
 
 static void dump_preshader(struct d3dx_preshader *pres)
 {
-    unsigned int i, immediate_count = pres->regs.table_sizes[PRES_REGTAB_IMMED];
+    unsigned int i, immediate_count = pres->regs.table_sizes[PRES_REGTAB_IMMED] * 4;
     const double *immediates = pres->regs.tables[PRES_REGTAB_IMMED];
 
     if (immediate_count)
@@ -678,7 +685,7 @@ static void dump_preshader(struct d3dx_preshader *pres)
 static HRESULT parse_preshader(struct d3dx_preshader *pres, unsigned int *ptr, unsigned int count, struct d3dx9_base_effect *base)
 {
     unsigned int *p;
-    unsigned int i, j, const_count;
+    unsigned int i, const_count;
     double *dconst;
     HRESULT hr;
     unsigned int saved_word;
@@ -747,28 +754,28 @@ static HRESULT parse_preshader(struct d3dx_preshader *pres, unsigned int *ptr, u
     if (FAILED(hr))
         return hr;
 
-    pres->regs.table_sizes[PRES_REGTAB_IMMED] = const_count;
+    pres->regs.table_sizes[PRES_REGTAB_IMMED] = const_count / 4;
 
     for (i = 0; i < pres->ins_count; ++i)
     {
-        for (j = 0; j < pres_op_info[pres->ins[i].op].input_count; ++j)
-        {
-            enum pres_reg_tables table;
-            unsigned int reg_idx;
-
-            if (pres->ins[i].inputs[j].index_reg.table == PRES_REGTAB_COUNT)
-            {
-                table = pres->ins[i].inputs[j].reg.table;
-                reg_idx = get_reg_offset(table, pres->ins[i].inputs[j].reg.offset
-                        + pres->ins[i].component_count - 1);
-            }
-            else
-            {
-                table = pres->ins[i].inputs[j].index_reg.table;
-                reg_idx = get_reg_offset(table, pres->ins[i].inputs[j].index_reg.offset);
-            }
-            update_table_size(pres->regs.table_sizes, table, reg_idx);
-        }
+        /* for (j = 0; j < pres_op_info[pres->ins[i].op].input_count; ++j) */
+        /* { */
+        /*     enum pres_reg_tables table; */
+        /*     unsigned int reg_idx; */
+
+        /*     if (pres->ins[i].inputs[j].index_reg.table == PRES_REGTAB_COUNT) */
+        /*     { */
+        /*         table = pres->ins[i].inputs[j].reg.table; */
+        /*         reg_idx = get_reg_offset(table, pres->ins[i].inputs[j].reg.offset */
+        /*                 + pres->ins[i].component_count - 1); */
+        /*     } */
+        /*     else */
+        /*     { */
+        /*         table = pres->ins[i].inputs[j].index_reg.table; */
+        /*         reg_idx = get_reg_offset(table, pres->ins[i].inputs[j].index_reg.offset); */
+        /*     } */
+        /*     update_table_size(pres->regs.table_sizes, table, reg_idx); */
+        /* } */
         update_table_size(pres->regs.table_sizes, pres->ins[i].output.reg.table,
                 get_reg_offset(pres->ins[i].output.reg.table,
                 pres->ins[i].output.reg.offset + pres->ins[i].component_count - 1));
@@ -1200,10 +1207,14 @@ static double exec_get_arg(struct d3dx_regstore *rs, const struct d3dx_pres_oper
         reg_index %= wrap_size;
 
         if (reg_index >= rs->table_sizes[table])
+        {
+            WARN("Wrapped offset out of bounds, using 0.0.\n");
             return 0.0;
+        }
 
         offset = reg_index * table_info[table].reg_component_count
                 + offset % table_info[table].reg_component_count;
+        WARN("Wrapping register index to %u.\n", offset);
     }
 
     return exec_get_reg_value(rs, table, offset);
@@ -1229,6 +1240,7 @@ static HRESULT execute_preshader(struct d3dx_preshader *pres)
 
         ins = &pres->ins[i];
         oi = &pres_op_info[ins->op];
+        TRACE("Executing instruction %s with arguments ", pres_op_info[ins->op].mnem);
         if (oi->func_all_comps)
         {
             if (oi->input_count * ins->component_count > ARGS_ARRAY_SIZE)
@@ -1238,23 +1250,32 @@ static HRESULT execute_preshader(struct d3dx_preshader *pres)
             }
             for (k = 0; k < oi->input_count; ++k)
                 for (j = 0; j < ins->component_count; ++j)
+                {
                     args[k * ins->component_count + j] = exec_get_arg(&pres->regs, &ins->inputs[k],
                             ins->scalar_op && !k ? 0 : j);
+                    TRACE("%g ", args[k]);
+                }
             res = oi->func(args, ins->component_count);
 
             /* only 'dot' instruction currently falls here */
             exec_set_arg(&pres->regs, &ins->output.reg, 0, res);
+            TRACE(" -> %g ", res);
         }
         else
         {
             for (j = 0; j < ins->component_count; ++j)
             {
                 for (k = 0; k < oi->input_count; ++k)
+                {
                     args[k] = exec_get_arg(&pres->regs, &ins->inputs[k], ins->scalar_op && !k ? 0 : j);
+                    TRACE("%g ", args[k]);
+                }
                 res = oi->func(args, ins->component_count);
                 exec_set_arg(&pres->regs, &ins->output.reg, j, res);
+                TRACE(" -> %g ", res);
             }
         }
+        TRACE("\n");
     }
     return D3D_OK;
 }
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c
index bddb8dd3..9d52926 100644
--- a/dlls/d3dx9_36/tests/effect.c
+++ b/dlls/d3dx9_36/tests/effect.c
@@ -5238,6 +5238,7 @@ static void test_effect_preshader_relative_addressing(IDirect3DDevice9 *device)
         expected = test_out_of_bounds_index[i].expected;
         expected_float = (const float *)expected;
 
+        trace("Test %u.\n", i);
         for (j = 0; j < 4; ++j)
         {
             ok(compare_float(v[j], expected_float[j], 0),
-- 
2.10.2



More information about the wine-devel mailing list