Signed-off-by: Nikolay Sivov <nsivov(a)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