[v2 PATCH 1/7] d3d10/effect: Use shader variable directly from pass structure on Apply().

Nikolay Sivov nsivov at codeweavers.com
Fri Oct 8 00:13:30 CDT 2021


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---

v2: added explicit test to show a difference between Set*Shader(NULL) and no shader being set.

 dlls/d3d10/d3d10_private.h |  15 ---
 dlls/d3d10/effect.c        | 185 +++++++++++++------------------------
 dlls/d3d10/tests/effect.c  |  22 +++++
 3 files changed, 86 insertions(+), 136 deletions(-)

diff --git a/dlls/d3d10/d3d10_private.h b/dlls/d3d10/d3d10_private.h
index 6979d2a114e..fbcc36e5e06 100644
--- a/dlls/d3d10/d3d10_private.h
+++ b/dlls/d3d10/d3d10_private.h
@@ -73,19 +73,6 @@ struct d3d10_matrix
     float m[4][4];
 };
 
-struct d3d10_effect_object
-{
-    struct d3d10_effect_pass *pass;
-    enum d3d10_effect_object_type type;
-    union
-    {
-        ID3D10VertexShader *vs;
-        ID3D10PixelShader *ps;
-        ID3D10GeometryShader *gs;
-        IUnknown *object;
-    } object;
-};
-
 struct d3d10_effect_shader_resource
 {
     D3D10_SHADER_INPUT_TYPE in_type;
@@ -236,9 +223,7 @@ struct d3d10_effect_pass
 
     struct d3d10_effect_technique *technique;
     char *name;
-    DWORD object_count;
     DWORD annotation_count;
-    struct d3d10_effect_object *objects;
     struct d3d10_effect_variable *annotations;
 
     struct d3d10_effect_pass_shader_desc vs;
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c
index 0ba906375d7..d4e44a7f419 100644
--- a/dlls/d3d10/effect.c
+++ b/dlls/d3d10/effect.c
@@ -1734,17 +1734,17 @@ static BOOL parse_fx10_state_group(const char *data, size_t data_size,
 }
 
 static HRESULT parse_fx10_object(const char *data, size_t data_size,
-        const char **ptr, struct d3d10_effect_object *o)
+        const char **ptr, struct d3d10_effect_pass *pass)
 {
     ID3D10EffectVariable *variable = &null_variable.ID3D10EffectVariable_iface;
     const char *data_ptr = NULL;
     DWORD offset, sodecl_offset;
     enum d3d10_effect_object_operation operation;
     HRESULT hr;
-    struct d3d10_effect *effect = o->pass->technique->effect;
+    struct d3d10_effect *effect = pass->technique->effect;
     ID3D10Effect *e = &effect->ID3D10Effect_iface;
     struct d3d10_effect_variable *v;
-    DWORD tmp, variable_idx = 0;
+    DWORD tmp, object_type, variable_idx = 0;
     const char *name;
     size_t name_len;
 
@@ -1754,8 +1754,8 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
         return E_FAIL;
     }
 
-    read_dword(ptr, &o->type);
-    TRACE("Effect object is of type %#x.\n", o->type);
+    read_dword(ptr, &object_type);
+    TRACE("Effect object is of type %#x.\n", object_type);
 
     read_dword(ptr, &tmp);
     TRACE("Effect object index %#x.\n", tmp);
@@ -1771,7 +1771,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
         case D3D10_EOO_CONST:
             TRACE("Copy variable values\n");
 
-            switch (o->type)
+            switch (object_type)
             {
                 case D3D10_EOT_VERTEXSHADER:
                     TRACE("Vertex shader\n");
@@ -1789,7 +1789,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
                     break;
 
                 case D3D10_EOT_STENCIL_REF:
-                    if (!read_value_list(data, data_size, offset, D3D10_SVT_UINT, 0, 1, &o->pass->stencil_ref))
+                    if (!read_value_list(data, data_size, offset, D3D10_SVT_UINT, 0, 1, &pass->stencil_ref))
                     {
                         ERR("Failed to read stencil ref.\n");
                         return E_FAIL;
@@ -1797,7 +1797,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
                     break;
 
                 case D3D10_EOT_SAMPLE_MASK:
-                    if (!read_value_list(data, data_size, offset, D3D10_SVT_UINT, 0, 1, &o->pass->sample_mask))
+                    if (!read_value_list(data, data_size, offset, D3D10_SVT_UINT, 0, 1, &pass->sample_mask))
                     {
                         FIXME("Failed to read sample mask.\n");
                         return E_FAIL;
@@ -1805,7 +1805,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
                     break;
 
                 case D3D10_EOT_BLEND_FACTOR:
-                    if (!read_value_list(data, data_size, offset, D3D10_SVT_FLOAT, 0, 4, &o->pass->blend_factor[0]))
+                    if (!read_value_list(data, data_size, offset, D3D10_SVT_FLOAT, 0, 4, &pass->blend_factor[0]))
                     {
                         FIXME("Failed to read blend factor.\n");
                         return E_FAIL;
@@ -1813,7 +1813,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
                     break;
 
                 default:
-                    FIXME("Unhandled object type %#x\n", o->type);
+                    FIXME("Unhandled object type %#x\n", object_type);
                     return E_FAIL;
             }
             break;
@@ -1873,7 +1873,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
             read_dword(&data_ptr, &sodecl_offset);
 
             if (FAILED(hr = parse_fx10_anonymous_shader(effect,
-                    &effect->anonymous_shaders[effect->anonymous_shader_current], o->type)))
+                    &effect->anonymous_shaders[effect->anonymous_shader_current], object_type)))
                 return hr;
 
             v = &effect->anonymous_shaders[effect->anonymous_shader_current].shader;
@@ -1893,7 +1893,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
                 TRACE("Stream output declaration: %s.\n", debugstr_a(v->u.shader.stream_output_declaration));
             }
 
-            switch (o->type)
+            switch (object_type)
             {
                 case D3D10_EOT_VERTEXSHADER:
                 case D3D10_EOT_PIXELSHADER:
@@ -1903,7 +1903,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
                     break;
 
                 default:
-                    FIXME("Unhandled object type %#x\n", o->type);
+                    FIXME("Unhandled object type %#x\n", object_type);
                     return E_FAIL;
             }
             break;
@@ -1913,7 +1913,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
             return E_FAIL;
     }
 
-    switch (o->type)
+    switch (object_type)
     {
         case D3D10_EOT_RASTERIZER_STATE:
         {
@@ -1927,10 +1927,10 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
             if (v->type->element_count)
             {
                 if (variable_idx >= v->type->element_count) return E_FAIL;
-                o->pass->rasterizer = &v->elements[variable_idx];
+                pass->rasterizer = &v->elements[variable_idx];
             }
             else
-                o->pass->rasterizer = v;
+                pass->rasterizer = v;
             break;
         }
 
@@ -1946,10 +1946,10 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
             if (v->type->element_count)
             {
                 if (variable_idx >= v->type->element_count) return E_FAIL;
-                o->pass->depth_stencil = &v->elements[variable_idx];
+                pass->depth_stencil = &v->elements[variable_idx];
             }
             else
-                o->pass->depth_stencil = v;
+                pass->depth_stencil = v;
             break;
         }
 
@@ -1965,40 +1965,34 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
             if (v->type->element_count)
             {
                 if (variable_idx >= v->type->element_count) return E_FAIL;
-                o->pass->blend = &v->elements[variable_idx];
+                pass->blend = &v->elements[variable_idx];
             }
             else
-                o->pass->blend = v;
+                pass->blend = v;
             break;
         }
 
         case D3D10_EOT_VERTEXSHADER:
         {
             ID3D10EffectShaderVariable *sv = variable->lpVtbl->AsShader(variable);
-            if (FAILED(hr = sv->lpVtbl->GetVertexShader(sv, variable_idx, &o->object.vs)))
-                return hr;
-            o->pass->vs.shader = impl_from_ID3D10EffectVariable((ID3D10EffectVariable *)sv);
-            o->pass->vs.index = variable_idx;
+            pass->vs.shader = impl_from_ID3D10EffectVariable((ID3D10EffectVariable *)sv);
+            pass->vs.index = variable_idx;
             break;
         }
 
         case D3D10_EOT_PIXELSHADER:
         {
             ID3D10EffectShaderVariable *sv = variable->lpVtbl->AsShader(variable);
-            if (FAILED(hr = sv->lpVtbl->GetPixelShader(sv, variable_idx, &o->object.ps)))
-                return hr;
-            o->pass->ps.shader = impl_from_ID3D10EffectVariable((ID3D10EffectVariable *)sv);
-            o->pass->ps.index = variable_idx;
+            pass->ps.shader = impl_from_ID3D10EffectVariable((ID3D10EffectVariable *)sv);
+            pass->ps.index = variable_idx;
             break;
         }
 
         case D3D10_EOT_GEOMETRYSHADER:
         {
             ID3D10EffectShaderVariable *sv = variable->lpVtbl->AsShader(variable);
-            if (FAILED(hr = sv->lpVtbl->GetGeometryShader(sv, variable_idx, &o->object.gs)))
-                return hr;
-            o->pass->gs.shader = impl_from_ID3D10EffectVariable((ID3D10EffectVariable *)sv);
-            o->pass->gs.index = variable_idx;
+            pass->gs.shader = impl_from_ID3D10EffectVariable((ID3D10EffectVariable *)sv);
+            pass->gs.index = variable_idx;
             break;
         }
 
@@ -2008,7 +2002,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
             break;
 
         default:
-            FIXME("Unhandled object type %#x.\n", o->type);
+            FIXME("Unhandled object type %#x.\n", object_type);
             return E_FAIL;
     }
 
@@ -2018,9 +2012,9 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size,
 static HRESULT parse_fx10_pass(const char *data, size_t data_size,
         const char **ptr, struct d3d10_effect_pass *p)
 {
+    DWORD offset, object_count;
     HRESULT hr = S_OK;
     unsigned int i;
-    DWORD offset;
 
     read_dword(ptr, &offset);
     TRACE("Pass name at offset %#x.\n", offset);
@@ -2032,8 +2026,8 @@ static HRESULT parse_fx10_pass(const char *data, size_t data_size,
     }
     TRACE("Pass name: %s.\n", debugstr_a(p->name));
 
-    read_dword(ptr, &p->object_count);
-    TRACE("Pass has %u effect objects.\n", p->object_count);
+    read_dword(ptr, &object_count);
+    TRACE("Pass has %u effect objects.\n", object_count);
 
     read_dword(ptr, &p->annotation_count);
     TRACE("Pass has %u annotations.\n", p->annotation_count);
@@ -2045,23 +2039,13 @@ static HRESULT parse_fx10_pass(const char *data, size_t data_size,
         return hr;
     }
 
-    if (!(p->objects = heap_calloc(p->object_count, sizeof(*p->objects))))
-    {
-        ERR("Failed to allocate effect objects memory.\n");
-        return E_OUTOFMEMORY;
-    }
-
     p->vs.shader = &null_shader_variable;
     p->ps.shader = &null_shader_variable;
     p->gs.shader = &null_shader_variable;
 
-    for (i = 0; i < p->object_count; ++i)
+    for (i = 0; i < object_count; ++i)
     {
-        struct d3d10_effect_object *o = &p->objects[i];
-
-        o->pass = p;
-
-        if (FAILED(hr = parse_fx10_object(data, data_size, ptr, o)))
+        if (FAILED(hr = parse_fx10_object(data, data_size, ptr, p)))
             return hr;
     }
 
@@ -2927,42 +2911,6 @@ HRESULT d3d10_effect_parse(struct d3d10_effect *This, const void *data, SIZE_T d
     return parse_dxbc(data, data_size, fx10_chunk_handler, This);
 }
 
-static HRESULT d3d10_effect_object_apply(struct d3d10_effect_object *o)
-{
-    ID3D10Device *device = o->pass->technique->effect->device;
-
-    TRACE("effect object %p, type %#x.\n", o, o->type);
-
-    switch(o->type)
-    {
-        case D3D10_EOT_RASTERIZER_STATE:
-        case D3D10_EOT_DEPTH_STENCIL_STATE:
-        case D3D10_EOT_BLEND_STATE:
-        case D3D10_EOT_STENCIL_REF:
-        case D3D10_EOT_BLEND_FACTOR:
-        case D3D10_EOT_SAMPLE_MASK:
-            break;
-
-        case D3D10_EOT_VERTEXSHADER:
-            ID3D10Device_VSSetShader(device, o->object.vs);
-            return S_OK;
-
-        case D3D10_EOT_PIXELSHADER:
-            ID3D10Device_PSSetShader(device, o->object.ps);
-            return S_OK;
-
-        case D3D10_EOT_GEOMETRYSHADER:
-            ID3D10Device_GSSetShader(device, o->object.gs);
-            return S_OK;
-
-        default:
-            FIXME("Unhandled effect object type %#x.\n", o->type);
-            return E_FAIL;
-    }
-
-    return S_OK;
-}
-
 static void d3d10_effect_shader_variable_destroy(struct d3d10_effect_shader_variable *s,
         D3D10_SHADER_VARIABLE_TYPE type)
 {
@@ -3087,25 +3035,6 @@ static void d3d10_effect_variable_destroy(struct d3d10_effect_variable *v)
     }
 }
 
-static void d3d10_effect_object_destroy(struct d3d10_effect_object *o)
-{
-    switch (o->type)
-    {
-        case D3D10_EOT_RASTERIZER_STATE:
-        case D3D10_EOT_DEPTH_STENCIL_STATE:
-        case D3D10_EOT_BLEND_STATE:
-        case D3D10_EOT_VERTEXSHADER:
-        case D3D10_EOT_PIXELSHADER:
-        case D3D10_EOT_GEOMETRYSHADER:
-            if (o->object.object)
-                IUnknown_Release(o->object.object);
-            break;
-
-        default:
-            break;
-    }
-}
-
 static void d3d10_effect_pass_destroy(struct d3d10_effect_pass *p)
 {
     unsigned int i;
@@ -3114,15 +3043,6 @@ static void d3d10_effect_pass_destroy(struct d3d10_effect_pass *p)
 
     heap_free(p->name);
 
-    if (p->objects)
-    {
-        for (i = 0; i < p->object_count; ++i)
-        {
-            d3d10_effect_object_destroy(&p->objects[i]);
-        }
-        heap_free(p->objects);
-    }
-
     if (p->annotations)
     {
         for (i = 0; i < p->annotation_count; ++i)
@@ -4109,12 +4029,35 @@ static void apply_shader_resources(ID3D10Device *device, struct d3d10_effect_var
     }
 }
 
+static void d3d10_effect_pass_set_shader(struct d3d10_effect_pass *pass,
+        const struct d3d10_effect_pass_shader_desc *shader_desc)
+{
+    ID3D10Device *device = pass->technique->effect->device;
+    struct d3d10_effect_variable *v = shader_desc->shader;
+
+    if (v->type->element_count)
+        v = &v->elements[shader_desc->index];
+
+    switch (v->type->basetype)
+    {
+        case D3D10_SVT_VERTEXSHADER:
+            ID3D10Device_VSSetShader(device, v->u.shader.shader.vs);
+            break;
+        case D3D10_SVT_PIXELSHADER:
+            ID3D10Device_PSSetShader(device, v->u.shader.shader.ps);
+            break;
+        case D3D10_SVT_GEOMETRYSHADER:
+            ID3D10Device_GSSetShader(device, v->u.shader.shader.gs);
+            break;
+        default:
+            WARN("Unexpected shader type %u.\n", v->type->basetype);
+    }
+}
+
 static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_Apply(ID3D10EffectPass *iface, UINT flags)
 {
     struct d3d10_effect_pass *pass = impl_from_ID3D10EffectPass(iface);
     ID3D10Device *device = pass->technique->effect->device;
-    HRESULT hr = S_OK;
-    unsigned int i;
 
     TRACE("iface %p, flags %#x\n", iface, flags);
 
@@ -4134,14 +4077,14 @@ static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_Apply(ID3D10EffectPass *iface
     if (pass->blend)
         ID3D10Device_OMSetBlendState(device, pass->blend->u.state.object.blend,
                 pass->blend_factor, pass->sample_mask);
+    if (pass->vs.shader != &null_shader_variable)
+        d3d10_effect_pass_set_shader(pass, &pass->vs);
+    if (pass->ps.shader != &null_shader_variable)
+        d3d10_effect_pass_set_shader(pass, &pass->ps);
+    if (pass->gs.shader != &null_shader_variable)
+        d3d10_effect_pass_set_shader(pass, &pass->gs);
 
-    for (i = 0; i < pass->object_count; ++i)
-    {
-        hr = d3d10_effect_object_apply(&pass->objects[i]);
-        if (FAILED(hr)) break;
-    }
-
-    return hr;
+    return S_OK;
 }
 
 static HRESULT STDMETHODCALLTYPE d3d10_effect_pass_ComputeStateBlockMask(ID3D10EffectPass *iface,
diff --git a/dlls/d3d10/tests/effect.c b/dlls/d3d10/tests/effect.c
index 781abb46745..6ad3f7421f4 100644
--- a/dlls/d3d10/tests/effect.c
+++ b/dlls/d3d10/tests/effect.c
@@ -2909,6 +2909,7 @@ static void test_effect_local_shader(void)
     D3D10_EFFECT_DESC effect_desc;
     ID3D10EffectShaderVariable *null_shader, *null_anon_vs, *null_anon_ps, *null_anon_gs,
         *p3_anon_vs, *p3_anon_ps, *p3_anon_gs, *p6_vs, *p6_ps, *p6_gs, *gs, *ps, *vs;
+    ID3D10PixelShader *ps_d3d, *ps_d3d_2;
     D3D10_EFFECT_SHADER_DESC shaderdesc;
     D3D10_SIGNATURE_PARAMETER_DESC sign;
     D3D10_STATE_BLOCK_MASK mask;
@@ -3005,6 +3006,12 @@ if (0)
     hr = p->lpVtbl->GetGeometryShaderDesc(p, NULL);
     ok(hr == E_INVALIDARG, "GetGeometryShaderDesc got %x, expected %x\n", hr, E_INVALIDARG);
 
+    v = effect->lpVtbl->GetVariableByName(effect, "p");
+    ps = v->lpVtbl->AsShader(v);
+
+    hr = ps->lpVtbl->GetPixelShader(ps, 0, &ps_d3d);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
     /* get the null_shader_variable */
     v = effect->lpVtbl->GetVariableByIndex(effect, 10000);
     null_shader = v->lpVtbl->AsShader(v);
@@ -3024,6 +3031,13 @@ if (0)
     ret = D3D10StateBlockMaskGetSetting(&mask, D3D10_DST_GS, 0);
     ok(!ret, "Unexpected mask.\n");
 
+    ID3D10Device_PSSetShader(device, ps_d3d);
+    hr = p->lpVtbl->Apply(p, 0);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ID3D10Device_PSGetShader(device, &ps_d3d_2);
+    ok(ps_d3d_2 == ps_d3d, "Unexpected shader object.\n");
+    ID3D10PixelShader_Release(ps_d3d_2);
+
     hr = p->lpVtbl->GetVertexShaderDesc(p, &pdesc);
     ok(hr == S_OK, "GetVertexShaderDesc got %x, expected %x\n", hr, S_OK);
     ok(pdesc.pShaderVariable == null_shader, "Got %p, expected %p\n", pdesc.pShaderVariable, null_shader);
@@ -3051,6 +3065,12 @@ if (0)
     /* pass 1 */
     p = t->lpVtbl->GetPassByIndex(t, 1);
 
+    ID3D10Device_PSSetShader(device, ps_d3d);
+    hr = p->lpVtbl->Apply(p, 0);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ID3D10Device_PSGetShader(device, &ps_d3d_2);
+    ok(!ps_d3d_2, "Unexpected shader object.\n");
+
     /* pass 1 vertexshader */
     hr = p->lpVtbl->GetVertexShaderDesc(p, &pdesc);
     ok(hr == S_OK, "GetVertexShaderDesc got %x, expected %x\n", hr, S_OK);
@@ -3881,6 +3901,8 @@ todo_wine
 
     effect->lpVtbl->Release(effect);
 
+    ID3D10PixelShader_Release(ps_d3d);
+
     refcount = ID3D10Device_Release(device);
     ok(!refcount, "Device has %u references left.\n", refcount);
 }
-- 
2.33.0




More information about the wine-devel mailing list