From c093321833140c3aadacae32c43d160e83483d17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Thu, 19 Jan 2017 16:56:56 +0100
Subject: [PATCH] d3d11: Initial implementation for deferred contexts.

---
 dlls/d3d11/device.c | 1073 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 1042 insertions(+), 31 deletions(-)

diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index dca5a88caa..738f1d19d4 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -17,11 +17,181 @@
  *
  */
 
+#include "wine/list.h"
+
 #define NONAMELESSUNION
 #include "d3d11_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d11);
 
+enum deferred_cmd
+{
+    DEFERRED_IASETVERTEXBUFFERS,        /* vbuffer_info */
+    DEFERRED_IASETPRIMITIVETOPOLOGY,    /* topology_info */
+    DEFERRED_IASETINDEXBUFFER,          /* index_buffer_info */
+    DEFERRED_IASETINPUTLAYOUT,          /* input_layout_info */
+
+    DEFERRED_RSSETSTATE,                /* rstate_info */
+    DEFERRED_RSSETVIEWPORTS,            /* viewport_info */
+
+    DEFERRED_OMSETDEPTHSTENCILSTATE,    /* stencil_state_info */
+    DEFERRED_OMSETBLENDSTATE,           /* blend_state_info */
+    DEFERRED_OMSETRENDERTARGETS,        /* render_target_info */
+
+    DEFERRED_DSSETSHADER,               /* ds_info */
+    DEFERRED_HSSETSHADER,               /* hs_info */
+    DEFERRED_PSSETSHADER,               /* ps_info */
+    DEFERRED_VSSETSHADER,               /* vs_info */
+
+    DEFERRED_DSSETSHADERRESOURCES,      /* res_info */
+    DEFERRED_PSSETSHADERRESOURCES,      /* res_info */
+
+    DEFERRED_DSSETSAMPLERS,             /* samplers_info */
+    DEFERRED_PSSETSAMPLERS,             /* samplers_info */
+
+    DEFERRED_DSSETCONSTANTBUFFERS,      /* constant_buffers_info */
+    DEFERRED_HSSETCONSTANTBUFFERS,      /* constant_buffers_info */
+    DEFERRED_PSSETCONSTANTBUFFERS,      /* constant_buffers_info */
+    DEFERRED_VSSETCONSTANTBUFFERS,      /* constant_buffers_info */
+
+    DEFERRED_DRAWINDEXED,               /* draw_indexed_info */
+    DEFERRED_DRAWINDEXEDINSTANCED,      /* draw_indexed_inst_info */
+
+    DEFERRED_MAP,                       /* map_info */
+
+    DEFERRED_CLEARSTATE,
+};
+
+struct deferred_call
+{
+    struct list entry;
+    enum deferred_cmd cmd;
+    union
+    {
+        struct
+        {
+            UINT start_slot;
+            UINT num_buffers;
+            ID3D11Buffer **buffers;
+            UINT *strides;
+            UINT *offsets;
+        } vbuffer_info;
+        struct
+        {
+            D3D11_PRIMITIVE_TOPOLOGY topology;
+        } topology_info;
+        struct
+        {
+            ID3D11Buffer *buffer;
+            DXGI_FORMAT format;
+            UINT offset;
+        } index_buffer_info;
+        struct
+        {
+            ID3D11InputLayout *layout;
+        } input_layout_info;
+        struct
+        {
+            ID3D11RasterizerState *state;
+        } rstate_info;
+        struct
+        {
+            UINT num_viewports;
+            D3D11_VIEWPORT *viewports;
+        } viewport_info;
+        struct
+        {
+            ID3D11DepthStencilState *state;
+            UINT stencil_ref;
+        } stencil_state_info;
+        struct
+        {
+            ID3D11BlendState *state;
+            FLOAT factor[4];
+            UINT mask;
+        } blend_state_info;
+        struct
+        {
+            UINT num_views;
+            ID3D11RenderTargetView **render_targets;
+            ID3D11DepthStencilView *depth_stencil;
+        } render_target_info;
+        struct
+        {
+            ID3D11DomainShader *shader;
+            /* FIXME: add class instances */
+        } ds_info;
+        struct
+        {
+            ID3D11HullShader *shader;
+            /* FIXME: add class instances */
+        } hs_info;
+        struct
+        {
+            ID3D11PixelShader *shader;
+            /* FIXME: add class instances */
+        } ps_info;
+        struct
+        {
+            ID3D11VertexShader *shader;
+            /* FIXME: add class instances */
+        } vs_info;
+        struct
+        {
+            UINT start_slot;
+            UINT num_views;
+            ID3D11ShaderResourceView **views;
+        } res_info;
+        struct
+        {
+            UINT start_slot;
+            UINT num_samplers;
+            ID3D11SamplerState **samplers;
+        } samplers_info;
+        struct
+        {
+            UINT start_slot;
+            UINT num_buffers;
+            ID3D11Buffer **buffers;
+        } constant_buffers_info;
+        struct
+        {
+            UINT count;
+            UINT start_index;
+            INT  base_vertex;
+        } draw_indexed_info;
+        struct
+        {
+            UINT count_per_instance;
+            UINT instance_count;
+            UINT start_index;
+            INT  base_vertex;
+            UINT start_instance;
+        } draw_indexed_inst_info;
+        struct
+        {
+            ID3D11Resource *resource;
+            UINT subresource_idx;
+            D3D11_MAP map_type;
+            UINT map_flags;
+            void *buffer;
+            UINT size;
+        } map_info;
+    };
+};
+
+/* ID3D11CommandList - command list */
+struct d3d11_command_list
+{
+    ID3D11CommandList ID3D11CommandList_iface;
+    ID3D11Device *device;
+    LONG refcount;
+
+    struct list commands;
+
+    struct wined3d_private_store private_store;
+};
+
 /* ID3D11DeviceContext - deferred context */
 struct d3d11_deferred_context
 {
@@ -29,9 +199,532 @@ struct d3d11_deferred_context
     ID3D11Device *device;
     LONG refcount;
 
+    struct list commands;
+
     struct wined3d_private_store private_store;
 };
 
+static struct deferred_call *add_deferred_call(struct d3d11_deferred_context *context, size_t extra_size)
+{
+    struct deferred_call *call;
+
+    if (!(call = HeapAlloc(GetProcessHeap(), 0, sizeof(*call) + extra_size)))
+        return NULL;
+
+    call->cmd = 0xdeadbeef;
+    list_add_tail(&context->commands, &call->entry);
+    return call;
+}
+
+/* for DEFERRED_DSSETSHADERRESOURCES and DEFERRED_PSSETSHADERRESOURCES */
+static void add_deferred_set_shader_resources(struct d3d11_deferred_context *context, enum deferred_cmd cmd,
+        UINT start_slot, UINT view_count, ID3D11ShaderResourceView *const *views)
+{
+    struct deferred_call *call;
+    int i;
+
+    if (!(call = add_deferred_call(context, sizeof(*views) * view_count)))
+        return;
+
+    call->cmd = cmd;
+    call->res_info.start_slot = start_slot;
+    call->res_info.num_views = view_count;
+    call->res_info.views = (void *)(call + 1);
+    for (i = 0; i < view_count; i++)
+    {
+        if (views[i]) ID3D11ShaderResourceView_AddRef(views[i]);
+        call->res_info.views[i] = views[i];
+    }
+}
+
+/* for DEFERRED_DSSETSAMPLERS and DEFERRED_PSSETSAMPLERS */
+static void add_deferred_set_samplers(struct d3d11_deferred_context *context, enum deferred_cmd cmd,
+        UINT start_slot, UINT sampler_count, ID3D11SamplerState *const *samplers)
+{
+    struct deferred_call *call;
+    int i;
+
+    if (!(call = add_deferred_call(context, sizeof(*samplers) * sampler_count)))
+        return;
+
+    call->cmd = cmd;
+    call->samplers_info.start_slot = start_slot;
+    call->samplers_info.num_samplers = sampler_count;
+    call->samplers_info.samplers = (void *)(call + 1);
+    for (i = 0; i < sampler_count; i++)
+    {
+        if (samplers[i]) ID3D11SamplerState_AddRef(samplers[i]);
+        call->samplers_info.samplers[i] = samplers[i];
+    }
+}
+
+/* for DEFERRED_DSSETCONSTANTBUFFERS, DEFERRED_HSSETCONSTANTBUFFERS,
+ * DEFERRED_PSSETCONSTANTBUFFERS and DEFERRED_VSSETCONSTANTBUFFERS */
+static void add_deferred_set_constant_buffers(struct d3d11_deferred_context *context, enum deferred_cmd cmd,
+        UINT start_slot, UINT buffer_count, ID3D11Buffer *const *buffers)
+{
+    struct deferred_call *call;
+    int i;
+
+    if (!(call = add_deferred_call(context, sizeof(*buffers) * buffer_count)))
+        return;
+
+    call->cmd = cmd;
+    call->constant_buffers_info.start_slot = start_slot;
+    call->constant_buffers_info.num_buffers = buffer_count;
+    call->constant_buffers_info.buffers = (void *)(call + 1);
+    for (i = 0; i < buffer_count; i++)
+    {
+        if (buffers[i]) ID3D11Buffer_AddRef(buffers[i]);
+        call->constant_buffers_info.buffers[i] = buffers[i];
+    }
+}
+
+static void free_deferred_calls(struct list *commands)
+{
+    struct deferred_call *call, *call2;
+    int i;
+
+    LIST_FOR_EACH_ENTRY_SAFE(call, call2, commands, struct deferred_call, entry)
+    {
+        switch (call->cmd)
+        {
+            case DEFERRED_IASETVERTEXBUFFERS:
+            {
+                for (i = 0; i < call->vbuffer_info.num_buffers; i++)
+                {
+                    if (call->vbuffer_info.buffers[i])
+                        ID3D11Buffer_Release(call->vbuffer_info.buffers[i]);
+                }
+                break;
+            }
+            case DEFERRED_IASETPRIMITIVETOPOLOGY:
+            {
+                break; /* nothing to do */
+            }
+            case DEFERRED_IASETINDEXBUFFER:
+            {
+                if (call->index_buffer_info.buffer)
+                    ID3D11Buffer_Release(call->index_buffer_info.buffer);
+                break;
+            }
+            case DEFERRED_IASETINPUTLAYOUT:
+            {
+                if (call->input_layout_info.layout)
+                    ID3D11InputLayout_Release(call->input_layout_info.layout);
+                break;
+            }
+            case DEFERRED_RSSETSTATE:
+            {
+                if (call->rstate_info.state)
+                    ID3D11RasterizerState_Release(call->rstate_info.state);
+                break;
+            }
+            case DEFERRED_RSSETVIEWPORTS:
+            {
+                break; /* nothing to do */
+            }
+            case DEFERRED_OMSETDEPTHSTENCILSTATE:
+            {
+                if (call->stencil_state_info.state)
+                    ID3D11DepthStencilState_Release(call->stencil_state_info.state);
+                break;
+            }
+            case DEFERRED_OMSETBLENDSTATE:
+            {
+                if (call->blend_state_info.state)
+                    ID3D11BlendState_Release(call->blend_state_info.state);
+                break;
+            }
+            case DEFERRED_OMSETRENDERTARGETS:
+            {
+                for (i = 0; i < call->render_target_info.num_views; i++)
+                {
+                    if (call->render_target_info.render_targets[i])
+                        ID3D11RenderTargetView_Release(call->render_target_info.render_targets[i]);
+                }
+                if (call->render_target_info.depth_stencil)
+                    ID3D11DepthStencilView_Release(call->render_target_info.depth_stencil);
+                break;
+            }
+            case DEFERRED_DSSETSHADER:
+            {
+                if (call->ds_info.shader)
+                    ID3D11DomainShader_Release(call->ds_info.shader);
+                break;
+            }
+            case DEFERRED_HSSETSHADER:
+            {
+                if (call->hs_info.shader)
+                    ID3D11HullShader_Release(call->hs_info.shader);
+                break;
+            }
+            case DEFERRED_PSSETSHADER:
+            {
+                if (call->ps_info.shader)
+                    ID3D11PixelShader_Release(call->ps_info.shader);
+                break;
+            }
+            case DEFERRED_VSSETSHADER:
+            {
+                if (call->vs_info.shader)
+                    ID3D11VertexShader_Release(call->vs_info.shader);
+                break;
+            }
+            case DEFERRED_DSSETSHADERRESOURCES:
+            case DEFERRED_PSSETSHADERRESOURCES:
+            {
+                for (i = 0; i < call->res_info.num_views; i++)
+                {
+                    if (call->res_info.views[i])
+                        ID3D11ShaderResourceView_Release(call->res_info.views[i]);
+                }
+                break;
+            }
+            case DEFERRED_DSSETSAMPLERS:
+            case DEFERRED_PSSETSAMPLERS:
+            {
+                for (i = 0; i < call->samplers_info.num_samplers; i++)
+                {
+                    if (call->samplers_info.samplers[i])
+                        ID3D11SamplerState_Release(call->samplers_info.samplers[i]);
+                }
+                break;
+            }
+            case DEFERRED_DSSETCONSTANTBUFFERS:
+            case DEFERRED_HSSETCONSTANTBUFFERS:
+            case DEFERRED_PSSETCONSTANTBUFFERS:
+            case DEFERRED_VSSETCONSTANTBUFFERS:
+            {
+                for (i = 0; i < call->constant_buffers_info.num_buffers; i++)
+                {
+                    if (call->constant_buffers_info.buffers[i])
+                        ID3D11Buffer_Release(call->constant_buffers_info.buffers[i]);
+                }
+                break;
+            }
+            case DEFERRED_DRAWINDEXED:
+            case DEFERRED_DRAWINDEXEDINSTANCED:
+            {
+                break; /* nothing to do */
+            }
+            case DEFERRED_MAP:
+            {
+                ID3D11Resource_Release(call->map_info.resource);
+                break;
+            }
+            case DEFERRED_CLEARSTATE:
+            {
+                break; /* nothing to do */
+            }
+            default:
+            {
+                FIXME("Unimplemented command type %u\n", call->cmd);
+                break;
+            }
+        }
+
+        list_remove(&call->entry);
+        HeapFree(GetProcessHeap(), 0, call);
+    }
+}
+
+static void exec_deferred_calls(ID3D11DeviceContext1 *iface, struct list *commands)
+{
+    struct deferred_call *call;
+
+    LIST_FOR_EACH_ENTRY(call, commands, struct deferred_call, entry)
+    {
+        switch (call->cmd)
+        {
+            case DEFERRED_IASETVERTEXBUFFERS:
+            {
+                ID3D11DeviceContext1_IASetVertexBuffers(iface, call->vbuffer_info.start_slot,
+                        call->vbuffer_info.num_buffers, call->vbuffer_info.buffers,
+                        call->vbuffer_info.strides, call->vbuffer_info.offsets);
+                break;
+            }
+            case DEFERRED_IASETPRIMITIVETOPOLOGY:
+            {
+                ID3D11DeviceContext1_IASetPrimitiveTopology(iface, call->topology_info.topology);
+                break;
+            }
+            case DEFERRED_IASETINDEXBUFFER:
+            {
+                ID3D11DeviceContext1_IASetIndexBuffer(iface, call->index_buffer_info.buffer,
+                        call->index_buffer_info.format, call->index_buffer_info.offset);
+                break;
+            }
+            case DEFERRED_IASETINPUTLAYOUT:
+            {
+                ID3D11DeviceContext1_IASetInputLayout(iface, call->input_layout_info.layout);
+                break;
+            }
+            case DEFERRED_RSSETSTATE:
+            {
+                ID3D11DeviceContext1_RSSetState(iface, call->rstate_info.state);
+                break;
+            }
+            case DEFERRED_RSSETVIEWPORTS:
+            {
+                ID3D11DeviceContext1_RSSetViewports(iface, call->viewport_info.num_viewports,
+                        call->viewport_info.viewports);
+                break;
+            }
+            case DEFERRED_OMSETDEPTHSTENCILSTATE:
+            {
+                ID3D11DeviceContext1_OMSetDepthStencilState(iface, call->stencil_state_info.state,
+                        call->stencil_state_info.stencil_ref);
+                break;
+            }
+            case DEFERRED_OMSETBLENDSTATE:
+            {
+                ID3D11DeviceContext1_OMSetBlendState(iface, call->blend_state_info.state,
+                        call->blend_state_info.factor, call->blend_state_info.mask);
+                break;
+            }
+            case DEFERRED_OMSETRENDERTARGETS:
+            {
+                ID3D11DeviceContext1_OMSetRenderTargets(iface, call->render_target_info.num_views,
+                        call->render_target_info.render_targets, call->render_target_info.depth_stencil);
+                break;
+            }
+            case DEFERRED_DSSETSHADER:
+            {
+                ID3D11DeviceContext1_DSSetShader(iface, call->ds_info.shader, NULL, 0);
+                break;
+            }
+            case DEFERRED_HSSETSHADER:
+            {
+                ID3D11DeviceContext1_HSSetShader(iface, call->hs_info.shader, NULL, 0);
+                break;
+            }
+            case DEFERRED_PSSETSHADER:
+            {
+                ID3D11DeviceContext1_PSSetShader(iface, call->ps_info.shader, NULL, 0);
+                break;
+            }
+            case DEFERRED_VSSETSHADER:
+            {
+                ID3D11DeviceContext1_VSSetShader(iface, call->vs_info.shader, NULL, 0);
+                break;
+            }
+            case DEFERRED_DSSETSHADERRESOURCES:
+            {
+                ID3D11DeviceContext1_DSSetShaderResources(iface, call->res_info.start_slot,
+                    call->res_info.num_views, call->res_info.views);
+                break;
+            }
+            case DEFERRED_PSSETSHADERRESOURCES:
+            {
+                ID3D11DeviceContext1_PSSetShaderResources(iface, call->res_info.start_slot,
+                        call->res_info.num_views, call->res_info.views);
+                break;
+            }
+            case DEFERRED_DSSETSAMPLERS:
+            {
+                ID3D11DeviceContext1_DSSetSamplers(iface, call->samplers_info.start_slot,
+                        call->samplers_info.num_samplers, call->samplers_info.samplers);
+                break;
+            }
+            case DEFERRED_PSSETSAMPLERS:
+            {
+                ID3D11DeviceContext1_PSSetSamplers(iface, call->samplers_info.start_slot,
+                        call->samplers_info.num_samplers, call->samplers_info.samplers);
+                break;
+            }
+            case DEFERRED_DSSETCONSTANTBUFFERS:
+            {
+                ID3D11DeviceContext1_DSSetConstantBuffers(iface, call->constant_buffers_info.start_slot,
+                        call->constant_buffers_info.num_buffers, call->constant_buffers_info.buffers);
+                break;
+            }
+            case DEFERRED_HSSETCONSTANTBUFFERS:
+            {
+                ID3D11DeviceContext1_HSSetConstantBuffers(iface, call->constant_buffers_info.start_slot,
+                        call->constant_buffers_info.num_buffers, call->constant_buffers_info.buffers);
+                break;
+            }
+            case DEFERRED_PSSETCONSTANTBUFFERS:
+            {
+                ID3D11DeviceContext1_PSSetConstantBuffers(iface, call->constant_buffers_info.start_slot,
+                        call->constant_buffers_info.num_buffers, call->constant_buffers_info.buffers);
+                break;
+            }
+            case DEFERRED_VSSETCONSTANTBUFFERS:
+            {
+                ID3D11DeviceContext1_VSSetConstantBuffers(iface, call->constant_buffers_info.start_slot,
+                        call->constant_buffers_info.num_buffers, call->constant_buffers_info.buffers);
+                break;
+            }
+            case DEFERRED_DRAWINDEXED:
+            {
+                ID3D11DeviceContext1_DrawIndexed(iface, call->draw_indexed_info.count,
+                        call->draw_indexed_info.start_index, call->draw_indexed_info.base_vertex);
+                break;
+            }
+            case DEFERRED_DRAWINDEXEDINSTANCED:
+            {
+                ID3D11DeviceContext1_DrawIndexedInstanced(iface, call->draw_indexed_inst_info.count_per_instance,
+                        call->draw_indexed_inst_info.instance_count, call->draw_indexed_inst_info.start_index,
+                        call->draw_indexed_inst_info.base_vertex, call->draw_indexed_inst_info.start_instance);
+                break;
+            }
+            case DEFERRED_MAP:
+            {
+                D3D11_MAPPED_SUBRESOURCE mapped;
+                HRESULT hr;
+
+                hr = ID3D11DeviceContext1_Map(iface, call->map_info.resource, call->map_info.subresource_idx,
+                        call->map_info.map_type, call->map_info.map_flags, &mapped);
+                if (SUCCEEDED(hr))
+                {
+                    memcpy(mapped.pData, call->map_info.buffer, call->map_info.size);
+                    ID3D11DeviceContext1_Unmap(iface, call->map_info.resource, call->map_info.subresource_idx);
+                }
+                else
+                    FIXME("Failed to map subresource!\n");
+
+                break;
+            }
+            case DEFERRED_CLEARSTATE:
+            {
+                ID3D11DeviceContext1_ClearState(iface);
+                break;
+            }
+            default:
+            {
+                FIXME("Unimplemented command type %u\n", call->cmd);
+                break;
+            }
+        }
+    }
+}
+
+/* ID3D11CommandList - command list 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 riid, void **out)
+{
+    TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
+
+    if (IsEqualGUID(riid, &IID_ID3D11CommandList)
+            || IsEqualGUID(riid, &IID_ID3D11DeviceChild)
+            || IsEqualGUID(riid, &IID_IUnknown))
+    {
+        ID3D11CommandList_AddRef(iface);
+        *out = iface;
+        return S_OK;
+    }
+
+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG STDMETHODCALLTYPE d3d11_command_list_AddRef(ID3D11CommandList *iface)
+{
+    struct d3d11_command_list *cmdlist = impl_from_ID3D11CommandList(iface);
+    ULONG refcount = InterlockedIncrement(&cmdlist->refcount);
+
+    TRACE("%p increasing refcount to %u.\n", cmdlist, refcount);
+
+    return refcount;
+}
+
+static ULONG STDMETHODCALLTYPE d3d11_command_list_Release(ID3D11CommandList *iface)
+{
+    struct d3d11_command_list *cmdlist = impl_from_ID3D11CommandList(iface);
+    ULONG refcount = InterlockedDecrement(&cmdlist->refcount);
+
+    TRACE("%p decreasing refcount to %u.\n", cmdlist, refcount);
+
+    if (!refcount)
+    {
+        free_deferred_calls(&cmdlist->commands);
+        wined3d_private_store_cleanup(&cmdlist->private_store);
+        ID3D11Device_Release(cmdlist->device);
+        HeapFree(GetProcessHeap(), 0, cmdlist);
+    }
+
+    return refcount;
+}
+
+static void STDMETHODCALLTYPE d3d11_command_list_GetDevice(ID3D11CommandList *iface, ID3D11Device **device)
+{
+    struct d3d11_command_list *cmdlist = impl_from_ID3D11CommandList(iface);
+
+    TRACE("iface %p, device %p.\n", iface, device);
+
+    ID3D11Device_AddRef(cmdlist->device);
+    *device = cmdlist->device;
+}
+
+static HRESULT STDMETHODCALLTYPE d3d11_command_list_GetPrivateData(ID3D11CommandList *iface, REFGUID guid,
+        UINT *data_size, void *data)
+{
+    struct d3d11_command_list *cmdlist = 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(&cmdlist->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 *cmdlist = 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(&cmdlist->private_store, guid, data_size, data);
+}
+
+static HRESULT STDMETHODCALLTYPE d3d11_command_list_SetPrivateDataInterface(ID3D11CommandList *iface,
+        REFGUID guid, const IUnknown *data)
+{
+    struct d3d11_command_list *cmdlist = impl_from_ID3D11CommandList(iface);
+
+    TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
+
+    return d3d_set_private_data_interface(&cmdlist->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 inline struct d3d11_command_list *unsafe_impl_from_ID3D11CommandList(ID3D11CommandList *iface)
+{
+    if (!iface)
+        return NULL;
+    assert(iface->lpVtbl == &d3d11_command_list_vtbl);
+    return CONTAINING_RECORD(iface, struct d3d11_command_list, ID3D11CommandList_iface);
+}
+
 static void STDMETHODCALLTYPE d3d_null_wined3d_object_destroyed(void *parent) {}
 
 static const struct wined3d_parent_ops d3d_null_wined3d_parent_ops =
@@ -1226,7 +1919,20 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_ResolveSubresource(ID3D11D
 static void STDMETHODCALLTYPE d3d11_immediate_context_ExecuteCommandList(ID3D11DeviceContext1 *iface,
         ID3D11CommandList *command_list, BOOL restore_state)
 {
-    FIXME("iface %p, command_list %p, restore_state %#x stub!\n", iface, command_list, restore_state);
+    struct d3d11_command_list *cmdlist = unsafe_impl_from_ID3D11CommandList(command_list);
+
+    TRACE("iface %p, command_list %p, restore_state %#x.\n", iface, command_list, restore_state);
+
+    if (!cmdlist)
+        return;
+
+    if (restore_state)
+        FIXME("restoring state not supported!\n");
+
+    wined3d_mutex_lock();
+    exec_deferred_calls(iface, &cmdlist->commands);
+    ID3D11DeviceContext1_ClearState(iface);
+    wined3d_mutex_unlock();
 }
 
 static void STDMETHODCALLTYPE d3d11_immediate_context_HSSetShaderResources(ID3D11DeviceContext1 *iface,
@@ -2938,6 +3644,7 @@ static ULONG STDMETHODCALLTYPE d3d11_deferred_context_Release(ID3D11DeviceContex
 
     if (!refcount)
     {
+        free_deferred_calls(&context->commands);
         wined3d_private_store_cleanup(&context->private_store);
         ID3D11Device_Release(context->device);
         HeapFree(GetProcessHeap(), 0, context);
@@ -2989,43 +3696,86 @@ static HRESULT STDMETHODCALLTYPE d3d11_deferred_context_SetPrivateDataInterface(
 static void STDMETHODCALLTYPE d3d11_deferred_context_VSSetConstantBuffers(ID3D11DeviceContext *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer *const *buffers)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p.\n",
             iface, start_slot, buffer_count, buffers);
+
+    add_deferred_set_constant_buffers(context, DEFERRED_VSSETCONSTANTBUFFERS, start_slot, buffer_count, buffers);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_PSSetShaderResources(ID3D11DeviceContext *iface,
         UINT start_slot, UINT view_count, ID3D11ShaderResourceView *const *views)
 {
-    FIXME("iface %p, start_slot %u, view_count %u, views %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+
+    TRACE("iface %p, start_slot %u, view_count %u, views %p.\n",
             iface, start_slot, view_count, views);
+
+    add_deferred_set_shader_resources(context, DEFERRED_PSSETSHADERRESOURCES, start_slot, view_count, views);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_PSSetShader(ID3D11DeviceContext *iface,
         ID3D11PixelShader *shader, ID3D11ClassInstance *const *class_instances, UINT class_instance_count)
 {
-    FIXME("iface %p, shader %p, class_instances %p, class_instance_count %u stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, shader %p, class_instances %p, class_instance_count %u.\n",
             iface, shader, class_instances, class_instance_count);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_PSSETSHADER;
+    if (shader) ID3D11PixelShader_AddRef(shader);
+    call->ps_info.shader = shader;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_PSSetSamplers(ID3D11DeviceContext *iface,
         UINT start_slot, UINT sampler_count, ID3D11SamplerState *const *samplers)
 {
-    FIXME("iface %p, start_slot %u, sampler_count %u, samplers %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+
+    TRACE("iface %p, start_slot %u, sampler_count %u, samplers %p.\n",
             iface, start_slot, sampler_count, samplers);
+
+    add_deferred_set_samplers(context, DEFERRED_PSSETSAMPLERS, start_slot, sampler_count, samplers);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_VSSetShader(ID3D11DeviceContext *iface,
         ID3D11VertexShader *shader, ID3D11ClassInstance *const *class_instances, UINT class_instance_count)
 {
-    FIXME("iface %p, shader %p, class_instances %p, class_instance_count %u stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, shader %p, class_instances %p, class_instance_count %u.\n",
             iface, shader, class_instances, class_instance_count);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_VSSETSHADER;
+    if (shader) ID3D11VertexShader_AddRef(shader);
+    call->vs_info.shader = shader;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_DrawIndexed(ID3D11DeviceContext *iface,
         UINT index_count, UINT start_index_location, INT base_vertex_location)
 {
-    FIXME("iface %p, index_count %u, start_index_location %u, base_vertex_location %d stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, index_count %u, start_index_location %u, base_vertex_location %d.\n",
             iface, index_count, start_index_location, base_vertex_location);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_DRAWINDEXED;
+    call->draw_indexed_info.count = index_count;
+    call->draw_indexed_info.start_index = start_index_location;
+    call->draw_indexed_info.base_vertex = base_vertex_location;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_Draw(ID3D11DeviceContext *iface,
@@ -3038,53 +3788,169 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_Draw(ID3D11DeviceContext *i
 static HRESULT STDMETHODCALLTYPE d3d11_deferred_context_Map(ID3D11DeviceContext *iface, ID3D11Resource *resource,
         UINT subresource_idx, D3D11_MAP map_type, UINT map_flags, D3D11_MAPPED_SUBRESOURCE *mapped_subresource)
 {
-    FIXME("iface %p, resource %p, subresource_idx %u, map_type %u, map_flags %#x, mapped_subresource %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct wined3d_resource *wined3d_resource;
+    struct wined3d_map_info map_info;
+    struct deferred_call *call, *previous = NULL;
+    HRESULT hr;
+
+    TRACE("iface %p, resource %p, subresource_idx %u, map_type %u, map_flags %#x, mapped_subresource %p.\n",
             iface, resource, subresource_idx, map_type, map_flags, mapped_subresource);
 
-    return E_NOTIMPL;
+    if (map_type != D3D11_MAP_WRITE_DISCARD && map_type != D3D11_MAP_WRITE_NO_OVERWRITE)
+        FIXME("Map type %u not supported!\n", map_type);
+
+    if (map_type != D3D11_MAP_WRITE_DISCARD)
+    {
+        LIST_FOR_EACH_ENTRY_REV(call, &context->commands, struct deferred_call, entry)
+        {
+            if (call->cmd != DEFERRED_MAP) continue;
+            if (call->map_info.resource != resource) continue;
+            if (call->map_info.subresource_idx != subresource_idx) continue;
+            previous = call;
+            break;
+        }
+        if (!previous)
+        {
+            FIXME("First map in deferred context didn't use D3D11_MAP_WRITE_DISCARD.\n");
+            return E_INVALIDARG;
+        }
+    }
+
+    wined3d_resource = wined3d_resource_from_d3d11_resource(resource);
+
+    wined3d_mutex_lock();
+    hr = wined3d_resource_map_info(wined3d_resource, subresource_idx,
+            &map_info, wined3d_map_flags_from_d3d11_map_type(map_type));
+    wined3d_mutex_unlock();
+
+    if (FAILED(hr))
+        return hr;
+
+    if (!(call = add_deferred_call(context, map_info.size)))
+        return E_OUTOFMEMORY;
+
+    call->cmd = DEFERRED_MAP;
+    ID3D11Resource_AddRef(resource);
+    call->map_info.resource = resource;
+    call->map_info.subresource_idx = subresource_idx;
+    call->map_info.map_type = map_type;
+    call->map_info.map_flags = map_flags;
+    call->map_info.buffer = (void *)(call + 1);
+    call->map_info.size = map_info.size;
+
+    if (previous)
+        memcpy(call->map_info.buffer, previous->map_info.buffer, map_info.size);
+
+    mapped_subresource->pData = call->map_info.buffer;
+    mapped_subresource->RowPitch = map_info.row_pitch;
+    mapped_subresource->DepthPitch = map_info.slice_pitch;
+
+    return S_OK;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_Unmap(ID3D11DeviceContext *iface, ID3D11Resource *resource,
         UINT subresource_idx)
 {
-    FIXME("iface %p, resource %p, subresource_idx %u stub!\n", iface, resource, subresource_idx);
+    TRACE("iface %p, resource %p, subresource_idx %u.\n", iface, resource, subresource_idx);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_PSSetConstantBuffers(ID3D11DeviceContext *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer *const *buffers)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p.\n",
             iface, start_slot, buffer_count, buffers);
+
+    add_deferred_set_constant_buffers(context, DEFERRED_PSSETCONSTANTBUFFERS, start_slot, buffer_count, buffers);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_IASetInputLayout(ID3D11DeviceContext *iface,
         ID3D11InputLayout *input_layout)
 {
-    FIXME("iface %p, input_layout %p stub!\n", iface, input_layout);
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, input_layout %p.\n", iface, input_layout);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_IASETINPUTLAYOUT;
+    if (input_layout) ID3D11InputLayout_AddRef(input_layout);
+    call->input_layout_info.layout = input_layout;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_IASetVertexBuffers(ID3D11DeviceContext *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer *const *buffers, const UINT *strides, const UINT *offsets)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p, strides %p, offsets %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+    int i;
+
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, strides %p, offsets %p.\n",
             iface, start_slot, buffer_count, buffers, strides, offsets);
+
+    if (!(call = add_deferred_call(context, buffer_count * (sizeof(*buffers) + sizeof(UINT) + sizeof(UINT)))))
+        return;
+
+    call->cmd = DEFERRED_IASETVERTEXBUFFERS;
+    call->vbuffer_info.start_slot = start_slot;
+    call->vbuffer_info.num_buffers = buffer_count;
+
+    call->vbuffer_info.buffers = (void *)(call + 1);
+    call->vbuffer_info.strides = (void *)&call->vbuffer_info.buffers[buffer_count];
+    call->vbuffer_info.offsets = (void *)&call->vbuffer_info.strides[buffer_count];
+    for (i = 0; i < buffer_count; i++)
+    {
+        if (buffers[i]) ID3D11Buffer_AddRef(buffers[i]);
+        call->vbuffer_info.buffers[i] = buffers[i];
+        call->vbuffer_info.strides[i] = strides[i];
+        call->vbuffer_info.offsets[i] = offsets[i];
+    }
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_IASetIndexBuffer(ID3D11DeviceContext *iface,
         ID3D11Buffer *buffer, DXGI_FORMAT format, UINT offset)
 {
-    FIXME("iface %p, buffer %p, format %s, offset %u stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, buffer %p, format %s, offset %u.\n",
             iface, buffer, debug_dxgi_format(format), offset);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_IASETINDEXBUFFER;
+    if (buffer) ID3D11Buffer_AddRef(buffer);
+    call->index_buffer_info.buffer = buffer;
+    call->index_buffer_info.format = format;
+    call->index_buffer_info.offset = offset;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_DrawIndexedInstanced(ID3D11DeviceContext *iface,
         UINT instance_index_count, UINT instance_count, UINT start_index_location, INT base_vertex_location,
         UINT start_instance_location)
 {
-    FIXME("iface %p, instance_index_count %u, instance_count %u, start_index_location %u, "
-            "base_vertex_location %d, start_instance_location %u stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, instance_index_count %u, instance_count %u, start_index_location %u, "
+            "base_vertex_location %d, start_instance_location %u.\n",
             iface, instance_index_count, instance_count, start_index_location,
             base_vertex_location, start_instance_location);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_DRAWINDEXEDINSTANCED;
+    call->draw_indexed_inst_info.count_per_instance = instance_index_count;
+    call->draw_indexed_inst_info.instance_count = instance_count;
+    call->draw_indexed_inst_info.start_index = start_index_location;
+    call->draw_indexed_inst_info.base_vertex = base_vertex_location;
+    call->draw_indexed_inst_info.start_instance = start_instance_location;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_DrawInstanced(ID3D11DeviceContext *iface,
@@ -3113,7 +3979,16 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_GSSetShader(ID3D11DeviceCon
 static void STDMETHODCALLTYPE d3d11_deferred_context_IASetPrimitiveTopology(ID3D11DeviceContext *iface,
         D3D11_PRIMITIVE_TOPOLOGY topology)
 {
-    FIXME("iface %p, topology %u stub!\n", iface, topology);
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, topology %u.\n", iface, topology);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_IASETPRIMITIVETOPOLOGY;
+    call->topology_info.topology = topology;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_VSSetShaderResources(ID3D11DeviceContext *iface,
@@ -3173,8 +4048,28 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_OMSetRenderTargets(ID3D11De
         UINT render_target_view_count, ID3D11RenderTargetView *const *render_target_views,
         ID3D11DepthStencilView *depth_stencil_view)
 {
-    FIXME("iface %p, render_target_view_count %u, render_target_views %p, depth_stencil_view %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+    int i;
+
+    TRACE("iface %p, render_target_view_count %u, render_target_views %p, depth_stencil_view %p.\n",
             iface, render_target_view_count, render_target_views, depth_stencil_view);
+
+    if (!(call = add_deferred_call(context, sizeof(*render_target_views) * render_target_view_count)))
+        return;
+
+    call->cmd = DEFERRED_OMSETRENDERTARGETS;
+    call->render_target_info.num_views = render_target_view_count;
+    call->render_target_info.render_targets = (void *)(call + 1);
+    for (i = 0; i < render_target_view_count; i++)
+    {
+        if (render_target_views[i])
+            ID3D11RenderTargetView_AddRef(render_target_views[i]);
+        call->render_target_info.render_targets[i] = render_target_views[i];
+    }
+    if (depth_stencil_view)
+        ID3D11DepthStencilView_AddRef(depth_stencil_view);
+    call->render_target_info.depth_stencil = depth_stencil_view;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_OMSetRenderTargetsAndUnorderedAccessViews(
@@ -3194,15 +4089,44 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_OMSetRenderTargetsAndUnorde
 static void STDMETHODCALLTYPE d3d11_deferred_context_OMSetBlendState(ID3D11DeviceContext *iface,
         ID3D11BlendState *blend_state, const float blend_factor[4], UINT sample_mask)
 {
-    FIXME("iface %p, blend_state %p, blend_factor %s, sample_mask 0x%08x stub!\n",
+    static const float default_blend_factor[] = {1.0f, 1.0f, 1.0f, 1.0f};
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+    int i;
+
+    TRACE("iface %p, blend_state %p, blend_factor %s, sample_mask 0x%08x.\n",
             iface, blend_state, debug_float4(blend_factor), sample_mask);
+
+    if (!blend_factor)
+        blend_factor = default_blend_factor;
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_OMSETBLENDSTATE;
+    if (blend_state) ID3D11BlendState_AddRef(blend_state);
+    call->blend_state_info.state = blend_state;
+    for (i = 0; i < 4; i++)
+        call->blend_state_info.factor[i] = blend_factor[i];
+    call->blend_state_info.mask = sample_mask;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_OMSetDepthStencilState(ID3D11DeviceContext *iface,
         ID3D11DepthStencilState *depth_stencil_state, UINT stencil_ref)
 {
-    FIXME("iface %p, depth_stencil_state %p, stencil_ref %u stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, depth_stencil_state %p, stencil_ref %u.\n",
             iface, depth_stencil_state, stencil_ref);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_OMSETDEPTHSTENCILSTATE;
+    if (depth_stencil_state) ID3D11DepthStencilState_AddRef(depth_stencil_state);
+    call->stencil_state_info.state = depth_stencil_state;
+    call->stencil_state_info.stencil_ref = stencil_ref;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_SOSetTargets(ID3D11DeviceContext *iface, UINT buffer_count,
@@ -3244,13 +4168,34 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_DispatchIndirect(ID3D11Devi
 static void STDMETHODCALLTYPE d3d11_deferred_context_RSSetState(ID3D11DeviceContext *iface,
         ID3D11RasterizerState *rasterizer_state)
 {
-    FIXME("iface %p, rasterizer_state %p stub!\n", iface, rasterizer_state);
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, rasterizer_state %p.\n", iface, rasterizer_state);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_RSSETSTATE;
+    if (rasterizer_state) ID3D11RasterizerState_AddRef(rasterizer_state);
+    call->rstate_info.state = rasterizer_state;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_RSSetViewports(ID3D11DeviceContext *iface,
         UINT viewport_count, const D3D11_VIEWPORT *viewports)
 {
-    FIXME("iface %p, viewport_count %u, viewports %p stub!\n", iface, viewport_count, viewports);
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, viewport_count %u, viewports %p.\n", iface, viewport_count, viewports);
+
+    if (!(call = add_deferred_call(context, sizeof(D3D11_VIEWPORT) * viewport_count)))
+        return;
+
+    call->cmd = DEFERRED_RSSETVIEWPORTS;
+    call->viewport_info.num_viewports = viewport_count;
+    call->viewport_info.viewports = (void *)(call + 1);
+    memcpy(call->viewport_info.viewports, viewports, sizeof(D3D11_VIEWPORT) * viewport_count);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_RSSetScissorRects(ID3D11DeviceContext *iface,
@@ -3365,8 +4310,18 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_HSSetShaderResources(ID3D11
 static void STDMETHODCALLTYPE d3d11_deferred_context_HSSetShader(ID3D11DeviceContext *iface,
         ID3D11HullShader *shader, ID3D11ClassInstance *const *class_instances, UINT class_instance_count)
 {
-    FIXME("iface %p, shader %p, class_instances %p, class_instance_count %u stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, shader %p, class_instances %p, class_instance_count %u.\n",
             iface, shader, class_instances, class_instance_count);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_HSSETSHADER;
+    if (shader) ID3D11HullShader_AddRef(shader);
+    call->hs_info.shader = shader;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_HSSetSamplers(ID3D11DeviceContext *iface,
@@ -3379,36 +4334,62 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_HSSetSamplers(ID3D11DeviceC
 static void STDMETHODCALLTYPE d3d11_deferred_context_HSSetConstantBuffers(ID3D11DeviceContext *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer *const *buffers)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p.\n",
             iface, start_slot, buffer_count, buffers);
+
+    add_deferred_set_constant_buffers(context, DEFERRED_HSSETCONSTANTBUFFERS, start_slot, buffer_count, buffers);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_DSSetShaderResources(ID3D11DeviceContext *iface,
         UINT start_slot, UINT view_count, ID3D11ShaderResourceView *const *views)
 {
-    FIXME("iface %p, start_slot %u, view_count %u, views %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+
+    TRACE("iface %p, start_slot %u, view_count %u, views %p.\n",
             iface, start_slot, view_count, views);
+
+    add_deferred_set_shader_resources(context, DEFERRED_DSSETSHADERRESOURCES, start_slot, view_count, views);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_DSSetShader(ID3D11DeviceContext *iface,
         ID3D11DomainShader *shader, ID3D11ClassInstance *const *class_instances, UINT class_instance_count)
 {
-    FIXME("iface %p, shader %p, class_instances %p, class_instance_count %u stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p, shader %p, class_instances %p, class_instance_count %u.\n",
             iface, shader, class_instances, class_instance_count);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_DSSETSHADER;
+    if (shader) ID3D11DomainShader_AddRef(shader);
+    call->ds_info.shader = shader;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_DSSetSamplers(ID3D11DeviceContext *iface,
         UINT start_slot, UINT sampler_count, ID3D11SamplerState *const *samplers)
 {
-    FIXME("iface %p, start_slot %u, sampler_count %u, samplers %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+
+    TRACE("iface %p, start_slot %u, sampler_count %u, samplers %p.\n",
             iface, start_slot, sampler_count, samplers);
+
+    add_deferred_set_samplers(context, DEFERRED_DSSETSAMPLERS, start_slot, sampler_count, samplers);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_DSSetConstantBuffers(ID3D11DeviceContext *iface,
         UINT start_slot, UINT buffer_count, ID3D11Buffer *const *buffers)
 {
-    FIXME("iface %p, start_slot %u, buffer_count %u, buffers %p stub!\n",
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+
+    TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p.\n",
             iface, start_slot, buffer_count, buffers);
+
+    add_deferred_set_constant_buffers(context, DEFERRED_DSSETCONSTANTBUFFERS, start_slot, buffer_count, buffers);
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_CSSetShaderResources(ID3D11DeviceContext *iface,
@@ -3709,7 +4690,15 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_CSGetConstantBuffers(ID3D11
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_ClearState(ID3D11DeviceContext *iface)
 {
-    FIXME("iface %p stub!\n", iface);
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+
+    TRACE("iface %p.\n", iface);
+
+    if (!(call = add_deferred_call(context, 0)))
+        return;
+
+    call->cmd = DEFERRED_CLEARSTATE;
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_Flush(ID3D11DeviceContext *iface)
@@ -3734,9 +4723,29 @@ static UINT STDMETHODCALLTYPE d3d11_deferred_context_GetContextFlags(ID3D11Devic
 static HRESULT STDMETHODCALLTYPE d3d11_deferred_context_FinishCommandList(ID3D11DeviceContext *iface,
         BOOL restore, ID3D11CommandList **command_list)
 {
-    FIXME("iface %p, restore %#x, command_list %p stub!\n", iface, restore, command_list);
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct d3d11_command_list *object;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, restore %#x, command_list %p.\n", iface, restore, command_list);
+
+    if (restore)
+        FIXME("Restoring state is not supported\n");
+
+    if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
+        return E_OUTOFMEMORY;
+
+    object->ID3D11CommandList_iface.lpVtbl = &d3d11_command_list_vtbl;
+    object->device = context->device;
+    object->refcount = 1;
+
+    list_init(&object->commands);
+    list_move_tail(&object->commands, &context->commands);
+
+    ID3D11Device_AddRef(context->device);
+    wined3d_private_store_init(&object->private_store);
+
+    *command_list = &object->ID3D11CommandList_iface;
+    return S_OK;
 }
 
 static const struct ID3D11DeviceContextVtbl d3d11_deferred_context_vtbl =
@@ -4351,6 +5360,8 @@ static HRESULT STDMETHODCALLTYPE d3d11_device_CreateDeferredContext(ID3D11Device
     object->device = (ID3D11Device *)iface;
     object->refcount = 1;
 
+    list_init(&object->commands);
+
     ID3D11Device2_AddRef(iface);
     wined3d_private_store_init(&object->private_store);
 
-- 
2.21.0

