From 4629cbdf8aae0f41dc0ee72aefaa94f77b1a21c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Tue, 10 Oct 2017 16:01:35 +0200 Subject: [PATCH] libs/vkd3d: Implement D3D12SerializeRootSignature(). --- include/d3d12.idl | 1 + libs/vkd3d/vkd3d_main.c | 166 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 165 insertions(+), 2 deletions(-) diff --git a/include/d3d12.idl b/include/d3d12.idl index 19b984c1..07218cda 100644 --- a/include/d3d12.idl +++ b/include/d3d12.idl @@ -68,6 +68,7 @@ interface ID3D10Blob : IUnknown } typedef ID3D10Blob ID3DBlob; +cpp_quote("#define IID_ID3DBlob IID_ID3D10Blob") typedef enum D3D_PRIMITIVE_TOPOLOGY { diff --git a/libs/vkd3d/vkd3d_main.c b/libs/vkd3d/vkd3d_main.c index 0b617ab3..af8c8bd2 100644 --- a/libs/vkd3d/vkd3d_main.c +++ b/libs/vkd3d/vkd3d_main.c @@ -47,6 +47,7 @@ HRESULT vkd3d_create_device(const struct vkd3d_device_create_info *create_info, riid, device); } +/* ID3D12RootSignatureDeserializer */ struct d3d12_root_signature_deserializer { ID3D12RootSignatureDeserializer ID3D12RootSignatureDeserializer_iface; @@ -66,8 +67,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_root_signature_deserializer_QueryInterfac { TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); - /* QueryInterface() implementation seems to be broken, E_NOINTERFACE is - * returned for IUnknown. */ + /* QueryInterface() implementation is broken, E_NOINTERFACE is returned for + * IUnknown. + */ if (IsEqualGUID(riid, &IID_ID3D12RootSignatureDeserializer)) { ID3D12RootSignatureDeserializer_AddRef(iface); @@ -166,3 +168,163 @@ HRESULT WINAPI D3D12CreateRootSignatureDeserializer(const void *data, SIZE_T dat return return_interface((IUnknown *)&object->ID3D12RootSignatureDeserializer_iface, &IID_ID3D12RootSignatureDeserializer, riid, deserializer); } + +/* ID3DBlob */ +struct d3d_blob +{ + ID3D10Blob ID3DBlob_iface; + LONG refcount; + + void *buffer; + SIZE_T size; +}; + +static struct d3d_blob *impl_from_ID3DBlob(ID3DBlob *iface) +{ + return CONTAINING_RECORD(iface, struct d3d_blob, ID3DBlob_iface); +} + +static HRESULT STDMETHODCALLTYPE d3d_blob_QueryInterface(ID3DBlob *iface, REFIID riid, void **object) +{ + TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object); + + if (IsEqualGUID(riid, &IID_ID3DBlob) + || IsEqualGUID(riid, &IID_IUnknown)) + { + ID3D10Blob_AddRef(iface); + *object = iface; + return S_OK; + } + + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid)); + + *object = NULL; + return E_NOINTERFACE; +} + +static ULONG STDMETHODCALLTYPE d3d_blob_AddRef(ID3DBlob *iface) +{ + struct d3d_blob *blob = impl_from_ID3DBlob(iface); + ULONG refcount = InterlockedIncrement(&blob->refcount); + + TRACE("%p increasing refcount to %u.\n", blob, refcount); + + return refcount; +} + +static ULONG STDMETHODCALLTYPE d3d_blob_Release(ID3DBlob *iface) +{ + struct d3d_blob *blob = impl_from_ID3DBlob(iface); + ULONG refcount = InterlockedDecrement(&blob->refcount); + + TRACE("%p decreasing refcount to %u.\n", blob, refcount); + + if (!refcount) + { + vkd3d_free(blob->buffer); + + vkd3d_free(blob); + } + + return refcount; +} + +static void * STDMETHODCALLTYPE d3d_blob_GetBufferPointer(ID3DBlob *iface) +{ + struct d3d_blob *blob = impl_from_ID3DBlob(iface); + + TRACE("iface %p.\n", iface); + + return blob->buffer; +} + +static SIZE_T STDMETHODCALLTYPE d3d_blob_GetBufferSize(ID3DBlob *iface) +{ + struct d3d_blob *blob = impl_from_ID3DBlob(iface); + + TRACE("iface %p.\n", iface); + + return blob->size; +} + +static const struct ID3D10BlobVtbl d3d_blob_vtbl = +{ + /* IUnknown methods */ + d3d_blob_QueryInterface, + d3d_blob_AddRef, + d3d_blob_Release, + /* ID3DBlob methods */ + d3d_blob_GetBufferPointer, + d3d_blob_GetBufferSize +}; + +static void d3d_blob_init(struct d3d_blob *blob, void *buffer, SIZE_T size) +{ + blob->ID3DBlob_iface.lpVtbl = &d3d_blob_vtbl; + blob->refcount = 1; + + blob->buffer = buffer; + blob->size = size; +} + +static HRESULT d3d_blob_create(void *buffer, SIZE_T size, struct d3d_blob **blob) +{ + struct d3d_blob *object; + + if (!(object = vkd3d_malloc(sizeof(*object)))) + return E_OUTOFMEMORY; + + d3d_blob_init(object, buffer, size); + + TRACE("Created blob object %p.\n", object); + + *blob = object; + + return S_OK; +} + +HRESULT WINAPI D3D12SerializeRootSignature(const D3D12_ROOT_SIGNATURE_DESC *root_signature_desc, + D3D_ROOT_SIGNATURE_VERSION version, ID3DBlob **blob, ID3DBlob **error_blob) +{ + struct vkd3d_shader_code dxbc; + struct d3d_blob *blob_object; + HRESULT hr; + + TRACE("root_signature_desc %p, version %#x, blob %p, error_blob %p.\n", + root_signature_desc, version, blob, error_blob); + + if (!blob) + { + WARN("Invalid blob parameter.\n"); + return E_INVALIDARG; + } + + if (version != D3D_ROOT_SIGNATURE_VERSION_1_0) + { + FIXME("Root signature version %#x is not supported.\n", version); + return E_NOTIMPL; + } + + if (error_blob) + { + FIXME("Ignoring error blob %p.\n", error_blob); + *error_blob = NULL; + } + + if (FAILED(hr = vkd3d_shader_serialize_root_signature(root_signature_desc, &dxbc))) + { + WARN("Failed to serialize root signature, hr %#x.\n", hr); + return hr; + } + + if (FAILED(hr = d3d_blob_create((void *)dxbc.code, dxbc.size, &blob_object))) + { + WARN("Failed to create blob object, hr %#x.\n", hr); + vkd3d_shader_free_shader_code(&dxbc); + return hr; + } + + *blob = &blob_object->ID3DBlob_iface; + + return S_OK; +}