Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d3d10/d3d10_private.h | 1 + dlls/d3d10/effect.c | 4 +++- dlls/d3d10/tests/effect.c | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/d3d10/d3d10_private.h b/dlls/d3d10/d3d10_private.h index 64c445ec07a..4d73121d6ca 100644 --- a/dlls/d3d10/d3d10_private.h +++ b/dlls/d3d10/d3d10_private.h @@ -118,6 +118,7 @@ struct d3d10_effect_shader_variable unsigned int resource_count; struct d3d10_effect_shader_resource *resources; char *stream_output_declaration; + unsigned int isinline : 1; };
struct d3d10_effect_state_object_variable diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c index 81745f7f239..d521684f788 100644 --- a/dlls/d3d10/effect.c +++ b/dlls/d3d10/effect.c @@ -1409,6 +1409,7 @@ static HRESULT parse_fx10_anonymous_shader(struct d3d10_effect *e, struct d3d10_
v->type = t; v->effect = e; + v->u.shader.isinline = 1; set_variable_vtbl(v);
if (!copy_name("$Anonymous", &v->name)) @@ -7008,7 +7009,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_effect_shader_variable_GetShaderDesc( D3D10_SHADER_DESC shader_desc; HRESULT hr;
- FIXME("iface %p, index %u, desc %p semi-stub.\n", iface, index, desc); + TRACE("iface %p, index %u, desc %p.\n", iface, index, desc);
if (FAILED(hr = d3d10_get_shader_variable(v, index, &s))) return hr; @@ -7017,6 +7018,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_effect_shader_variable_GetShaderDesc( if (s->input_signature) desc->pInputSignature = ID3D10Blob_GetBufferPointer(s->input_signature); desc->SODecl = s->stream_output_declaration; + desc->IsInline = s->isinline; if (s->bytecode) { desc->pBytecode = ID3D10Blob_GetBufferPointer(s->bytecode); diff --git a/dlls/d3d10/tests/effect.c b/dlls/d3d10/tests/effect.c index 70bcf1ea72b..f59686c26a3 100644 --- a/dlls/d3d10/tests/effect.c +++ b/dlls/d3d10/tests/effect.c @@ -3671,8 +3671,8 @@ if (0) ok(hr == S_OK, "Unexpected hr %#x.\n", hr); hr = pdesc.pShaderVariable->lpVtbl->GetShaderDesc(pdesc.pShaderVariable, 0, &shaderdesc); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); -todo_wine { ok(shaderdesc.IsInline, "Unexpected inline flag.\n"); +todo_wine { ok(shaderdesc.SODecl && !strcmp(shaderdesc.SODecl, "SV_POSITION.y"), "Unexpected stream output declaration %s.\n", shaderdesc.SODecl); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d3d10/effect.c | 16 +++++++++++++++- dlls/d3d10/tests/effect.c | 4 +--- 2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c index d521684f788..25a0db10a25 100644 --- a/dlls/d3d10/effect.c +++ b/dlls/d3d10/effect.c @@ -1629,7 +1629,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, { ID3D10EffectVariable *variable = &null_variable.ID3D10EffectVariable_iface; const char *data_ptr = NULL; - DWORD offset; + DWORD offset, sodecl_offset; enum d3d10_effect_object_operation operation; HRESULT hr; struct d3d10_effect *effect = o->pass->technique->effect; @@ -1761,6 +1761,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, data_ptr = data + offset; read_dword(&data_ptr, &offset); TRACE("Effect object starts at offset %#x.\n", offset); + read_dword(&data_ptr, &sodecl_offset);
if (FAILED(hr = parse_fx10_anonymous_shader(effect, &effect->anonymous_shaders[effect->anonymous_shader_current], o->type))) @@ -1770,6 +1771,19 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, variable = &v->ID3D10EffectVariable_iface; ++effect->anonymous_shader_current;
+ if (sodecl_offset) + { + TRACE("Anonymous shader stream output declaration at offset %#x.\n", sodecl_offset); + if (!fx10_copy_string(data, data_size, sodecl_offset, + &v->u.shader.stream_output_declaration)) + { + ERR("Failed to copy stream output declaration.\n"); + return E_OUTOFMEMORY; + } + + TRACE("Stream output declaration: %s.\n", debugstr_a(v->u.shader.stream_output_declaration)); + } + switch (o->type) { case D3D10_EOT_VERTEXSHADER: diff --git a/dlls/d3d10/tests/effect.c b/dlls/d3d10/tests/effect.c index f59686c26a3..a9d077566e0 100644 --- a/dlls/d3d10/tests/effect.c +++ b/dlls/d3d10/tests/effect.c @@ -3672,10 +3672,8 @@ if (0) hr = pdesc.pShaderVariable->lpVtbl->GetShaderDesc(pdesc.pShaderVariable, 0, &shaderdesc); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(shaderdesc.IsInline, "Unexpected inline flag.\n"); -todo_wine { - ok(shaderdesc.SODecl && !strcmp(shaderdesc.SODecl, "SV_POSITION.y"), "Unexpected stream output declaration %s.\n", + ok(!strcmp(shaderdesc.SODecl, "SV_POSITION.y"), "Unexpected stream output declaration %s.\n", shaderdesc.SODecl); -}
v = effect->lpVtbl->GetVariableByName(effect, "g_so"); gs = v->lpVtbl->AsShader(v);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d3d10/effect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c index 25a0db10a25..91273656c74 100644 --- a/dlls/d3d10/effect.c +++ b/dlls/d3d10/effect.c @@ -774,7 +774,7 @@ static HRESULT parse_fx10_shader(const char *data, size_t data_size, DWORD offse break;
case D3D10_SVT_GEOMETRYSHADER: - if (v->type->flags & D3D10_EOT_FLAG_GS_SO) + if (v->u.shader.stream_output_declaration) { struct d3d10_effect_so_decl so_decl;
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- It just came to my mind that it's possible to have streamout without a geometry shader in d3d10/11 (see e.g. CreateGeometryShaderWithStreamOutput() docs). I don't know if effects support that but worth a look I guess?
On 9/2/21 5:25 PM, Matteo Bruni wrote:
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
It just came to my mind that it's possible to have streamout without a geometry shader in d3d10/11 (see e.g. CreateGeometryShaderWithStreamOutput() docs). I don't know if effects support that but worth a look I guess?
ConstructGSWithSO(NULL, "...") doesn't compile, I can tell as much. Given how badly documentation is lacking, it's best to wait for some real world examples I suppose.
On Thu, Sep 2, 2021 at 8:54 PM Nikolay Sivov nsivov@codeweavers.com wrote:
On 9/2/21 5:25 PM, Matteo Bruni wrote:
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
It just came to my mind that it's possible to have streamout without a geometry shader in d3d10/11 (see e.g. CreateGeometryShaderWithStreamOutput() docs). I don't know if effects support that but worth a look I guess?
ConstructGSWithSO(NULL, "...") doesn't compile, I can tell as much. Given how badly documentation is lacking, it's best to wait for some real world examples I suppose.
Sure, that's fine to me. FWIW I tried this (adding it to the effect from the d3d10 tests):
GeometryShader v_so = ConstructGSWithSO ( CompileShader( vs_4_0, VS()), "SV_POSITION.x" );
FXC seems to accept it just fine and, according to FXC itself, it actually generates a GeometryShader object with the VS() shader inside (as a normal vertex shader, vs_4_0 and all) and the streamout declaration.
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d3d10/effect.c | 2 -- 1 file changed, 2 deletions(-)
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c index 91273656c74..aacf2fcbfaf 100644 --- a/dlls/d3d10/effect.c +++ b/dlls/d3d10/effect.c @@ -765,12 +765,10 @@ static HRESULT parse_fx10_shader(const char *data, size_t data_size, DWORD offse { case D3D10_SVT_VERTEXSHADER: hr = ID3D10Device_CreateVertexShader(device, ptr, dxbc_size, &v->u.shader.shader.vs); - if (FAILED(hr)) return hr; break;
case D3D10_SVT_PIXELSHADER: hr = ID3D10Device_CreatePixelShader(device, ptr, dxbc_size, &v->u.shader.shader.ps); - if (FAILED(hr)) return hr; break;
case D3D10_SVT_GEOMETRYSHADER:
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/d3d10/effect.c | 24 +++++++++++------ dlls/d3d10/tests/effect.c | 57 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 8 deletions(-)
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c index aacf2fcbfaf..218c4ad888a 100644 --- a/dlls/d3d10/effect.c +++ b/dlls/d3d10/effect.c @@ -6983,7 +6983,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_effect_shader_variable_GetRawValue( /* ID3D10EffectShaderVariable methods */
static HRESULT d3d10_get_shader_variable(struct d3d10_effect_variable *v, UINT shader_index, - struct d3d10_effect_shader_variable **s) + struct d3d10_effect_shader_variable **s, D3D10_SHADER_VARIABLE_TYPE *basetype) { unsigned int i;
@@ -6993,6 +6993,7 @@ static HRESULT d3d10_get_shader_variable(struct d3d10_effect_variable *v, UINT s if (!shader_index) { *s = &v->u.shader; + if (basetype) *basetype = v->type->basetype; return S_OK; }
@@ -7010,6 +7011,8 @@ static HRESULT d3d10_get_shader_variable(struct d3d10_effect_variable *v, UINT s }
*s = &v->effect->used_shaders[i + shader_index]->u.shader; + if (basetype) *basetype = v->effect->used_shaders[i + shader_index]->type->basetype; + return S_OK; }
@@ -7023,7 +7026,7 @@ static HRESULT STDMETHODCALLTYPE d3d10_effect_shader_variable_GetShaderDesc(
TRACE("iface %p, index %u, desc %p.\n", iface, index, desc);
- if (FAILED(hr = d3d10_get_shader_variable(v, index, &s))) + if (FAILED(hr = d3d10_get_shader_variable(v, index, &s, NULL))) return hr;
memset(desc, 0, sizeof(*desc)); @@ -7052,19 +7055,24 @@ static HRESULT STDMETHODCALLTYPE d3d10_effect_shader_variable_GetVertexShader( ID3D10EffectShaderVariable *iface, UINT index, ID3D10VertexShader **shader) { struct d3d10_effect_variable *v = impl_from_ID3D10EffectShaderVariable(iface); + struct d3d10_effect_shader_variable *s; + D3D10_SHADER_VARIABLE_TYPE basetype; + HRESULT hr;
TRACE("iface %p, index %u, shader %p.\n", iface, index, shader);
- if (v->type->element_count) - v = impl_from_ID3D10EffectVariable(iface->lpVtbl->GetElement(iface, index)); + *shader = NULL;
- if (v->type->basetype != D3D10_SVT_VERTEXSHADER) + if (FAILED(hr = d3d10_get_shader_variable(v, index, &s, &basetype))) + return hr; + + if (basetype != D3D10_SVT_VERTEXSHADER) { WARN("Shader is not a vertex shader.\n"); - return E_FAIL; + return D3DERR_INVALIDCALL; }
- if ((*shader = v->u.shader.shader.vs)) + if ((*shader = s->shader.vs)) ID3D10VertexShader_AddRef(*shader);
return S_OK; @@ -7120,7 +7128,7 @@ static HRESULT d3d10_get_shader_variable_signature(struct d3d10_effect_variable struct d3d10_effect_shader_variable *s; HRESULT hr;
- if (FAILED(hr = d3d10_get_shader_variable(v, shader_index, &s))) + if (FAILED(hr = d3d10_get_shader_variable(v, shader_index, &s, NULL))) return hr;
if (!s->reflection) diff --git a/dlls/d3d10/tests/effect.c b/dlls/d3d10/tests/effect.c index a9d077566e0..4583863d59b 100644 --- a/dlls/d3d10/tests/effect.c +++ b/dlls/d3d10/tests/effect.c @@ -6010,6 +6010,62 @@ static void test_effect_shader_description(void) ok(!refcount, "Device has %u references left.\n", refcount); }
+static void test_effect_shader_object(void) +{ + ID3D10EffectShaderVariable *s; + ID3D10EffectVariable *v; + ID3D10VertexShader *vs; + ID3D10Effect* effect; + ID3D10Device *device; + ULONG refcount; + HRESULT hr; + + if (!(device = create_device())) + { + skip("Failed to create device, skipping tests.\n"); + return; + } + + hr = create_effect(fx_local_shader, 0, device, NULL, &effect); + ok(SUCCEEDED(hr), "Failed to create an effect!\n"); + + v = effect->lpVtbl->GetVariableByName(effect, "v0"); + + s = v->lpVtbl->AsShader(v); + + vs = (void *)0xdeadbeef; + hr = s->lpVtbl->GetVertexShader(s, 0, &vs); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!vs, "Unexpected shader object.\n"); + + vs = (void *)0xdeadbeef; + hr = s->lpVtbl->GetVertexShader(s, 1, &vs); + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr); + ok(!vs, "Unexpected shader object.\n"); + + vs = (void *)0xdeadbeef; + hr = s->lpVtbl->GetVertexShader(s, 2, &vs); + ok(hr == D3DERR_INVALIDCALL, "Unexpected hr %#x.\n", hr); + ok(!vs, "Unexpected shader object.\n"); + + vs = NULL; + hr = s->lpVtbl->GetVertexShader(s, 3, &vs); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!vs, "Unexpected shader object.\n"); + ID3D10VertexShader_Release(vs); + + vs = NULL; + hr = s->lpVtbl->GetVertexShader(s, 4, &vs); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + ok(!!vs, "Unexpected shader object.\n"); + ID3D10VertexShader_Release(vs); + + effect->lpVtbl->Release(effect); + + refcount = ID3D10Device_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); +} + START_TEST(effect) { test_effect_constant_buffer_type(); @@ -6028,4 +6084,5 @@ START_TEST(effect) test_effect_resource_variable(); test_effect_optimize(); test_effect_shader_description(); + test_effect_shader_object(); }
Signed-off-by: Matteo Bruni mbruni@codeweavers.com
From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- v2 (Matteo): Update require_space() check for inline shaders.
dlls/d3d10/effect.c | 18 ++++++++++++++++-- dlls/d3d10/tests/effect.c | 4 +--- 2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/dlls/d3d10/effect.c b/dlls/d3d10/effect.c index d521684f788..48df10acff5 100644 --- a/dlls/d3d10/effect.c +++ b/dlls/d3d10/effect.c @@ -1629,7 +1629,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, { ID3D10EffectVariable *variable = &null_variable.ID3D10EffectVariable_iface; const char *data_ptr = NULL; - DWORD offset; + DWORD offset, sodecl_offset; enum d3d10_effect_object_operation operation; HRESULT hr; struct d3d10_effect *effect = o->pass->technique->effect; @@ -1753,7 +1753,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, return E_FAIL; }
- if (offset >= data_size || !require_space(offset, 1, sizeof(DWORD), data_size)) + if (offset >= data_size || !require_space(offset, 2, sizeof(DWORD), data_size)) { WARN("Invalid offset %#x (data size %#lx).\n", offset, (long)data_size); return E_FAIL; @@ -1761,6 +1761,7 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, data_ptr = data + offset; read_dword(&data_ptr, &offset); TRACE("Effect object starts at offset %#x.\n", offset); + read_dword(&data_ptr, &sodecl_offset);
if (FAILED(hr = parse_fx10_anonymous_shader(effect, &effect->anonymous_shaders[effect->anonymous_shader_current], o->type))) @@ -1770,6 +1771,19 @@ static HRESULT parse_fx10_object(const char *data, size_t data_size, variable = &v->ID3D10EffectVariable_iface; ++effect->anonymous_shader_current;
+ if (sodecl_offset) + { + TRACE("Anonymous shader stream output declaration at offset %#x.\n", sodecl_offset); + if (!fx10_copy_string(data, data_size, sodecl_offset, + &v->u.shader.stream_output_declaration)) + { + ERR("Failed to copy stream output declaration.\n"); + return E_OUTOFMEMORY; + } + + TRACE("Stream output declaration: %s.\n", debugstr_a(v->u.shader.stream_output_declaration)); + } + switch (o->type) { case D3D10_EOT_VERTEXSHADER: diff --git a/dlls/d3d10/tests/effect.c b/dlls/d3d10/tests/effect.c index f59686c26a3..a9d077566e0 100644 --- a/dlls/d3d10/tests/effect.c +++ b/dlls/d3d10/tests/effect.c @@ -3672,10 +3672,8 @@ if (0) hr = pdesc.pShaderVariable->lpVtbl->GetShaderDesc(pdesc.pShaderVariable, 0, &shaderdesc); ok(hr == S_OK, "Unexpected hr %#x.\n", hr); ok(shaderdesc.IsInline, "Unexpected inline flag.\n"); -todo_wine { - ok(shaderdesc.SODecl && !strcmp(shaderdesc.SODecl, "SV_POSITION.y"), "Unexpected stream output declaration %s.\n", + ok(!strcmp(shaderdesc.SODecl, "SV_POSITION.y"), "Unexpected stream output declaration %s.\n", shaderdesc.SODecl); -}
v = effect->lpVtbl->GetVariableByName(effect, "g_so"); gs = v->lpVtbl->AsShader(v);