From: Józef Kucia Subject: [PATCH 7/8] d3d11: Implement d3d11_device_CreateGeometryShaderWithStreamOutput(). Message-Id: <20170323111551.16591-7-jkucia@codeweavers.com> Date: Thu, 23 Mar 2017 12:15:50 +0100 In-Reply-To: <20170323111551.16591-1-jkucia@codeweavers.com> References: <20170323111551.16591-1-jkucia@codeweavers.com> Signed-off-by: Józef Kucia --- dlls/d3d11/d3d11_private.h | 6 +++ dlls/d3d11/device.c | 29 ++++++++++--- dlls/d3d11/shader.c | 105 +++++++++++++++++++++++++++++++++++++++------ dlls/d3d11/tests/d3d11.c | 5 +-- 4 files changed, 123 insertions(+), 22 deletions(-) diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h index 62f46ea..6caca05 100644 --- a/dlls/d3d11/d3d11_private.h +++ b/dlls/d3d11/d3d11_private.h @@ -37,6 +37,10 @@ #include "wine/winedxgi.h" #include "wine/rbtree.h" +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#endif + #define MAKE_TAG(ch0, ch1, ch2, ch3) \ ((DWORD)(ch0) | ((DWORD)(ch1) << 8) | \ ((DWORD)(ch2) << 16) | ((DWORD)(ch3) << 24 )) @@ -316,6 +320,8 @@ struct d3d_geometry_shader }; HRESULT d3d_geometry_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length, + const D3D11_SO_DECLARATION_ENTRY *so_entries, unsigned int so_entry_count, + const unsigned int *buffer_strides, unsigned int buffer_stride_count, unsigned int rasterizer_stream, struct d3d_geometry_shader **shader) DECLSPEC_HIDDEN; struct d3d_geometry_shader *unsafe_impl_from_ID3D11GeometryShader(ID3D11GeometryShader *iface) DECLSPEC_HIDDEN; struct d3d_geometry_shader *unsafe_impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface) DECLSPEC_HIDDEN; diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index b0b4045..d9c3a5a 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -2476,7 +2476,8 @@ static HRESULT STDMETHODCALLTYPE d3d11_device_CreateGeometryShader(ID3D11Device if (class_linkage) FIXME("Class linkage is not implemented yet.\n"); - if (FAILED(hr = d3d_geometry_shader_create(device, byte_code, byte_code_length, &object))) + if (FAILED(hr = d3d_geometry_shader_create(device, byte_code, byte_code_length, + NULL, 0, NULL, 0, 0, &object))) return hr; *shader = &object->ID3D11GeometryShader_iface; @@ -2486,15 +2487,28 @@ static HRESULT STDMETHODCALLTYPE d3d11_device_CreateGeometryShader(ID3D11Device static HRESULT STDMETHODCALLTYPE d3d11_device_CreateGeometryShaderWithStreamOutput(ID3D11Device *iface, const void *byte_code, SIZE_T byte_code_length, const D3D11_SO_DECLARATION_ENTRY *so_entries, - UINT entry_count, const UINT *buffer_strides, UINT strides_count, UINT rasterized_stream, + UINT entry_count, const UINT *buffer_strides, UINT strides_count, UINT rasterizer_stream, ID3D11ClassLinkage *class_linkage, ID3D11GeometryShader **shader) { - FIXME("iface %p, byte_code %p, byte_code_length %lu, so_entries %p, entry_count %u, " - "buffer_strides %p, strides_count %u, rasterized_stream %u, class_linkage %p, shader %p stub!\n", + struct d3d_device *device = impl_from_ID3D11Device(iface); + struct d3d_geometry_shader *object; + HRESULT hr; + + TRACE("iface %p, byte_code %p, byte_code_length %lu, so_entries %p, entry_count %u, " + "buffer_strides %p, strides_count %u, rasterizer_stream %u, class_linkage %p, shader %p.\n", iface, byte_code, byte_code_length, so_entries, entry_count, buffer_strides, strides_count, - rasterized_stream, class_linkage, shader); + rasterizer_stream, class_linkage, shader); - return E_NOTIMPL; + if (class_linkage) + FIXME("Class linkage is not implemented yet.\n"); + + if (FAILED(hr = d3d_geometry_shader_create(device, byte_code, byte_code_length, + so_entries, entry_count, buffer_strides, strides_count, rasterizer_stream, &object))) + return hr; + + *shader = &object->ID3D11GeometryShader_iface; + + return hr; } static HRESULT STDMETHODCALLTYPE d3d11_device_CreatePixelShader(ID3D11Device *iface, const void *byte_code, @@ -4892,7 +4906,8 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateGeometryShader(ID3D10Device1 TRACE("iface %p, byte_code %p, byte_code_length %lu, shader %p.\n", iface, byte_code, byte_code_length, shader); - if (FAILED(hr = d3d_geometry_shader_create(device, byte_code, byte_code_length, &object))) + if (FAILED(hr = d3d_geometry_shader_create(device, byte_code, byte_code_length, + NULL, 0, NULL, 0, 0, &object))) return hr; *shader = &object->ID3D10GeometryShader_iface; diff --git a/dlls/d3d11/shader.c b/dlls/d3d11/shader.c index 87312c3..552ab0e 100644 --- a/dlls/d3d11/shader.c +++ b/dlls/d3d11/shader.c @@ -1188,29 +1188,107 @@ static const struct wined3d_parent_ops d3d_geometry_shader_wined3d_parent_ops = d3d_geometry_shader_wined3d_object_destroyed, }; -static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader, struct d3d_device *device, - const void *byte_code, SIZE_T byte_code_length) +static HRESULT wined3d_so_elements_from_d3d11_so_entries(struct wined3d_stream_output_element *elements, + const D3D11_SO_DECLARATION_ENTRY *entries, unsigned int entry_count, + const struct wined3d_shader_signature *os) { + unsigned int i; + + for (i = 0; i < entry_count; ++i) + { + struct wined3d_stream_output_element *e = &elements[i]; + const D3D11_SO_DECLARATION_ENTRY *f = &entries[i]; + struct wined3d_shader_signature_element *element; + + TRACE("Stream: %u, semantic: %s, semantic idx: %u, start component: %u, " + "component count %u, output slot %u.\n", + f->Stream, debugstr_a(f->SemanticName), f->SemanticIndex, + f->StartComponent, f->ComponentCount, f->OutputSlot); + + e->stream_idx = f->Stream; + e->component_idx = f->StartComponent; + e->component_count = f->ComponentCount; + e->output_slot = f->OutputSlot; + + if (!f->SemanticName) + { + e->register_idx = WINED3D_STREAM_OUTPUT_GAP; + } + else if ((element = shader_find_signature_element(os, f->SemanticName, f->SemanticIndex))) + { + e->register_idx = element->register_idx; + TRACE("Register idx: %u.\n", e->register_idx); + } + else + { + WARN("Failed to find output signature element for stream output entry.\n"); + return E_INVALIDARG; + } + } + + return S_OK; +} + +static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader, + struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length, + const D3D11_SO_DECLARATION_ENTRY *so_entries, unsigned int so_entry_count, + const unsigned int *buffer_strides, unsigned int buffer_stride_count, + unsigned int rasterizer_stream) +{ + struct wined3d_stream_output_desc so_desc; struct wined3d_shader_desc desc; + unsigned int i; HRESULT hr; - shader->ID3D11GeometryShader_iface.lpVtbl = &d3d11_geometry_shader_vtbl; - shader->ID3D10GeometryShader_iface.lpVtbl = &d3d10_geometry_shader_vtbl; - shader->refcount = 1; - wined3d_mutex_lock(); - wined3d_private_store_init(&shader->private_store); + if (so_entry_count > D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT) + { + WARN("Entry count %u is greater than %u.\n", + so_entry_count, D3D11_SO_STREAM_COUNT * D3D11_SO_OUTPUT_COMPONENT_COUNT); + return E_INVALIDARG; + } if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &desc, device->feature_level))) { WARN("Failed to extract shader, hr %#x.\n", hr); - wined3d_private_store_cleanup(&shader->private_store); - wined3d_mutex_unlock(); return hr; } desc.max_version = d3d_sm_from_feature_level(device->feature_level); - hr = wined3d_shader_create_gs(device->wined3d_device, &desc, NULL, shader, - &d3d_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader); + memset(&so_desc, 0, sizeof(so_desc)); + if (so_entries) + { + so_desc.element_count = so_entry_count; + for (i = 0; i < min(buffer_stride_count, ARRAY_SIZE(so_desc.buffer_strides)); ++i) + so_desc.buffer_strides[i] = buffer_strides[i]; + so_desc.buffer_stride_count = buffer_stride_count; + so_desc.rasterizer_stream_idx = rasterizer_stream; + + if (!(so_desc.elements = d3d11_calloc(so_entry_count, sizeof(*so_desc.elements)))) + { + ERR("Failed to allocate wined3d stream output element array memory.\n"); + shader_free_signature(&desc.input_signature); + shader_free_signature(&desc.output_signature); + return E_OUTOFMEMORY; + } + if (FAILED(hr = wined3d_so_elements_from_d3d11_so_entries(so_desc.elements, + so_entries, so_entry_count, &desc.output_signature))) + { + HeapFree(GetProcessHeap(), 0, so_desc.elements); + shader_free_signature(&desc.input_signature); + shader_free_signature(&desc.output_signature); + return hr; + } + } + + shader->ID3D11GeometryShader_iface.lpVtbl = &d3d11_geometry_shader_vtbl; + shader->ID3D10GeometryShader_iface.lpVtbl = &d3d10_geometry_shader_vtbl; + shader->refcount = 1; + wined3d_mutex_lock(); + wined3d_private_store_init(&shader->private_store); + + hr = wined3d_shader_create_gs(device->wined3d_device, &desc, so_entries ? &so_desc : NULL, + shader, &d3d_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader); + HeapFree(GetProcessHeap(), 0, so_desc.elements); shader_free_signature(&desc.input_signature); shader_free_signature(&desc.output_signature); if (FAILED(hr)) @@ -1229,6 +1307,8 @@ static HRESULT d3d_geometry_shader_init(struct d3d_geometry_shader *shader, stru } HRESULT d3d_geometry_shader_create(struct d3d_device *device, const void *byte_code, SIZE_T byte_code_length, + const D3D11_SO_DECLARATION_ENTRY *so_entries, unsigned int so_entry_count, + const unsigned int *buffer_strides, unsigned int buffer_stride_count, unsigned int rasterizer_stream, struct d3d_geometry_shader **shader) { struct d3d_geometry_shader *object; @@ -1237,7 +1317,8 @@ HRESULT d3d_geometry_shader_create(struct d3d_device *device, const void *byte_c if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) return E_OUTOFMEMORY; - if (FAILED(hr = d3d_geometry_shader_init(object, device, byte_code, byte_code_length))) + if (FAILED(hr = d3d_geometry_shader_init(object, device, byte_code, byte_code_length, + so_entries, so_entry_count, buffer_strides, buffer_stride_count, rasterizer_stream))) { WARN("Failed to initialize geometry shader, hr %#x.\n", hr); HeapFree(GetProcessHeap(), 0, object); diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 8523265..a3db181 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -11448,8 +11448,7 @@ static void test_index_buffer_offset(void) hr = ID3D11Device_CreateGeometryShaderWithStreamOutput(device, gs_code, sizeof(gs_code), so_declaration, sizeof(so_declaration) / sizeof(*so_declaration), &stride, 1, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &gs); - todo_wine ok(SUCCEEDED(hr), "Failed to create geometry shader with stream output, hr %#x.\n", hr); - if (FAILED(hr)) goto cleanup; + ok(SUCCEEDED(hr), "Failed to create geometry shader with stream output, hr %#x.\n", hr); hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), NULL, &vs); ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); @@ -11483,6 +11482,7 @@ static void test_index_buffer_offset(void) for (i = 0; i < sizeof(expected_data) / sizeof(*expected_data); ++i) { data = get_readback_vec4(&rb, i, 0); + todo_wine ok(compare_vec4(data, &expected_data[i], 0) || broken(is_nvidia_device(device) && !(i % 2) && compare_vec4(data, &broken_result, 0)), "Got unexpected result {%.8e, %.8e, %.8e, %.8e} at %u.\n", @@ -11495,7 +11495,6 @@ static void test_index_buffer_offset(void) ID3D11Buffer_Release(vb); ID3D11VertexShader_Release(vs); ID3D11GeometryShader_Release(gs); -cleanup: ID3D11InputLayout_Release(input_layout); release_test_context(&test_context); } -- 2.10.2