[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