From ec0370a2d297e6436a4364d81c16c5ff86cc1684 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Mon, 30 Mar 2009 11:24:55 +0200 Subject: [PATCH] d3d10core: Create a vertex declaration from the input layout. --- dlls/d3d10core/d3d10core_private.h | 9 +- dlls/d3d10core/device.c | 23 ++++- dlls/d3d10core/inputlayout.c | 139 +++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 4 deletions(-) diff --git a/dlls/d3d10core/d3d10core_private.h b/dlls/d3d10core/d3d10core_private.h index ff723ba4066..df9794ff12b 100644 --- a/dlls/d3d10core/d3d10core_private.h +++ b/dlls/d3d10core/d3d10core_private.h @@ -1,5 +1,5 @@ /* - * Copyright 2008 Henri Verbeet for CodeWeavers + * Copyright 2008-2009 Henri Verbeet for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -38,6 +38,7 @@ ((DWORD)(ch0) | ((DWORD)(ch1) << 8) | \ ((DWORD)(ch2) << 16) | ((DWORD)(ch3) << 24 )) #define TAG_DXBC MAKE_TAG('D', 'X', 'B', 'C') +#define TAG_ISGN MAKE_TAG('I', 'S', 'G', 'N') /* TRACE helper functions */ const char *debug_d3d10_primitive_topology(D3D10_PRIMITIVE_TOPOLOGY topology); @@ -118,8 +119,14 @@ struct d3d10_input_layout { const struct ID3D10InputLayoutVtbl *vtbl; LONG refcount; + + IWineD3DVertexDeclaration *wined3d_decl; }; +HRESULT d3d10_input_layout_to_wined3d_declaration(const D3D10_INPUT_ELEMENT_DESC *element_descs, + UINT element_count, const void *shader_byte_code, SIZE_T shader_byte_code_length, + WINED3DVERTEXELEMENT **wined3d_elements, UINT *wined3d_element_count); + /* ID3D10VertexShader */ extern const struct ID3D10VertexShaderVtbl d3d10_vertex_shader_vtbl; struct d3d10_vertex_shader diff --git a/dlls/d3d10core/device.c b/dlls/d3d10core/device.c index 7320f92b9f2..ff31b53de52 100644 --- a/dlls/d3d10core/device.c +++ b/dlls/d3d10core/device.c @@ -1,5 +1,5 @@ /* - * Copyright 2008 Henri Verbeet for CodeWeavers + * Copyright 2008-2009 Henri Verbeet for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -909,10 +909,14 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateInputLayout(ID3D10Device *if const D3D10_INPUT_ELEMENT_DESC *element_descs, UINT element_count, const void *shader_byte_code, SIZE_T shader_byte_code_length, ID3D10InputLayout **input_layout) { + struct d3d10_device *This = (struct d3d10_device *)iface; struct d3d10_input_layout *object; + WINED3DVERTEXELEMENT *wined3d_elements; + UINT wined3d_element_count; + HRESULT hr; - FIXME("iface %p, element_descs %p, element_count %u, shader_byte_code %p," - "\tshader_byte_code_length %lu, input_layout %p stub!\n", + TRACE("iface %p, element_descs %p, element_count %u, shader_byte_code %p," + "\tshader_byte_code_length %lu, input_layout %p\n", iface, element_descs, element_count, shader_byte_code, shader_byte_code_length, input_layout); @@ -926,6 +930,19 @@ static HRESULT STDMETHODCALLTYPE d3d10_device_CreateInputLayout(ID3D10Device *if object->vtbl = &d3d10_input_layout_vtbl; object->refcount = 1; + hr = d3d10_input_layout_to_wined3d_declaration(element_descs, element_count, + shader_byte_code, shader_byte_code_length, &wined3d_elements, &wined3d_element_count); + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + IWineD3DDevice_CreateVertexDeclaration(This->wined3d_device, &object->wined3d_decl, + (IUnknown *)object, wined3d_elements, wined3d_element_count); + + HeapFree(GetProcessHeap(), 0, wined3d_elements); + *input_layout = (ID3D10InputLayout *)object; return S_OK; diff --git a/dlls/d3d10core/inputlayout.c b/dlls/d3d10core/inputlayout.c index 034a642d199..d78ecad7a91 100644 --- a/dlls/d3d10core/inputlayout.c +++ b/dlls/d3d10core/inputlayout.c @@ -24,6 +24,144 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d10core); +struct input_signature_element +{ + const char *semantic_name; + UINT semantic_idx; + DWORD unknown; /* system value semantic? */ + DWORD component_type; + UINT register_idx; + DWORD mask; +}; + +struct input_signature +{ + struct input_signature_element *elements; + UINT element_count; +}; + +static HRESULT parse_isgn(const char *data, struct input_signature *is) +{ + struct input_signature_element *e; + const char *ptr = data; + unsigned int i; + DWORD count; + + read_dword(&ptr, &count); + TRACE("%u elements\n", count); + + skip_dword_unknown(&ptr, 1); + + e = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*e)); + if (!e) + { + ERR("Failed to allocate input signature memory.\n"); + return E_OUTOFMEMORY; + } + + for (i = 0; i < count; ++i) + { + UINT name_offset; + + read_dword(&ptr, &name_offset); + e[i].semantic_name = data + name_offset; + read_dword(&ptr, &e[i].semantic_idx); + read_dword(&ptr, &e[i].unknown); + read_dword(&ptr, &e[i].component_type); + read_dword(&ptr, &e[i].register_idx); + read_dword(&ptr, &e[i].mask); + + TRACE("semantic: %s, semantic idx: %u, unknown %#x, type %u, register idx: %u, use_mask %#x, input_mask %#x\n", + e[i].semantic_name, e[i].semantic_idx, e[i].unknown, e[i].component_type, + e[i].register_idx, (e[i].mask >> 8) & 0xff, e[i].mask & 0xff); + } + + is->elements = e; + is->element_count = count; + + return S_OK; +} + +static HRESULT isgn_handler(const char *data, DWORD data_size, DWORD tag, void *ctx) +{ + struct input_signature *is = ctx; + const char *ptr = data; + char tag_str[5]; + + switch(tag) + { + case TAG_ISGN: + return parse_isgn(ptr, is); + + default: + memcpy(tag_str, &tag, 4); + tag_str[4] = '\0'; + FIXME("Unhandled chunk %s\n", tag_str); + return S_OK; + } +} + +HRESULT d3d10_input_layout_to_wined3d_declaration(const D3D10_INPUT_ELEMENT_DESC *element_descs, + UINT element_count, const void *shader_byte_code, SIZE_T shader_byte_code_length, + WINED3DVERTEXELEMENT **wined3d_elements, UINT *wined3d_element_count) +{ + struct input_signature is; + HRESULT hr; + UINT i; + + hr = parse_dxbc(shader_byte_code, shader_byte_code_length, isgn_handler, &is); + if (FAILED(hr)) + { + ERR("Failed to parse input signature.\n"); + return E_FAIL; + } + + *wined3d_elements = HeapAlloc(GetProcessHeap(), 0, element_count * sizeof(**wined3d_elements)); + if (!*wined3d_elements) + { + ERR("Failed to allocate wined3d vertex element array memory.\n"); + HeapFree(GetProcessHeap(), 0, is.elements); + return E_OUTOFMEMORY; + } + *wined3d_element_count = 0; + + for (i = 0; i < element_count; ++i) + { + UINT j; + + for (j = 0; j < is.element_count; ++j) + { + if (!strcmp(element_descs[i].SemanticName, is.elements[j].semantic_name) + && element_descs[i].SemanticIndex == is.elements[j].semantic_idx) + { + WINED3DVERTEXELEMENT *e = &(*wined3d_elements)[(*wined3d_element_count)++]; + const D3D10_INPUT_ELEMENT_DESC *f = &element_descs[i]; + + e->format = wined3dformat_from_dxgi_format(f->Format); + e->input_slot = f->InputSlot; + e->offset = f->AlignedByteOffset; + e->output_slot = is.elements[j].register_idx; + e->method = WINED3DDECLMETHOD_DEFAULT; + e->usage = 0; + e->usage_idx = 0; + + if (f->AlignedByteOffset == D3D10_APPEND_ALIGNED_ELEMENT) + FIXME("D3D10_APPEND_ALIGNED_ELEMENT not supported\n"); + if (f->InputSlotClass != D3D10_INPUT_PER_VERTEX_DATA) + FIXME("Ignoring input slot class (%#x)\n", f->InputSlotClass); + if (f->InstanceDataStepRate) + FIXME("Ignoring instace data step rate (%#x)\n", f->InstanceDataStepRate); + + break; + } + } + } + + HeapFree(GetProcessHeap(), 0, is.elements); + + return S_OK; +} + /* IUnknown methods */ static HRESULT STDMETHODCALLTYPE d3d10_input_layout_QueryInterface(ID3D10InputLayout *iface, @@ -65,6 +203,7 @@ static ULONG STDMETHODCALLTYPE d3d10_input_layout_Release(ID3D10InputLayout *ifa if (!refcount) { + IWineD3DVertexDeclaration_Release(This->wined3d_decl); HeapFree(GetProcessHeap(), 0, This); }