[PATCH 2/3] d3dx9: Support relative addressing in preshader.

Paul Gofman gofmanp at gmail.com
Thu Mar 23 10:06:58 CDT 2017


Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
 dlls/d3dx9_36/preshader.c    | 103 ++++++++++++++++++++++++++++++++++++-------
 dlls/d3dx9_36/tests/effect.c |  38 ++++++++--------
 2 files changed, 106 insertions(+), 35 deletions(-)

diff --git a/dlls/d3dx9_36/preshader.c b/dlls/d3dx9_36/preshader.c
index 9aedc99..2974ffd 100644
--- a/dlls/d3dx9_36/preshader.c
+++ b/dlls/d3dx9_36/preshader.c
@@ -191,6 +191,8 @@ struct d3dx_pres_operand
     /* offset is component index, not register index, e. g.
        offset for component c3.y is 13 (3 * 4 + 1) */
     unsigned int offset;
+    enum pres_reg_tables base_reg_table;
+    unsigned int base_reg_offset;
 };
 
 #define MAX_INPUTS_COUNT 8
@@ -368,7 +370,7 @@ static unsigned int *find_bytecode_comment(unsigned int *ptr, unsigned int count
     return NULL;
 }
 
-static unsigned int *parse_pres_arg(unsigned int *ptr, unsigned int count, struct d3dx_pres_operand *opr)
+static unsigned int *parse_pres_reg(unsigned int *ptr, enum pres_reg_tables *table, unsigned int *offset)
 {
     static const enum pres_reg_tables reg_table[8] =
     {
@@ -376,26 +378,41 @@ static unsigned int *parse_pres_arg(unsigned int *ptr, unsigned int count, struc
         PRES_REGTAB_OCONST, PRES_REGTAB_OBCONST, PRES_REGTAB_OICONST, PRES_REGTAB_TEMP
     };
 
-    if (count < 3)
+    if (*ptr >= ARRAY_SIZE(reg_table) || reg_table[*ptr] == PRES_REGTAB_COUNT)
     {
-        WARN("Byte code buffer ends unexpectedly.\n");
+        FIXME("Unsupported register table %#x.\n", *ptr);
         return NULL;
     }
 
-    if (*ptr)
+    *table = reg_table[*ptr++];
+    *offset = *ptr++;
+    return ptr;
+}
+
+static unsigned int *parse_pres_arg(unsigned int *ptr, unsigned int count, struct d3dx_pres_operand *opr)
+{
+    if (count < 3 || (*ptr && count < 5))
     {
-        FIXME("Relative addressing not supported yet, word %#x.\n", *ptr);
+        WARN("Byte code buffer ends unexpectedly, count %u.\n", count);
         return NULL;
     }
-    ++ptr;
 
-    if (*ptr >= ARRAY_SIZE(reg_table) || reg_table[*ptr] == PRES_REGTAB_COUNT)
+    if (*ptr)
     {
-        FIXME("Unsupported register table %#x.\n", *ptr);
-        return NULL;
+        if (*ptr != 1)
+        {
+            FIXME("Unknown relative addressing flag, word %#x.\n", *ptr);
+            return NULL;
+        }
+        ptr = parse_pres_reg(ptr + 1, &opr->base_reg_table, &opr->base_reg_offset);
+    }
+    else
+    {
+        opr->base_reg_table = PRES_REGTAB_COUNT;
+        ++ptr;
     }
-    opr->table = reg_table[*ptr++];
-    opr->offset = *ptr++;
+
+    ptr = parse_pres_reg(ptr, &opr->table, &opr->offset);
 
     if (opr->table == PRES_REGTAB_OBCONST)
         opr->offset /= 4;
@@ -452,6 +469,12 @@ static unsigned int *parse_pres_ins(unsigned int *ptr, unsigned int count, struc
         ptr = p;
     }
     ptr = parse_pres_arg(ptr, count, &ins->output);
+    if (ins->output.base_reg_table != PRES_REGTAB_COUNT)
+    {
+        FIXME("Relative addressing in output register not supported.\n");
+        return NULL;
+    }
+
     return ptr;
 }
 
@@ -567,7 +590,7 @@ static void dump_arg(struct d3dx_regstore *rs, const struct d3dx_pres_operand *a
     unsigned int i, table;
 
     table = arg->table;
-    if (table == PRES_REGTAB_IMMED)
+    if (table == PRES_REGTAB_IMMED && arg->base_reg_table == PRES_REGTAB_COUNT)
     {
         TRACE("(");
         for (i = 0; i < component_count; ++i)
@@ -577,7 +600,20 @@ static void dump_arg(struct d3dx_regstore *rs, const struct d3dx_pres_operand *a
     }
     else
     {
-        TRACE("%s%u.", table_symbol[table], get_reg_offset(table, arg->offset));
+        if (arg->base_reg_table == PRES_REGTAB_COUNT)
+        {
+            TRACE("%s%u.", table_symbol[table], get_reg_offset(table, arg->offset));
+        }
+        else
+        {
+            unsigned int base_reg;
+
+            base_reg = get_reg_offset(arg->base_reg_table, arg->base_reg_offset);
+            TRACE("%s[%u + %s%u.%c].", table_symbol[table], get_reg_offset(table, arg->offset),
+                    table_symbol[arg->base_reg_table], base_reg,
+                    xyzw_str[arg->base_reg_offset
+                    - base_reg * table_info[arg->base_reg_table].reg_component_count]);
+        }
         for (i = 0; i < component_count; ++i)
             TRACE("%c", xyzw_str[(arg->offset + i) % 4]);
     }
@@ -1088,12 +1124,47 @@ static HRESULT init_set_constants(struct d3dx_const_tab *const_tab, ID3DXConstan
     return ret;
 }
 
+static double exec_get_reg_value(struct d3dx_regstore *rs, enum pres_reg_tables table, unsigned int offset)
+{
+    unsigned int size;
+
+    size = rs->table_sizes[table] * table_info[table].reg_component_count;
+    if (offset >= size)
+    {
+        if ((offset & 255) < size)
+            offset &= 255;
+        else
+            offset = offset % size;
+    }
+
+    if (!regstore_is_val_set_reg(rs, table, offset / table_info[table].reg_component_count))
+        WARN("Using uninitialized input, table %u, offset %u.\n", table, offset);
+
+    return regstore_get_double(rs, table, offset);
+}
+
 static double exec_get_arg(struct d3dx_regstore *rs, const struct d3dx_pres_operand *opr, unsigned int comp)
 {
-    if (!regstore_is_val_set_reg(rs, opr->table, (opr->offset + comp) / table_info[opr->table].reg_component_count))
-        WARN("Using uninitialized input, table %u, offset %u.\n", opr->table, opr->offset + comp);
+    unsigned int base_offset, index;
+
+    if (opr->base_reg_table == PRES_REGTAB_COUNT)
+        index = 0;
+    else
+        index = (int)exec_get_reg_value(rs, opr->base_reg_table, opr->base_reg_offset);
+
+    if (index >= rs->table_sizes[opr->table] && opr->table == PRES_REGTAB_CONST)
+    {
+        unsigned int size_pow2;
+
+        for (size_pow2 = 1; size_pow2 < rs->table_sizes[opr->table]; size_pow2 <<= 1)
+            ;
+        index &= (size_pow2 - 1);
+        if (index >= rs->table_sizes[opr->table])
+            return 0.0;
+    }
 
-    return regstore_get_double(rs, opr->table, opr->offset + comp);
+    base_offset = index * 4;
+    return exec_get_reg_value(rs, opr->table, base_offset + opr->offset + comp);
 }
 
 static void exec_set_arg(struct d3dx_regstore *rs, const struct d3dx_pres_operand *opr,
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c
index 54f5377..622a8d5 100644
--- a/dlls/d3dx9_36/tests/effect.c
+++ b/dlls/d3dx9_36/tests/effect.c
@@ -3971,7 +3971,7 @@ test_effect_preshader_op_expected[] =
     {"prec",   {FALSE, FALSE,  TRUE, FALSE}, {0x2b8cbccc, 0x2c0cbccc, 0xac531800, 0x00000000}},
 
     {"dotswiz", {FALSE, FALSE, FALSE, FALSE}, {0xc00ccccd, 0xc0d33334, 0xc10ccccd, 0}},
-    {"reladdr", { TRUE,  TRUE,  TRUE,  TRUE}, {0xc00ccccd, 0x40000000, 0x41a00000, 0x41500000}},
+    {"reladdr", {FALSE, FALSE, FALSE, FALSE}, {0xc00ccccd, 0x40000000, 0x41a00000, 0x41500000}},
 };
 
 enum expected_state_update
@@ -4207,7 +4207,7 @@ static void test_effect_preshader(IDirect3DDevice9 *device)
     ok(hr == D3D_OK, "SetVector failed, hr %#x.\n", hr);
 
     hr = effect->lpVtbl->BeginPass(effect, 0);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
 
     hr = effect->lpVtbl->BeginPass(effect, 0);
     ok(hr == D3DERR_INVALIDCALL, "Got result %#x.\n", hr);
@@ -4375,7 +4375,7 @@ static void test_preshader_op(IDirect3DDevice9 *device, const DWORD *sample_effe
     }
 
     hr = effect->lpVtbl->BeginPass(effect, 0);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
 
     hr = IDirect3DDevice9_GetLight(device, blob_position[test->args_count].result_index, &light);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
@@ -4674,7 +4674,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
 
     hr = effect->lpVtbl->BeginPass(effect, 0);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
 
     for (i = 0; i < ARRAY_SIZE(check_op_parameters); ++i)
     {
@@ -4692,7 +4692,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
         hr = effect->lpVtbl->SetValue(effect, param, &fvect, sizeof(fvect));
         ok(hr == D3D_OK, "Got result %#x.\n", hr);
         hr = effect->lpVtbl->CommitChanges(effect);
-        todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+        ok(hr == D3D_OK, "Got result %#x.\n", hr);
 
         test_effect_preshader_op_results(device, check_op_parameters[i].state_updated,
                 check_op_parameters[i].param_name);
@@ -4710,7 +4710,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
         hr = effect->lpVtbl->SetValue(effect, param, buffer, sizeof(buffer));
         ok(hr == D3D_OK, "Got result %#x.\n", hr);
         hr = effect->lpVtbl->CommitChanges(effect);
-        todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+        ok(hr == D3D_OK, "Got result %#x.\n", hr);
 
         test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[i].const_updated_mask,
                 check_vconsts_parameters[i].param_name);
@@ -4723,7 +4723,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetVectorArray(effect, param, &fvect, 1);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[0].const_updated_mask,
                 check_vconsts_parameters[0].param_name);
 
@@ -4735,7 +4735,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetFloat(effect, param, 92.0f);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     test_effect_preshader_compare_vconsts(device, const_no_update_mask,
                 check_vconsts_parameters[10].param_name);
 
@@ -4748,7 +4748,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetValue(effect, param, &fvect.x, sizeof(fvect.x));
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[10].const_updated_mask,
                 check_vconsts_parameters[10].param_name);
 
@@ -4759,7 +4759,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetFloatArray(effect, param, &fvect.x, 1);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[10].const_updated_mask,
                 check_vconsts_parameters[10].param_name);
 
@@ -4771,7 +4771,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetInt(effect, param, 93);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     test_effect_preshader_compare_vconsts(device, const_no_update_mask,
                 check_vconsts_parameters[10].param_name);
 
@@ -4782,7 +4782,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetVector(effect, param, &fvect);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[1].const_updated_mask,
                 check_vconsts_parameters[1].param_name);
 
@@ -4797,7 +4797,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetValue(effect, param, &fvect.x, sizeof(float));
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     test_effect_preshader_compare_vconsts(device, check_vconsts_parameters[7].const_updated_mask,
                 check_vconsts_parameters[7].param_name);
 
@@ -4822,7 +4822,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetValue(effect, param, &fvect, sizeof(float) * 3);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGDENSITY, &value);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     ok(value == 0, "Unexpected fog density %g.\n", *(float *)&value);
@@ -4861,7 +4861,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetValue(effect, param, &fvect.x, sizeof(float));
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_FOGDENSITY, &value);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     ok(*(float *)&value == 9999.0f, "Unexpected fog density %g.\n", *(float *)&value);
@@ -4897,7 +4897,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     test_effect_preshader_clear_vconsts(device);
 
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
 
     hr = IDirect3DDevice9_GetVertexShader(device, &vshader);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
@@ -4918,7 +4918,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect));
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = IDirect3DDevice9_GetVertexShader(device, &vshader);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     ok(!vshader, "Got non NULL vshader.\n");
@@ -4928,7 +4928,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect));
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = IDirect3DDevice9_GetVertexShader(device, &vshader);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     ok(!!vshader, "Got NULL vshader.\n");
@@ -4945,7 +4945,7 @@ static void test_effect_commitchanges(IDirect3DDevice9 *device)
     hr = effect->lpVtbl->SetValue(effect, param, ivect, sizeof(ivect));
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
     hr = effect->lpVtbl->CommitChanges(effect);
-    todo_wine ok(hr == D3D_OK, "Got result %#x.\n", hr);
+    ok(hr == D3D_OK, "Got result %#x.\n", hr);
     test_effect_preshader_compare_vconsts(device, NULL, NULL);
 
     hr = effect->lpVtbl->EndPass(effect);
-- 
2.9.3




More information about the wine-patches mailing list