[PATCH v2 6/8] d3d11: Implement ID3D11DeviceContext::FinishCommandList().

Zebediah Figura z.figura12 at gmail.com
Wed May 26 21:14:48 CDT 2021


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/d3d11/d3d11_private.h |  10 +++
 dlls/d3d11/device.c        | 154 ++++++++++++++++++++++++++++++++++++-
 dlls/wined3d/cs.c          | 103 +++++++++++++++++++++++++
 dlls/wined3d/wined3d.spec  |   4 +
 include/wine/wined3d.h     |   6 ++
 5 files changed, 276 insertions(+), 1 deletion(-)

diff --git a/dlls/d3d11/d3d11_private.h b/dlls/d3d11/d3d11_private.h
index 2b5a51afbd1..afbde9a4bfb 100644
--- a/dlls/d3d11/d3d11_private.h
+++ b/dlls/d3d11/d3d11_private.h
@@ -583,6 +583,16 @@ struct d3d_device
     SIZE_T context_state_count;
 };
 
+struct d3d11_command_list
+{
+    ID3D11CommandList ID3D11CommandList_iface;
+    LONG refcount;
+
+    ID3D11Device2 *device;
+    struct wined3d_command_list *wined3d_list;
+    struct wined3d_private_store private_store;
+};
+
 static inline struct d3d_device *impl_from_ID3D11Device(ID3D11Device *iface)
 {
     return CONTAINING_RECORD((ID3D11Device2 *)iface, struct d3d_device, ID3D11Device2_iface);
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index 6f07bc92cdf..e832d8e68d3 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -330,6 +330,123 @@ static void d3d_device_context_state_init(struct d3d_device_context_state *state
     d3d_device_context_state_AddRef(&state->ID3DDeviceContextState_iface);
 }
 
+/* ID3D11CommandList methods */
+
+static inline struct d3d11_command_list *impl_from_ID3D11CommandList(ID3D11CommandList *iface)
+{
+    return CONTAINING_RECORD(iface, struct d3d11_command_list, ID3D11CommandList_iface);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d11_command_list_QueryInterface(ID3D11CommandList *iface, REFIID iid, void **out)
+{
+    TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+    if (IsEqualGUID(iid, &IID_ID3D11CommandList)
+            || IsEqualGUID(iid, &IID_ID3D11DeviceChild)
+            || IsEqualGUID(iid, &IID_IUnknown))
+    {
+        ID3D11CommandList_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+    *out = NULL;
+
+    return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d11_command_list_AddRef(ID3D11CommandList *iface)
+{
+    struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface);
+    ULONG refcount = InterlockedIncrement(&list->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", list, refcount);
+
+    return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d11_command_list_Release(ID3D11CommandList *iface)
+{
+    struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface);
+    ULONG refcount = InterlockedDecrement(&list->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", list, refcount);
+
+    if (!refcount)
+    {
+        wined3d_mutex_lock();
+        wined3d_command_list_decref(list->wined3d_list);
+        wined3d_mutex_unlock();
+        ID3D11Device2_Release(list->device);
+        heap_free(list);
+    }
+
+    return refcount;
+}
+
+static void STDMETHODCALLTYPE d3d11_command_list_GetDevice(ID3D11CommandList *iface, ID3D11Device **device)
+{
+    struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    *device = (ID3D11Device *)list->device;
+    ID3D11Device2_AddRef(list->device);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d11_command_list_GetPrivateData(ID3D11CommandList *iface, REFGUID guid,
+        UINT *data_size, void *data)
+{
+    struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface);
+
+    TRACE("iface %p, guid %s, data_size %p, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+    return d3d_get_private_data(&list->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d11_command_list_SetPrivateData(ID3D11CommandList *iface, REFGUID guid,
+        UINT data_size, const void *data)
+{
+    struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface);
+
+    TRACE("iface %p, guid %s, data_size %u, data %p.\n", iface, debugstr_guid(guid), data_size, data);
+
+    return d3d_set_private_data(&list->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d11_command_list_SetPrivateDataInterface(ID3D11CommandList *iface,
+        REFGUID guid, const IUnknown *data)
+{
+    struct d3d11_command_list *list = impl_from_ID3D11CommandList(iface);
+
+    TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+    return d3d_set_private_data_interface(&list->private_store, guid, data);
+}
+
+static UINT STDMETHODCALLTYPE d3d11_command_list_GetContextFlags(ID3D11CommandList *iface)
+{
+    TRACE("iface %p.\n", iface);
+
+    return 0;
+}
+
+static const struct ID3D11CommandListVtbl d3d11_command_list_vtbl =
+{
+    /* IUnknown methods */
+    d3d11_command_list_QueryInterface,
+    d3d11_command_list_AddRef,
+    d3d11_command_list_Release,
+    /* ID3D11DeviceChild methods */
+    d3d11_command_list_GetDevice,
+    d3d11_command_list_GetPrivateData,
+    d3d11_command_list_SetPrivateData,
+    d3d11_command_list_SetPrivateDataInterface,
+    /* ID3D11CommandList methods */
+    d3d11_command_list_GetContextFlags,
+};
+
 /* ID3D11DeviceContext - immediate context methods */
 
 static inline struct d3d11_device_context *impl_from_ID3D11DeviceContext1(ID3D11DeviceContext1 *iface)
@@ -2629,9 +2746,44 @@ static UINT STDMETHODCALLTYPE d3d11_device_context_GetContextFlags(ID3D11DeviceC
 static HRESULT STDMETHODCALLTYPE d3d11_device_context_FinishCommandList(ID3D11DeviceContext1 *iface,
         BOOL restore, ID3D11CommandList **command_list)
 {
+    struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface);
+    struct d3d11_command_list *object;
+    HRESULT hr;
+
     TRACE("iface %p, restore %#x, command_list %p.\n", iface, restore, command_list);
 
-    return DXGI_ERROR_INVALID_CALL;
+    if (context->type == D3D11_DEVICE_CONTEXT_IMMEDIATE)
+    {
+        WARN("Attempt to record command list on an immediate context; returning DXGI_ERROR_INVALID_CALL.\n");
+        return DXGI_ERROR_INVALID_CALL;
+    }
+
+    if (!(object = heap_alloc_zero(sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    wined3d_mutex_lock();
+
+    if (FAILED(hr = wined3d_deferred_context_record_command_list(context->wined3d_context,
+            !!restore, &object->wined3d_list)))
+    {
+        WARN("Failed to record wined3d command list, hr %#x.\n", hr);
+        heap_free(object);
+        return hr;
+    }
+
+    wined3d_mutex_unlock();
+
+    object->ID3D11CommandList_iface.lpVtbl = &d3d11_command_list_vtbl;
+    object->refcount = 1;
+    object->device = &context->device->ID3D11Device2_iface;
+    wined3d_private_store_init(&object->private_store);
+
+    ID3D11Device2_AddRef(object->device);
+
+    TRACE("Created command list %p.\n", object);
+    *command_list = &object->ID3D11CommandList_iface;
+
+    return S_OK;
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_CopySubresourceRegion1(ID3D11DeviceContext1 *iface,
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index b55bfdab866..db1c811a1f1 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -26,6 +26,59 @@ WINE_DECLARE_DEBUG_CHANNEL(fps);
 
 #define WINED3D_INITIAL_CS_SIZE 4096
 
+struct wined3d_command_list
+{
+    LONG refcount;
+
+    struct wined3d_device *device;
+
+    SIZE_T data_size;
+    void *data;
+
+    SIZE_T resource_count;
+    struct wined3d_resource **resources;
+};
+
+static void wined3d_command_list_destroy_object(void *object)
+{
+    struct wined3d_command_list *list = object;
+
+    TRACE("list %p.\n", list);
+
+    heap_free(list->resources);
+    heap_free(list->data);
+    heap_free(list);
+}
+
+ULONG CDECL wined3d_command_list_incref(struct wined3d_command_list *list)
+{
+    ULONG refcount = InterlockedIncrement(&list->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", list, refcount);
+
+    return refcount;
+}
+
+ULONG CDECL wined3d_command_list_decref(struct wined3d_command_list *list)
+{
+    ULONG refcount = InterlockedDecrement(&list->refcount);
+    struct wined3d_device *device = list->device;
+
+    TRACE("%p decreasing refcount to %u.\n", list, refcount);
+
+    if (!refcount)
+    {
+        SIZE_T i;
+
+        for (i = 0; i < list->resource_count; ++i)
+            wined3d_resource_decref(list->resources[i]);
+
+        wined3d_cs_destroy_object(device->cs, wined3d_command_list_destroy_object, list);
+    }
+
+    return refcount;
+}
+
 enum wined3d_cs_op
 {
     WINED3D_CS_OP_NOP,
@@ -3333,3 +3386,53 @@ void CDECL wined3d_deferred_context_destroy(struct wined3d_device_context *conte
     heap_free(deferred->data);
     heap_free(deferred);
 }
+
+HRESULT CDECL wined3d_deferred_context_record_command_list(struct wined3d_device_context *context,
+        bool restore, struct wined3d_command_list **list)
+{
+    struct wined3d_deferred_context *deferred = wined3d_deferred_context_from_context(context);
+    struct wined3d_command_list *object;
+
+    TRACE("context %p, list %p.\n", context, list);
+
+    if (restore)
+    {
+        FIXME("Restoring context state is not implemented.\n");
+        return E_NOTIMPL;
+    }
+
+    if (!(object = heap_alloc_zero(sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    object->refcount = 1;
+    object->device = deferred->c.device;
+
+    if (!(object->data = heap_alloc(deferred->data_size)))
+    {
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
+    object->data_size = deferred->data_size;
+    memcpy(object->data, deferred->data, deferred->data_size);
+
+    if (!(object->resources = heap_alloc(deferred->resource_count * sizeof(*object->resources))))
+    {
+        heap_free(object->data);
+        heap_free(object);
+        return E_OUTOFMEMORY;
+    }
+    object->resource_count = deferred->resource_count;
+    memcpy(object->resources, deferred->resources, deferred->resource_count * sizeof(*object->resources));
+    /* Transfer our references to the resources to the command list. */
+
+    deferred->data_size = 0;
+    deferred->resource_count = 0;
+
+    /* This is in fact recorded into a subsequent command list. */
+    wined3d_device_context_reset_state(&deferred->c);
+
+    TRACE("Created command list %p.\n", object);
+    *list = object;
+
+    return S_OK;
+}
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index 84412515c39..6683b3bc30f 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -33,8 +33,12 @@
 @ cdecl wined3d_buffer_get_resource(ptr)
 @ cdecl wined3d_buffer_incref(ptr)
 
+@ cdecl wined3d_command_list_decref(ptr)
+@ cdecl wined3d_command_list_incref(ptr)
+
 @ cdecl wined3d_deferred_context_create(ptr ptr)
 @ cdecl wined3d_deferred_context_destroy(ptr)
+@ cdecl wined3d_deferred_context_record_command_list(ptr long ptr)
 
 @ cdecl wined3d_depth_stencil_state_create(ptr ptr ptr ptr ptr)
 @ cdecl wined3d_depth_stencil_state_decref(ptr)
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 812c042cdd7..bb6bf58a822 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2221,6 +2221,7 @@ struct wined3d;
 struct wined3d_adapter;
 struct wined3d_blend_state;
 struct wined3d_buffer;
+struct wined3d_command_list;
 struct wined3d_depth_stencil_state;
 struct wined3d_device;
 struct wined3d_device_context;
@@ -2340,8 +2341,13 @@ void * __cdecl wined3d_buffer_get_parent(const struct wined3d_buffer *buffer);
 struct wined3d_resource * __cdecl wined3d_buffer_get_resource(struct wined3d_buffer *buffer);
 ULONG __cdecl wined3d_buffer_incref(struct wined3d_buffer *buffer);
 
+ULONG __cdecl wined3d_command_list_decref(struct wined3d_command_list *list);
+ULONG __cdecl wined3d_command_list_incref(struct wined3d_command_list *list);
+
 HRESULT __cdecl wined3d_deferred_context_create(struct wined3d_device *device, struct wined3d_device_context **context);
 void __cdecl wined3d_deferred_context_destroy(struct wined3d_device_context *context);
+HRESULT __cdecl wined3d_deferred_context_record_command_list(struct wined3d_device_context *context,
+        bool restore, struct wined3d_command_list **list);
 
 HRESULT __cdecl wined3d_depth_stencil_state_create(struct wined3d_device *device,
         const struct wined3d_depth_stencil_state_desc *desc, void *parent,
-- 
2.30.2




More information about the wine-devel mailing list