From 3842fc233f25fb4aa07f142ca2a13a40979560fe Mon Sep 17 00:00:00 2001
From: Johannes Specht <jojos_band@gmx.net>
Date: Mon, 4 Sep 2017 03:07:13 +0200
Subject: [PATCH] d3d11: Implement OMSetRenderTargetsAndUnorderedAccessViews
 for deferred contexts.

---
 dlls/d3d11/device.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 75 insertions(+), 2 deletions(-)

diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index b63f344..96dd4e1 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -40,6 +40,7 @@ enum deferred_cmd
     DEFERRED_OMSETDEPTHSTENCILSTATE,    /* stencil_state_info */
     DEFERRED_OMSETBLENDSTATE,           /* blend_state_info */
     DEFERRED_OMSETRENDERTARGETS,        /* render_target_info */
+    DEFERRED_OMSETRENDERTARGETSANDUNORDEREDACCESVIEWS,  /* render_targets_and_unordered_access_views_info */
 
     DEFERRED_COPYRESOURCE,              /* copy_resource_info */
     DEFERRED_SETRESOURCEMINLOD,         /* set_resource_min_lod_info */
@@ -194,6 +195,16 @@ struct deferred_call
         } copy_structure_count_info;
         struct
         {
+            UINT render_target_view_count;
+            ID3D11RenderTargetView **render_target_views;
+            ID3D11DepthStencilView *depth_stencil_view;
+            UINT unordered_access_view_start_slot;
+            UINT unordered_access_view_count;
+            ID3D11UnorderedAccessView **unordered_access_views;
+            UINT *initial_counts;
+        } render_targets_and_unordered_access_views_info;
+        struct
+        {
             ID3D11ComputeShader *shader;
             /* FIXME: add class instances */
         } cs_info;
@@ -495,6 +506,22 @@ static void free_deferred_calls(struct list *commands)
                     ID3D11DepthStencilView_Release(call->render_target_info.depth_stencil);
                 break;
             }
+            case DEFERRED_OMSETRENDERTARGETSANDUNORDEREDACCESVIEWS:
+            {
+                for (i = 0; i < call->render_targets_and_unordered_access_views_info.render_target_view_count; i++)
+                {
+                    if (call->render_targets_and_unordered_access_views_info.render_target_views[i])
+                        ID3D11RenderTargetView_Release(call->render_targets_and_unordered_access_views_info.render_target_views[i]);
+                }
+                if (call->render_targets_and_unordered_access_views_info.depth_stencil_view)
+                    ID3D11DepthStencilView_Release(call->render_targets_and_unordered_access_views_info.depth_stencil_view);
+                for (i = 0; i < call->render_targets_and_unordered_access_views_info.unordered_access_view_count; i++)
+                {
+                    if (call->render_targets_and_unordered_access_views_info.unordered_access_views[i])
+                        ID3D11UnorderedAccessView_Release(call->render_targets_and_unordered_access_views_info.unordered_access_views[i]);
+                }
+                break;
+            }
             case DEFERRED_COPYRESOURCE:
             {
                 if (call->copy_resource_info.dst_resource)
@@ -764,6 +791,18 @@ static void exec_deferred_calls(ID3D11DeviceContext1 *iface, struct list *comman
                         call->render_target_info.render_targets, call->render_target_info.depth_stencil);
                 break;
             }
+            case DEFERRED_OMSETRENDERTARGETSANDUNORDEREDACCESVIEWS:
+            {
+                ID3D11DeviceContext1_OMSetRenderTargetsAndUnorderedAccessViews(iface,
+                        call->render_targets_and_unordered_access_views_info.render_target_view_count,
+                        call->render_targets_and_unordered_access_views_info.render_target_views,
+                        call->render_targets_and_unordered_access_views_info.depth_stencil_view,
+                        call->render_targets_and_unordered_access_views_info.unordered_access_view_start_slot,
+                        call->render_targets_and_unordered_access_views_info.unordered_access_view_count,
+                        call->render_targets_and_unordered_access_views_info.unordered_access_views,
+                        call->render_targets_and_unordered_access_views_info.initial_counts);
+                break;
+            }
             case DEFERRED_COPYRESOURCE:
             {
                 ID3D11DeviceContext1_CopyResource(iface,
@@ -4623,12 +4662,46 @@ static void STDMETHODCALLTYPE d3d11_deferred_context_OMSetRenderTargetsAndUnorde
         UINT unordered_access_view_start_slot, UINT unordered_access_view_count,
         ID3D11UnorderedAccessView *const *unordered_access_views, const UINT *initial_counts)
 {
-    FIXME("iface %p, render_target_view_count %u, render_target_views %p, depth_stencil_view %p, "
+    struct d3d11_deferred_context *context = impl_from_deferred_ID3D11DeviceContext(iface);
+    struct deferred_call *call;
+    UINT i;
+
+    TRACE("iface %p, render_target_view_count %u, render_target_views %p, depth_stencil_view %p, "
             "unordered_access_view_start_slot %u, unordered_access_view_count %u, unordered_access_views %p, "
-            "initial_counts %p stub!\n",
+            "initial_counts %p.\n",
             iface, render_target_view_count, render_target_views, depth_stencil_view,
             unordered_access_view_start_slot, unordered_access_view_count, unordered_access_views,
             initial_counts);
+
+    if (!(call = add_deferred_call(context, sizeof(ID3D11RenderTargetView *) * render_target_view_count +
+                                   (sizeof(ID3D11UnorderedAccessView *) + sizeof(UINT)) * unordered_access_view_count)))
+        return;
+
+    call->cmd = DEFERRED_OMSETRENDERTARGETSANDUNORDEREDACCESVIEWS;
+    call->render_targets_and_unordered_access_views_info.render_target_view_count = render_target_view_count;
+    call->render_targets_and_unordered_access_views_info.unordered_access_view_start_slot = unordered_access_view_start_slot;
+    call->render_targets_and_unordered_access_views_info.unordered_access_view_count = unordered_access_view_count;
+
+    if (depth_stencil_view) ID3D11DepthStencilView_AddRef(depth_stencil_view);
+    call->render_targets_and_unordered_access_views_info.depth_stencil_view = depth_stencil_view;
+
+    call->render_targets_and_unordered_access_views_info.render_target_views = (void *)(call + 1);
+    call->render_targets_and_unordered_access_views_info.unordered_access_views =
+            (void *)&call->render_targets_and_unordered_access_views_info.render_target_views[render_target_view_count];
+    call->render_targets_and_unordered_access_views_info.initial_counts = initial_counts ?
+            (void *)&call->render_targets_and_unordered_access_views_info.unordered_access_views[unordered_access_view_count] : NULL;
+
+    for (i = 0; i < render_target_view_count; i++)
+    {
+        if (render_target_views[i]) ID3D11RenderTargetView_AddRef(render_target_views[i]);
+        call->render_targets_and_unordered_access_views_info.render_target_views[i] = render_target_views[i];
+    }
+    for (i = 0; i < unordered_access_view_count; i++)
+    {
+        if (unordered_access_views[i]) ID3D11UnorderedAccessView_AddRef(unordered_access_views[i]);
+        call->render_targets_and_unordered_access_views_info.unordered_access_views[i] = unordered_access_views[i];
+        if (initial_counts) call->render_targets_and_unordered_access_views_info.initial_counts[i] = initial_counts[i];
+    }
 }
 
 static void STDMETHODCALLTYPE d3d11_deferred_context_OMSetBlendState(ID3D11DeviceContext *iface,
-- 
1.9.1

