[PATCH v2 4/6] wined3d: Set an array of rendertarget views as a single CS operation.

Zebediah Figura zfigura at codeweavers.com
Thu Jul 8 17:00:57 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 dlls/d3d11/device.c            | 53 ++++++++++--------
 dlls/d3d8/device.c             |  3 +-
 dlls/d3d9/device.c             |  2 +-
 dlls/ddraw/ddraw.c             |  2 +-
 dlls/ddraw/device.c            | 13 +++--
 dlls/ddraw/surface.c           |  7 +--
 dlls/wined3d/cs.c              | 78 +++++++++++++++------------
 dlls/wined3d/device.c          | 99 +++++++++++++++++-----------------
 dlls/wined3d/wined3d.spec      |  2 +-
 dlls/wined3d/wined3d_private.h |  4 +-
 include/wine/wined3d.h         |  4 +-
 11 files changed, 144 insertions(+), 123 deletions(-)

diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c
index 12675826394..fc34421f082 100644
--- a/dlls/d3d11/device.c
+++ b/dlls/d3d11/device.c
@@ -1071,29 +1071,33 @@ static void STDMETHODCALLTYPE d3d11_device_context_GSSetSamplers(ID3D11DeviceCon
 }
 
 static void STDMETHODCALLTYPE d3d11_device_context_OMSetRenderTargets(ID3D11DeviceContext1 *iface,
-        UINT render_target_view_count, ID3D11RenderTargetView *const *render_target_views,
-        ID3D11DepthStencilView *depth_stencil_view)
+        UINT rtv_count, ID3D11RenderTargetView *const *rtvs, ID3D11DepthStencilView *depth_stencil_view)
 {
+    struct wined3d_rendertarget_view *wined3d_rtvs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
     struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface);
     struct d3d_depthstencil_view *dsv;
     unsigned 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);
+    TRACE("iface %p, rtv_count %u, rtvs %p, depth_stencil_view %p.\n", iface, rtv_count, rtvs, depth_stencil_view);
 
-    wined3d_mutex_lock();
-    for (i = 0; i < render_target_view_count; ++i)
+    if (rtv_count > ARRAY_SIZE(wined3d_rtvs))
     {
-        struct d3d_rendertarget_view *rtv = unsafe_impl_from_ID3D11RenderTargetView(render_target_views[i]);
-        wined3d_device_context_set_rendertarget_view(context->wined3d_context, i,
-                rtv ? rtv->wined3d_view : NULL, FALSE);
+        WARN("View count %u exceeds limit.\n", rtv_count);
+        rtv_count = ARRAY_SIZE(wined3d_rtvs);
     }
-    for (; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
+
+    for (i = 0; i < rtv_count; ++i)
     {
-        wined3d_device_context_set_rendertarget_view(context->wined3d_context, i, NULL, FALSE);
+        struct d3d_rendertarget_view *rtv = unsafe_impl_from_ID3D11RenderTargetView(rtvs[i]);
+
+        wined3d_rtvs[i] = rtv ? rtv->wined3d_view : NULL;
     }
 
     dsv = unsafe_impl_from_ID3D11DepthStencilView(depth_stencil_view);
+
+    wined3d_mutex_lock();
+    wined3d_device_context_set_rendertarget_views(context->wined3d_context, 0,
+            ARRAY_SIZE(wined3d_rtvs), wined3d_rtvs, FALSE);
     wined3d_device_context_set_depth_stencil_view(context->wined3d_context, dsv ? dsv->wined3d_view : NULL);
     wined3d_mutex_unlock();
 }
@@ -4873,30 +4877,33 @@ static void STDMETHODCALLTYPE d3d10_device_GSSetSamplers(ID3D10Device1 *iface,
 }
 
 static void STDMETHODCALLTYPE d3d10_device_OMSetRenderTargets(ID3D10Device1 *iface,
-        UINT render_target_view_count, ID3D10RenderTargetView *const *render_target_views,
-        ID3D10DepthStencilView *depth_stencil_view)
+        UINT rtv_count, ID3D10RenderTargetView *const *rtvs, ID3D10DepthStencilView *depth_stencil_view)
 {
+    struct wined3d_rendertarget_view *wined3d_rtvs[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
     struct d3d_device *device = impl_from_ID3D10Device(iface);
     struct d3d_depthstencil_view *dsv;
     unsigned 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);
+    TRACE("iface %p, rtv_count %u, rtvs %p, depth_stencil_view %p.\n", iface, rtv_count, rtvs, depth_stencil_view);
 
-    wined3d_mutex_lock();
-    for (i = 0; i < render_target_view_count; ++i)
+    if (rtv_count > ARRAY_SIZE(wined3d_rtvs))
     {
-        struct d3d_rendertarget_view *rtv = unsafe_impl_from_ID3D10RenderTargetView(render_target_views[i]);
-
-        wined3d_device_context_set_rendertarget_view(device->immediate_context.wined3d_context, i,
-                rtv ? rtv->wined3d_view : NULL, FALSE);
+        WARN("View count %u exceeds limit.\n", rtv_count);
+        rtv_count = ARRAY_SIZE(wined3d_rtvs);
     }
-    for (; i < D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
+
+    for (i = 0; i < rtv_count; ++i)
     {
-        wined3d_device_context_set_rendertarget_view(device->immediate_context.wined3d_context, i, NULL, FALSE);
+        struct d3d_rendertarget_view *rtv = unsafe_impl_from_ID3D10RenderTargetView(rtvs[i]);
+
+        wined3d_rtvs[i] = rtv ? rtv->wined3d_view : NULL;
     }
 
     dsv = unsafe_impl_from_ID3D10DepthStencilView(depth_stencil_view);
+
+    wined3d_mutex_lock();
+    wined3d_device_context_set_rendertarget_views(device->immediate_context.wined3d_context, 0,
+            ARRAY_SIZE(wined3d_rtvs), wined3d_rtvs, FALSE);
     wined3d_device_context_set_depth_stencil_view(device->immediate_context.wined3d_context,
             dsv ? dsv->wined3d_view : NULL);
     wined3d_mutex_unlock();
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c
index c0fa38e090a..6c1646a1893 100644
--- a/dlls/d3d8/device.c
+++ b/dlls/d3d8/device.c
@@ -1544,7 +1544,8 @@ static HRESULT WINAPI d3d8_device_SetRenderTarget(IDirect3DDevice8 *iface,
         rtv = render_target ? d3d8_surface_acquire_rendertarget_view(rt_impl) : NULL;
         if (render_target)
         {
-            if (SUCCEEDED(hr = wined3d_device_context_set_rendertarget_view(device->immediate_context, 0, rtv, TRUE)))
+            if (SUCCEEDED(hr = wined3d_device_context_set_rendertarget_views(device->immediate_context,
+                    0, 1, &rtv, TRUE)))
                 device_reset_viewport_state(device);
             else
                 wined3d_device_context_set_depth_stencil_view(device->immediate_context, original_dsv);
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c
index c8b906a981f..1a1bc5ddb6c 100644
--- a/dlls/d3d9/device.c
+++ b/dlls/d3d9/device.c
@@ -2028,7 +2028,7 @@ static HRESULT WINAPI d3d9_device_SetRenderTarget(IDirect3DDevice9Ex *iface, DWO
 
     wined3d_mutex_lock();
     rtv = surface_impl ? d3d9_surface_acquire_rendertarget_view(surface_impl) : NULL;
-    hr = wined3d_device_context_set_rendertarget_view(device->immediate_context, idx, rtv, TRUE);
+    hr = wined3d_device_context_set_rendertarget_views(device->immediate_context, idx, 1, &rtv, TRUE);
     d3d9_surface_release_rendertarget_view(surface_impl, rtv);
     if (SUCCEEDED(hr))
     {
diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c
index 972c18fbfe9..5b70bb4f86d 100644
--- a/dlls/ddraw/ddraw.c
+++ b/dlls/ddraw/ddraw.c
@@ -958,7 +958,7 @@ static HRESULT ddraw_set_cooperative_level(struct ddraw *ddraw, HWND window,
 
         if (rtv)
         {
-            wined3d_device_context_set_rendertarget_view(ddraw->immediate_context, 0, rtv, FALSE);
+            wined3d_device_context_set_rendertarget_views(ddraw->immediate_context, 0, 1, &rtv, FALSE);
             wined3d_rendertarget_view_decref(rtv);
         }
 
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c
index b66ae7698c8..8afbab0e58d 100644
--- a/dlls/ddraw/device.c
+++ b/dlls/ddraw/device.c
@@ -270,6 +270,7 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
      * wined3d device when the render target is released. */
     if (!ref)
     {
+        static struct wined3d_rendertarget_view *const null_rtv;
         DWORD i;
         struct list *vp_entry, *vp_entry2;
 
@@ -283,7 +284,7 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
         if (This->vertex_buffer)
             wined3d_buffer_decref(This->vertex_buffer);
 
-        wined3d_device_context_set_rendertarget_view(This->immediate_context, 0, NULL, FALSE);
+        wined3d_device_context_set_rendertarget_views(This->immediate_context, 0, 1, &null_rtv, FALSE);
 
         wined3d_stateblock_decref(This->state);
         if (This->recording)
@@ -1848,6 +1849,7 @@ static BOOL validate_surface_palette(struct ddraw_surface *surface)
 static HRESULT d3d_device_set_render_target(struct d3d_device *device,
         struct ddraw_surface *target, IUnknown *rt_iface)
 {
+    struct wined3d_rendertarget_view *rtv;
     HRESULT hr;
 
     if (device->rt_iface == rt_iface)
@@ -1861,8 +1863,8 @@ static HRESULT d3d_device_set_render_target(struct d3d_device *device,
         return DDERR_INVALIDPARAMS;
     }
 
-    if (FAILED(hr = wined3d_device_context_set_rendertarget_view(device->immediate_context,
-            0, ddraw_surface_get_rendertarget_view(target), FALSE)))
+    rtv = ddraw_surface_get_rendertarget_view(target);
+    if (FAILED(hr = wined3d_device_context_set_rendertarget_views(device->immediate_context, 0, 1, &rtv, FALSE)))
         return hr;
 
     IUnknown_AddRef(rt_iface);
@@ -6994,6 +6996,7 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, c
         0.0f, 0.0f, 1.0f, 0.0f,
         0.0f, 0.0f, 0.0f, 1.0f,
     };
+    struct wined3d_rendertarget_view *rtv;
     HRESULT hr;
 
     if (ddraw->cooperative_level & DDSCL_FPUPRESERVE)
@@ -7043,8 +7046,8 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, c
     wined3d_stateblock_incref(ddraw->state);
 
     /* Render to the back buffer */
-    if (FAILED(hr = wined3d_device_context_set_rendertarget_view(device->immediate_context,
-            0, ddraw_surface_get_rendertarget_view(target), TRUE)))
+    rtv = ddraw_surface_get_rendertarget_view(target);
+    if (FAILED(hr = wined3d_device_context_set_rendertarget_views(device->immediate_context, 0, 1, &rtv, TRUE)))
     {
         ERR("Failed to set render target, hr %#x.\n", hr);
         wined3d_stateblock_decref(device->state);
diff --git a/dlls/ddraw/surface.c b/dlls/ddraw/surface.c
index 7834d9c943b..25aa2be41bb 100644
--- a/dlls/ddraw/surface.c
+++ b/dlls/ddraw/surface.c
@@ -1369,7 +1369,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *
 
         src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
         if (rtv == dst_impl->wined3d_rtv)
-            wined3d_device_context_set_rendertarget_view(dst_impl->ddraw->immediate_context, 0, src_rtv, FALSE);
+            wined3d_device_context_set_rendertarget_views(dst_impl->ddraw->immediate_context, 0, 1, &src_rtv, FALSE);
         wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
         dst_impl->wined3d_rtv = src_rtv;
         wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl);
@@ -1406,7 +1406,8 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *
             src_impl = impl_from_IDirectDrawSurface(current);
             src_rtv = ddraw_surface_get_rendertarget_view(src_impl);
             if (rtv == dst_impl->wined3d_rtv)
-                wined3d_device_context_set_rendertarget_view(dst_impl->ddraw->immediate_context, 0, src_rtv, FALSE);
+                wined3d_device_context_set_rendertarget_views(dst_impl->ddraw->immediate_context,
+                        0, 1, &src_rtv, FALSE);
             wined3d_rendertarget_view_set_parent(src_rtv, dst_impl);
             dst_impl->wined3d_rtv = src_rtv;
             wined3d_texture_set_sub_resource_parent(src_impl->wined3d_texture, 0, dst_impl);
@@ -1429,7 +1430,7 @@ static HRESULT WINAPI DECLSPEC_HOTPATCH ddraw_surface1_Flip(IDirectDrawSurface *
     /* We don't have to worry about potential texture bindings, since
      * flippable surfaces can never be textures. */
     if (rtv == src_impl->wined3d_rtv)
-        wined3d_device_context_set_rendertarget_view(dst_impl->ddraw->immediate_context, 0, tmp_rtv, FALSE);
+        wined3d_device_context_set_rendertarget_views(dst_impl->ddraw->immediate_context, 0, 1, &tmp_rtv, FALSE);
     wined3d_rendertarget_view_set_parent(tmp_rtv, src_impl);
     src_impl->wined3d_rtv = tmp_rtv;
     wined3d_texture_set_sub_resource_parent(texture, 0, src_impl);
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index c2ba4010704..434a9c20fb1 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -113,7 +113,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_SET_PREDICATION,
     WINED3D_CS_OP_SET_VIEWPORTS,
     WINED3D_CS_OP_SET_SCISSOR_RECTS,
-    WINED3D_CS_OP_SET_RENDERTARGET_VIEW,
+    WINED3D_CS_OP_SET_RENDERTARGET_VIEWS,
     WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW,
     WINED3D_CS_OP_SET_VERTEX_DECLARATION,
     WINED3D_CS_OP_SET_STREAM_SOURCES,
@@ -232,11 +232,12 @@ struct wined3d_cs_set_scissor_rects
     RECT rects[1];
 };
 
-struct wined3d_cs_set_rendertarget_view
+struct wined3d_cs_set_rendertarget_views
 {
     enum wined3d_cs_op opcode;
-    unsigned int view_idx;
-    struct wined3d_rendertarget_view *view;
+    unsigned int start_idx;
+    unsigned int count;
+    struct wined3d_rendertarget_view *views[1];
 };
 
 struct wined3d_cs_set_depth_stencil_view
@@ -586,7 +587,7 @@ static const char *debug_cs_op(enum wined3d_cs_op op)
         WINED3D_TO_STR(WINED3D_CS_OP_SET_PREDICATION);
         WINED3D_TO_STR(WINED3D_CS_OP_SET_VIEWPORTS);
         WINED3D_TO_STR(WINED3D_CS_OP_SET_SCISSOR_RECTS);
-        WINED3D_TO_STR(WINED3D_CS_OP_SET_RENDERTARGET_VIEW);
+        WINED3D_TO_STR(WINED3D_CS_OP_SET_RENDERTARGET_VIEWS);
         WINED3D_TO_STR(WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW);
         WINED3D_TO_STR(WINED3D_CS_OP_SET_VERTEX_DECLARATION);
         WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_SOURCES);
@@ -1289,43 +1290,50 @@ void wined3d_device_context_emit_set_scissor_rects(struct wined3d_device_context
     wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT);
 }
 
-static void wined3d_cs_exec_set_rendertarget_view(struct wined3d_cs *cs, const void *data)
+static void wined3d_cs_exec_set_rendertarget_views(struct wined3d_cs *cs, const void *data)
 {
-    const struct wined3d_cs_set_rendertarget_view *op = data;
-    bool prev_alpha_swizzle, curr_alpha_swizzle;
-    struct wined3d_rendertarget_view *prev;
-    bool prev_srgb_write, curr_srgb_write;
-    struct wined3d_device *device;
+    const struct wined3d_cs_set_rendertarget_views *op = data;
+    struct wined3d_device *device = cs->c.device;
+    unsigned int i;
 
-    device = cs->c.device;
-    prev = cs->state.fb.render_targets[op->view_idx];
-    cs->state.fb.render_targets[op->view_idx] = op->view;
-    device_invalidate_state(device, STATE_FRAMEBUFFER);
-
-    prev_alpha_swizzle = prev && prev->format->id == WINED3DFMT_A8_UNORM;
-    curr_alpha_swizzle = op->view && op->view->format->id == WINED3DFMT_A8_UNORM;
-    if (prev_alpha_swizzle != curr_alpha_swizzle)
-        device_invalidate_state(device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
-
-    if (!(device->adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
-            || cs->state.render_states[WINED3D_RS_SRGBWRITEENABLE])
+    for (i = 0; i < op->count; ++i)
     {
-        prev_srgb_write = prev && prev->format_flags & WINED3DFMT_FLAG_SRGB_WRITE;
-        curr_srgb_write = op->view && op->view->format_flags & WINED3DFMT_FLAG_SRGB_WRITE;
-        if (prev_srgb_write != curr_srgb_write)
-            device_invalidate_state(device, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE));
+        struct wined3d_rendertarget_view *prev = cs->state.fb.render_targets[op->start_idx + i];
+        struct wined3d_rendertarget_view *view = op->views[i];
+        bool prev_alpha_swizzle, curr_alpha_swizzle;
+        bool prev_srgb_write, curr_srgb_write;
+
+        cs->state.fb.render_targets[op->start_idx + i] = view;
+
+        prev_alpha_swizzle = prev && prev->format->id == WINED3DFMT_A8_UNORM;
+        curr_alpha_swizzle = view && view->format->id == WINED3DFMT_A8_UNORM;
+        if (prev_alpha_swizzle != curr_alpha_swizzle)
+            device_invalidate_state(device, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL));
+
+        if (!(device->adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL)
+                || cs->state.render_states[WINED3D_RS_SRGBWRITEENABLE])
+        {
+            prev_srgb_write = prev && prev->format_flags & WINED3DFMT_FLAG_SRGB_WRITE;
+            curr_srgb_write = view && view->format_flags & WINED3DFMT_FLAG_SRGB_WRITE;
+            if (prev_srgb_write != curr_srgb_write)
+                device_invalidate_state(device, STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE));
+        }
     }
+
+    device_invalidate_state(device, STATE_FRAMEBUFFER);
 }
 
-void wined3d_device_context_emit_set_rendertarget_view(struct wined3d_device_context *context, unsigned int view_idx,
-        struct wined3d_rendertarget_view *view)
+void wined3d_device_context_emit_set_rendertarget_views(struct wined3d_device_context *context,
+        unsigned int start_idx, unsigned int count, struct wined3d_rendertarget_view *const *views)
 {
-    struct wined3d_cs_set_rendertarget_view *op;
+    struct wined3d_cs_set_rendertarget_views *op;
 
-    op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT);
-    op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEW;
-    op->view_idx = view_idx;
-    op->view = view;
+    op = wined3d_device_context_require_space(context,
+            offsetof(struct wined3d_cs_set_rendertarget_views, views[count]), WINED3D_CS_QUEUE_DEFAULT);
+    op->opcode = WINED3D_CS_OP_SET_RENDERTARGET_VIEWS;
+    op->start_idx = start_idx;
+    op->count = count;
+    memcpy(op->views, views, count * sizeof(*views));
 
     wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT);
 }
@@ -2884,7 +2892,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_SET_PREDICATION             */ wined3d_cs_exec_set_predication,
     /* WINED3D_CS_OP_SET_VIEWPORTS               */ wined3d_cs_exec_set_viewports,
     /* WINED3D_CS_OP_SET_SCISSOR_RECTS           */ wined3d_cs_exec_set_scissor_rects,
-    /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW       */ wined3d_cs_exec_set_rendertarget_view,
+    /* WINED3D_CS_OP_SET_RENDERTARGET_VIEWS      */ wined3d_cs_exec_set_rendertarget_views,
     /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW      */ wined3d_cs_exec_set_depth_stencil_view,
     /* WINED3D_CS_OP_SET_VERTEX_DECLARATION      */ wined3d_cs_exec_set_vertex_declaration,
     /* WINED3D_CS_OP_SET_STREAM_SOURCES          */ wined3d_cs_exec_set_stream_sources,
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 84bda7b44d9..e4a16e56a56 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -932,16 +932,14 @@ void CDECL wined3d_device_release_focus_window(struct wined3d_device *device)
 
 static void device_init_swapchain_state(struct wined3d_device *device, struct wined3d_swapchain *swapchain)
 {
+    struct wined3d_rendertarget_view *views[WINED3D_MAX_RENDER_TARGETS] = {0};
     BOOL ds_enable = swapchain->state.desc.enable_auto_depth_stencil;
     struct wined3d_device_context *context = &device->cs->c;
-    unsigned int i;
 
-    for (i = 0; i < device->adapter->d3d_info.limits.max_rt_count; ++i)
-    {
-        wined3d_device_context_set_rendertarget_view(context, i, NULL, FALSE);
-    }
     if (device->back_buffer_view)
-        wined3d_device_context_set_rendertarget_view(context, 0, device->back_buffer_view, TRUE);
+        views[0] = device->back_buffer_view;
+    wined3d_device_context_set_rendertarget_views(context, 0,
+            device->adapter->d3d_info.limits.max_rt_count, views, !!device->back_buffer_view);
 
     wined3d_device_context_set_depth_stencil_view(context, ds_enable ? device->auto_depth_stencil_view : NULL);
 }
@@ -1651,10 +1649,8 @@ void CDECL wined3d_device_context_set_state(struct wined3d_device_context *conte
     context->state = state;
     wined3d_device_context_emit_set_feature_level(context, state->feature_level);
 
-    for (i = 0; i < WINED3D_MAX_RENDER_TARGETS; ++i)
-    {
-        wined3d_device_context_emit_set_rendertarget_view(context, i, state->fb.render_targets[i]);
-    }
+    wined3d_device_context_emit_set_rendertarget_views(context, 0,
+            ARRAY_SIZE(state->fb.render_targets), state->fb.render_targets);
 
     wined3d_device_context_emit_set_depth_stencil_view(context, state->fb.depth_stencil);
     wined3d_device_context_emit_set_vertex_declaration(context, state->vertex_declaration);
@@ -2099,70 +2095,77 @@ static void wined3d_device_context_unbind_srv_for_rtv(struct wined3d_device_cont
     }
 }
 
-HRESULT CDECL wined3d_device_context_set_rendertarget_view(struct wined3d_device_context *context,
-        unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport)
+HRESULT CDECL wined3d_device_context_set_rendertarget_views(struct wined3d_device_context *context,
+        unsigned int start_idx, unsigned int count, struct wined3d_rendertarget_view *const *views, BOOL set_viewport)
 {
     struct wined3d_state *state = context->state;
-    struct wined3d_rendertarget_view *prev;
-    unsigned int max_rt_count;
+    unsigned int i, max_rt_count;
+    HRESULT hr = WINED3D_OK;
 
-    TRACE("context %p, view_idx %u, view %p, set_viewport %#x.\n",
-            context, view_idx, view, set_viewport);
+    TRACE("context %p, start_idx %u, count %u, views %p, set_viewport %#x.\n",
+            context, start_idx, count, views, set_viewport);
 
     max_rt_count = context->device->adapter->d3d_info.limits.max_rt_count;
-    if (view_idx >= max_rt_count)
+    if (start_idx >= max_rt_count)
     {
         WARN("Only %u render targets are supported.\n", max_rt_count);
         return WINED3DERR_INVALIDCALL;
     }
-
-    if (view && !(view->resource->bind_flags & WINED3D_BIND_RENDER_TARGET))
-    {
-        WARN("View resource %p doesn't have render target bind flags.\n", view->resource);
-        return WINED3DERR_INVALIDCALL;
-    }
+    count = min(count, max_rt_count - start_idx);
 
     /* Set the viewport and scissor rectangles, if requested. Tests show that
      * stateblock recording is ignored, the change goes directly into the
      * primary stateblock. */
-    if (!view_idx && set_viewport)
+    if (!start_idx && set_viewport)
     {
         state->viewports[0].x = 0;
         state->viewports[0].y = 0;
-        state->viewports[0].width = view->width;
-        state->viewports[0].height = view->height;
+        state->viewports[0].width = views[0]->width;
+        state->viewports[0].height = views[0]->height;
         state->viewports[0].min_z = 0.0f;
         state->viewports[0].max_z = 1.0f;
         state->viewport_count = 1;
         wined3d_device_context_emit_set_viewports(context, 1, state->viewports);
 
-        SetRect(&state->scissor_rects[0], 0, 0, view->width, view->height);
+        SetRect(&state->scissor_rects[0], 0, 0, views[0]->width, views[0]->height);
         state->scissor_rect_count = 1;
         wined3d_device_context_emit_set_scissor_rects(context, 1, state->scissor_rects);
     }
 
-    prev = state->fb.render_targets[view_idx];
-    if (view == prev)
+    if (!memcmp(views, &state->fb.render_targets[start_idx], count * sizeof(*views)))
         return WINED3D_OK;
 
-    if (view)
+    wined3d_device_context_emit_set_rendertarget_views(context, start_idx, count, views);
+    for (i = 0; i < count; ++i)
     {
-        wined3d_rendertarget_view_incref(view);
-        wined3d_rtv_bind_count_inc(view);
-    }
-    state->fb.render_targets[view_idx] = view;
-    wined3d_device_context_emit_set_rendertarget_view(context, view_idx, view);
-    /* Release after the assignment, to prevent device_resource_released()
-     * from seeing the surface as still in use. */
-    if (prev)
-    {
-        wined3d_rtv_bind_count_dec(prev);
-        wined3d_rendertarget_view_decref(prev);
+        struct wined3d_rendertarget_view *prev = state->fb.render_targets[start_idx + i];
+        struct wined3d_rendertarget_view *view = views[i];
+
+        if (view && !(view->resource->bind_flags & WINED3D_BIND_RENDER_TARGET))
+        {
+            WARN("View resource %p doesn't have render target bind flags.\n", views[i]->resource);
+            hr = WINED3DERR_INVALIDCALL;
+            continue;
+        }
+
+        if (view)
+        {
+            wined3d_rendertarget_view_incref(view);
+            wined3d_rtv_bind_count_inc(view);
+        }
+        state->fb.render_targets[start_idx + i] = view;
+        /* Release after the assignment, to prevent device_resource_released()
+         * from seeing the resource as still in use. */
+        if (prev)
+        {
+            wined3d_rtv_bind_count_dec(prev);
+            wined3d_rendertarget_view_decref(prev);
+        }
+
+        wined3d_device_context_unbind_srv_for_rtv(context, view, FALSE);
     }
 
-    wined3d_device_context_unbind_srv_for_rtv(context, view, FALSE);
-
-    return WINED3D_OK;
+    return hr;
 }
 
 HRESULT CDECL wined3d_device_context_set_depth_stencil_view(struct wined3d_device_context *context,
@@ -5187,6 +5190,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         const struct wined3d_swapchain_desc *swapchain_desc, const struct wined3d_display_mode *mode,
         wined3d_device_reset_cb callback, BOOL reset_state)
 {
+    static struct wined3d_rendertarget_view *const views[WINED3D_MAX_RENDER_TARGETS];
     const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
     struct wined3d_device_context *context = &device->cs->c;
     struct wined3d_swapchain_state *swapchain_state;
@@ -5228,10 +5232,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
         state_unbind_resources(state);
     }
 
-    for (i = 0; i < d3d_info->limits.max_rt_count; ++i)
-    {
-        wined3d_device_context_set_rendertarget_view(context, i, NULL, FALSE);
-    }
+    wined3d_device_context_set_rendertarget_views(context, 0, d3d_info->limits.max_rt_count, views, FALSE);
     wined3d_device_context_set_depth_stencil_view(context, NULL);
 
     if (reset_state)
@@ -5454,7 +5455,7 @@ HRESULT CDECL wined3d_device_reset(struct wined3d_device *device,
     else
     {
         if ((view = device->back_buffer_view))
-            wined3d_device_context_set_rendertarget_view(context, 0, view, FALSE);
+            wined3d_device_context_set_rendertarget_views(context, 0, 1, &view, FALSE);
         if ((view = device->auto_depth_stencil_view))
             wined3d_device_context_set_depth_stencil_view(context, view);
     }
diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec
index c6a61b98242..2d36d0882ff 100644
--- a/dlls/wined3d/wined3d.spec
+++ b/dlls/wined3d/wined3d.spec
@@ -130,7 +130,7 @@
 @ cdecl wined3d_device_context_set_predication(ptr ptr long)
 @ cdecl wined3d_device_context_set_primitive_type(ptr long long)
 @ cdecl wined3d_device_context_set_rasterizer_state(ptr ptr)
-@ cdecl wined3d_device_context_set_rendertarget_view(ptr long ptr long)
+@ cdecl wined3d_device_context_set_rendertarget_views(ptr long long ptr long)
 @ cdecl wined3d_device_context_set_samplers(ptr long long long ptr)
 @ cdecl wined3d_device_context_set_scissor_rects(ptr long ptr)
 @ cdecl wined3d_device_context_set_shader(ptr long ptr)
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 19a19dced27..fb25e856ead 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4825,8 +4825,8 @@ void wined3d_device_context_emit_set_rasterizer_state(struct wined3d_device_cont
         struct wined3d_rasterizer_state *rasterizer_state) DECLSPEC_HIDDEN;
 void wined3d_device_context_emit_set_render_state(struct wined3d_device_context *context,
         enum wined3d_render_state state, unsigned int value) DECLSPEC_HIDDEN;
-void wined3d_device_context_emit_set_rendertarget_view(struct wined3d_device_context *context, unsigned int view_idx,
-        struct wined3d_rendertarget_view *view) DECLSPEC_HIDDEN;
+void wined3d_device_context_emit_set_rendertarget_views(struct wined3d_device_context *context, unsigned int start_idx,
+        unsigned int count, struct wined3d_rendertarget_view *const *views) DECLSPEC_HIDDEN;
 void wined3d_device_context_emit_set_samplers(struct wined3d_device_context *context, enum wined3d_shader_type type,
         unsigned int start_idx, unsigned int count, struct wined3d_sampler *const *samplers) DECLSPEC_HIDDEN;
 void wined3d_device_context_emit_set_sampler_state(struct wined3d_device_context *context, unsigned int sampler_idx,
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 6bfc755a5bb..baa71758d17 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -2517,8 +2517,8 @@ void __cdecl wined3d_device_context_set_primitive_type(struct wined3d_device_con
         enum wined3d_primitive_type primitive_topology, unsigned int patch_vertex_count);
 void __cdecl wined3d_device_context_set_rasterizer_state(struct wined3d_device_context *context,
         struct wined3d_rasterizer_state *rasterizer_state);
-HRESULT __cdecl wined3d_device_context_set_rendertarget_view(struct wined3d_device_context *context,
-        unsigned int view_idx, struct wined3d_rendertarget_view *view, BOOL set_viewport);
+HRESULT __cdecl wined3d_device_context_set_rendertarget_views(struct wined3d_device_context *context,
+        unsigned int start_idx, unsigned int count, struct wined3d_rendertarget_view *const *views, BOOL set_viewport);
 void __cdecl wined3d_device_context_set_samplers(struct wined3d_device_context *context, enum wined3d_shader_type type,
         unsigned int start_idx, unsigned int count, struct wined3d_sampler *const *samplers);
 void __cdecl wined3d_device_context_set_scissor_rects(struct wined3d_device_context *context, unsigned int rect_count,
-- 
2.30.2




More information about the wine-devel mailing list