[v7 7/7] d3dx9: Implement setting named shader constants in effect.

Paul Gofman gofmanp at gmail.com
Mon Mar 28 02:20:27 CDT 2016


Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
Changes
- Use BOOL for the vs flag in d3dx_set_shader_const_fxlc
- Turn SET_TABLE macro in d3dx_param_eval_set_shader_constants into function

 dlls/d3dx9_36/d3dx9_private.h |   2 +
 dlls/d3dx9_36/effect.c        |  58 +++++++++++++++++++---
 dlls/d3dx9_36/preshader.c     | 113 ++++++++++++++++++++++++++++++++++++++++++
 dlls/d3dx9_36/tests/effect.c  |   4 +-
 4 files changed, 169 insertions(+), 8 deletions(-)

diff --git a/dlls/d3dx9_36/d3dx9_private.h b/dlls/d3dx9_36/d3dx9_private.h
index 9ba0fac..9eab997 100644
--- a/dlls/d3dx9_36/d3dx9_private.h
+++ b/dlls/d3dx9_36/d3dx9_private.h
@@ -197,5 +197,7 @@ HRESULT d3dx_create_param_eval(struct d3dx9_base_effect *base_effect, void *byte
 void d3dx_free_param_eval(struct d3dx_param_eval *peval) DECLSPEC_HIDDEN;
 HRESULT d3dx_evaluate_parameter(struct d3dx_param_eval *peval,
         struct d3dx_parameter *param, void **param_value) DECLSPEC_HIDDEN;
+HRESULT d3dx_param_eval_set_shader_constants(struct IDirect3DDevice9 *device,
+        struct d3dx_param_eval *peval) DECLSPEC_HIDDEN;
 
 #endif /* __WINE_D3DX9_PRIVATE_H */
diff --git a/dlls/d3dx9_36/effect.c b/dlls/d3dx9_36/effect.c
index 2dbb610..a5d9f59 100644
--- a/dlls/d3dx9_36/effect.c
+++ b/dlls/d3dx9_36/effect.c
@@ -2726,7 +2726,51 @@ static HRESULT d3dx_set_shader_const_state(IDirect3DDevice9 *device, enum SHADER
 }
 
 static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass,
-        struct d3dx_state *state, int parent_index)
+        struct d3dx_state *state, unsigned int parent_index);
+
+HRESULT d3dx_set_shader_const_fxlc(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass,
+        struct d3dx_parameter *param, BOOL vs)
+{
+    IDirect3DDevice9 *device = effect->device;
+    HRESULT hr, ret;
+    struct d3dx_parameter **params;
+    D3DXCONSTANT_DESC *cdesc;
+    unsigned int parameters_count;
+    unsigned int i, j;
+
+    if (!param->param_eval)
+    {
+        FIXME("Preshader structure is null.\n");
+        return D3DERR_INVALIDCALL;
+    }
+    if (FAILED(hr = d3dx_param_eval_set_shader_constants(device, param->param_eval)))
+        return hr;
+    params = param->param_eval->shader_inputs.inputs_param;
+    cdesc = param->param_eval->shader_inputs.inputs;
+    parameters_count = param->param_eval->shader_inputs.input_count;
+    ret = D3D_OK;
+    for (i = 0; i < parameters_count; i++)
+    {
+        if (params[i] && params[i]->class == D3DXPC_OBJECT && params[i]->type == D3DXPT_SAMPLER)
+        {
+            struct d3dx_sampler *sampler;
+
+            sampler = (struct d3dx_sampler *)params[i]->data;
+            TRACE("sampler %s, register index %u, state count %u.\n", params[i]->name,
+                    cdesc[i].RegisterIndex, sampler->state_count);
+            for (j = 0; j < sampler->state_count; j++)
+            {
+                if (FAILED(hr = d3dx9_apply_state(effect, pass, &sampler->states[j],
+                        cdesc[i].RegisterIndex + (vs ? D3DVERTEXTEXTURESAMPLER0 : 0))))
+                    ret = hr;
+            }
+        }
+    }
+    return ret;
+}
+
+static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pass *pass,
+        struct d3dx_state *state, unsigned int parent_index)
 {
     IDirect3DDevice9 *device = effect->device;
     struct d3dx_parameter *param;
@@ -2752,7 +2796,7 @@ static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pas
         {
             UINT unit;
 
-            unit = parent_index == -1 ? state->index : parent_index;
+            unit = parent_index == ~0u ? state->index : parent_index;
             TRACE("%s, unit %u, value %p.\n", state_table[state->operation].name, unit,
                     *(IDirect3DBaseTexture9 **)param_value);
             return IDirect3DDevice9_SetTexture(device, unit, *(IDirect3DBaseTexture9 **)param_value);
@@ -2782,7 +2826,7 @@ static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pas
         {
             UINT sampler;
 
-            sampler = parent_index == -1 ? state->index : parent_index;
+            sampler = parent_index == ~0u ? state->index : parent_index;
             TRACE("%s, sampler %u, value %u.\n", state_table[state->operation].name, sampler, *(DWORD *)param_value);
             return IDirect3DDevice9_SetSamplerState(device, sampler, state_table[state->operation].op,
                     *(DWORD *)param_value);
@@ -2791,13 +2835,15 @@ static HRESULT d3dx9_apply_state(struct ID3DXEffectImpl *effect, struct d3dx_pas
             TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DVertexShader9 **)param_value);
             if (FAILED(hr = IDirect3DDevice9_SetVertexShader(device, *(IDirect3DVertexShader9 **)param_value)))
                 ERR("Could not set vertex shader, hr %#x.\n", hr);
-            FIXME("Not executing preshader and not setting constants.\n");
+            else if (*(IDirect3DVertexShader9 **)param_value)
+                hr = d3dx_set_shader_const_fxlc(effect, pass, param, TRUE);
             return hr;
         case SC_PIXELSHADER:
             TRACE("%s, shader %p.\n", state_table[state->operation].name, *(IDirect3DPixelShader9 **)param_value);
             if (FAILED(hr = IDirect3DDevice9_SetPixelShader(device, *(IDirect3DPixelShader9 **)param_value)))
                 ERR("Could not set pixel shader, hr %#x.\n", hr);
-            FIXME("Not executing preshader and not setting constants.\n");
+            else if (*(IDirect3DPixelShader9 **)param_value)
+                hr = d3dx_set_shader_const_fxlc(effect, pass, param, FALSE);
             return hr;
         case SC_TRANSFORM:
             TRACE("%s, state %u.\n", state_table[state->operation].name, state->index);
@@ -2861,7 +2907,7 @@ static HRESULT d3dx9_apply_pass_states(struct ID3DXEffectImpl *effect, struct d3
     {
         HRESULT hr;
 
-        if (FAILED(hr = d3dx9_apply_state(effect, pass, &pass->states[i], -1)))
+        if (FAILED(hr = d3dx9_apply_state(effect, pass, &pass->states[i], ~0u)))
         {
             WARN("Error applying state, hr %#x.\n", hr);
             ret = hr;
diff --git a/dlls/d3dx9_36/preshader.c b/dlls/d3dx9_36/preshader.c
index 875228a..2e4b75b 100644
--- a/dlls/d3dx9_36/preshader.c
+++ b/dlls/d3dx9_36/preshader.c
@@ -296,6 +296,18 @@ static void regstore_set_double(struct d3dx_regstore *rs, unsigned int table, un
             1u << (reg_idx % PRES_BITMASK_BLOCK_SIZE);
 }
 
+static void regstore_reset_table(struct d3dx_regstore *rs, unsigned int table)
+{
+    unsigned int size;
+
+    size = rs->table_sizes[table] * table_info[table].reg_component_count * table_info[table].component_size;
+
+    memset(rs->tables[table], 0, size);
+    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)
 {
     unsigned int *bytecode = (unsigned int *)data;
@@ -996,3 +1008,104 @@ HRESULT d3dx_evaluate_parameter(struct d3dx_param_eval *peval, struct d3dx_param
         set_number((unsigned int *)(*param_value) + i, param->type, oc + i, D3DXPT_FLOAT);
     return D3D_OK;
 }
+
+static HRESULT set_shader_constants_device(struct IDirect3DDevice9 *device, struct d3dx_regstore *rs,
+        D3DXPARAMETER_TYPE type, enum pres_reg_tables table)
+{
+    unsigned int start, n;
+    void *ptr;
+    HRESULT hr, result;
+
+    result = D3D_OK;
+    start = 0;
+    while (start < rs->table_sizes[table])
+    {
+        n = 0;
+        while (start < rs->table_sizes[table] && !regstore_is_val_set_reg(rs, table, start))
+            start++;
+        while (start + n < rs->table_sizes[table] && regstore_is_val_set_reg(rs, table, start + n))
+            n++;
+        if (!n)
+            continue;
+        TRACE("setting %u consts at %u.\n", n, start);
+        ptr = (BYTE *)rs->tables[table] + start * table_info[table].reg_component_count
+                * table_info[table].component_size;
+        if (type == D3DXPT_VERTEXSHADER)
+        {
+            switch(table)
+            {
+                case PRES_REGTAB_OCONST:
+                    hr = IDirect3DDevice9_SetVertexShaderConstantF(device, start, (const float *)ptr, n);
+                    break;
+                case PRES_REGTAB_OICONST:
+                    hr = IDirect3DDevice9_SetVertexShaderConstantI(device, start, (const int *)ptr, n);
+                    break;
+                case PRES_REGTAB_OBCONST:
+                    hr = IDirect3DDevice9_SetVertexShaderConstantB(device, start, (const BOOL *)ptr, n);
+                    break;
+                default:
+                    FIXME("Unexpected register table %u.\n", table);
+                    return D3DERR_INVALIDCALL;
+            }
+        }
+        else if (type == D3DXPT_PIXELSHADER)
+        {
+            switch(table)
+            {
+                case PRES_REGTAB_OCONST:
+                    hr = IDirect3DDevice9_SetPixelShaderConstantF(device, start, (const float *)ptr, n);
+                    break;
+                case PRES_REGTAB_OICONST:
+                    hr = IDirect3DDevice9_SetPixelShaderConstantI(device, start, (const int *)ptr, n);
+                    break;
+                case PRES_REGTAB_OBCONST:
+                    hr = IDirect3DDevice9_SetPixelShaderConstantB(device, start, (const BOOL *)ptr, n);
+                    break;
+                default:
+                    FIXME("Unexpected register table %u.\n", table);
+                    return D3DERR_INVALIDCALL;
+            }
+        }
+        else
+        {
+            FIXME("Unexpected parameter type %u.\n", type);
+            return D3DERR_INVALIDCALL;
+        }
+
+        if (FAILED(hr))
+        {
+            ERR("Setting constants failed, type %u, table %u, hr %#x.\n", type, table, hr);
+            result = hr;
+        }
+        start += n;
+    }
+    regstore_reset_table(rs, table);
+    return result;
+}
+
+HRESULT d3dx_param_eval_set_shader_constants(struct IDirect3DDevice9 *device, struct d3dx_param_eval *peval)
+{
+    static const enum pres_reg_tables set_tables[] =
+            {PRES_REGTAB_OCONST, PRES_REGTAB_OICONST, PRES_REGTAB_OBCONST};
+    HRESULT hr, result;
+    struct d3dx_preshader *pres = &peval->pres;
+    struct d3dx_regstore *rs = &pres->regs;
+    unsigned int i;
+
+    TRACE("device %p, peval %p, param_type %u.\n", device, peval, peval->param_type);
+
+    if (FAILED(hr = set_constants(rs, &pres->inputs)))
+        return hr;
+    if (FAILED(hr = execute_preshader(pres)))
+        return hr;
+    if (FAILED(hr = set_constants(rs, &peval->shader_inputs)))
+        return hr;
+
+    result = D3D_OK;
+    for (i = 0; i < ARRAY_SIZE(set_tables); ++i)
+    {
+        if (FAILED(hr = set_shader_constants_device(device, rs, peval->param_type, set_tables[i])))
+            result = hr;
+    }
+    return result;
+}
diff --git a/dlls/d3dx9_36/tests/effect.c b/dlls/d3dx9_36/tests/effect.c
index 7d74d46..7e915d6 100644
--- a/dlls/d3dx9_36/tests/effect.c
+++ b/dlls/d3dx9_36/tests/effect.c
@@ -3793,7 +3793,7 @@ static void test_effect_preshader(IDirect3DDevice9 *device)
 
     hr = IDirect3DDevice9_GetVertexShaderConstantF(device, 0, &fdata[0].x, TEST_EFFECT_PRES_NFLOATV);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
-    todo_wine ok(!memcmp(fdata, test_effect_preshader_fconstsv, sizeof(test_effect_preshader_fconstsv)),
+    ok(!memcmp(fdata, test_effect_preshader_fconstsv, sizeof(test_effect_preshader_fconstsv)),
             "Vertex shader float constants do not match.\n");
     for (i = TEST_EFFECT_PRES_NFLOATV; i < 256; ++i)
     {
@@ -3804,7 +3804,7 @@ static void test_effect_preshader(IDirect3DDevice9 *device)
     }
     hr = IDirect3DDevice9_GetPixelShaderConstantF(device, 0, &fdata[0].x, TEST_EFFECT_PRES_NFLOATP);
     ok(hr == D3D_OK, "Got result %#x.\n", hr);
-    todo_wine ok(!memcmp(fdata, test_effect_preshader_fconstsp, sizeof(test_effect_preshader_fconstsp)),
+    ok(!memcmp(fdata, test_effect_preshader_fconstsp, sizeof(test_effect_preshader_fconstsp)),
             "Pixel shader float constants do not match.\n");
     for (i = TEST_EFFECT_PRES_NFLOATP; i < 224; ++i)
     {
-- 
2.5.5




More information about the wine-patches mailing list