d3d11: Implement ID3D11DeviceContext::FinishCommandList().

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2021-05-27 11:14:33 -05:00 committed by Alexandre Julliard
parent 97d3ea26b9
commit 01658a4a8e
5 changed files with 277 additions and 1 deletions

View file

@ -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);

View file

@ -330,6 +330,124 @@ 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();
wined3d_private_store_cleanup(&list->private_store);
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,
};
static void d3d11_device_context_cleanup(struct d3d11_device_context *context)
{
wined3d_private_store_cleanup(&context->private_store);
@ -2635,9 +2753,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,

View file

@ -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;
}

View file

@ -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)

View file

@ -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,