From 3f4e6673dcafcc30a6b6286203fe3a11043c32de Mon Sep 17 00:00:00 2001 From: Jan Sikorski Date: Fri, 15 Oct 2021 14:25:58 +0200 Subject: [PATCH] wined3d: Set render targets and UAVs atomically in wined3d. Signed-off-by: Jan Sikorski Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d3d11/device.c | 42 ++++++++++++++++++++++++++------------- dlls/wined3d/device.c | 31 +++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 1 + include/wine/wined3d.h | 4 ++++ 4 files changed, 64 insertions(+), 14 deletions(-) diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 68b0333604f..31c68f62e68 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -1140,7 +1140,11 @@ static void STDMETHODCALLTYPE d3d11_device_context_OMSetRenderTargetsAndUnordere ID3D11DepthStencilView *depth_stencil_view, UINT uav_start_idx, UINT uav_count, ID3D11UnorderedAccessView *const *uavs, const UINT *initial_counts) { + struct d3d_depthstencil_view *dsv = unsafe_impl_from_ID3D11DepthStencilView(depth_stencil_view); + struct wined3d_rendertarget_view *wined3d_rtvs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0}; + struct wined3d_unordered_access_view *wined3d_uavs[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0}; struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface); + unsigned int wined3d_initial_counts[D3D11_PS_CS_UAV_REGISTER_COUNT]; unsigned int i; TRACE("iface %p, render_target_view_count %u, render_target_views %p, depth_stencil_view %p, " @@ -1148,18 +1152,29 @@ static void STDMETHODCALLTYPE d3d11_device_context_OMSetRenderTargetsAndUnordere iface, render_target_view_count, render_target_views, depth_stencil_view, uav_start_idx, uav_count, uavs, initial_counts); - if (render_target_view_count != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) + if (render_target_view_count == D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) + render_target_view_count = ~0u; + else { - d3d11_device_context_OMSetRenderTargets(iface, render_target_view_count, render_target_views, - depth_stencil_view); + if (render_target_view_count > ARRAY_SIZE(wined3d_rtvs)) + { + WARN("View count %u exceeds limit.\n", render_target_view_count); + render_target_view_count = ARRAY_SIZE(wined3d_rtvs); + } + + for (i = 0; i < render_target_view_count; ++i) + { + struct d3d_rendertarget_view *rtv = unsafe_impl_from_ID3D11RenderTargetView(render_target_views[i]); + + wined3d_rtvs[i] = rtv ? rtv->wined3d_view : NULL; + } } - if (uav_count != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) + if (uav_count == D3D11_KEEP_UNORDERED_ACCESS_VIEWS) + uav_count = ~0u; + else { - struct wined3d_unordered_access_view *wined3d_views[D3D11_PS_CS_UAV_REGISTER_COUNT] = {0}; - unsigned int wined3d_initial_counts[D3D11_PS_CS_UAV_REGISTER_COUNT]; - - if (!wined3d_bound_range(uav_start_idx, uav_count, ARRAY_SIZE(wined3d_views))) + if (!wined3d_bound_range(uav_start_idx, uav_count, ARRAY_SIZE(wined3d_uavs))) { WARN("View count %u exceeds limit; ignoring call.\n", uav_count); return; @@ -1172,15 +1187,14 @@ static void STDMETHODCALLTYPE d3d11_device_context_OMSetRenderTargetsAndUnordere struct d3d11_unordered_access_view *view = unsafe_impl_from_ID3D11UnorderedAccessView(uavs[i]); - wined3d_views[uav_start_idx + i] = view ? view->wined3d_view : NULL; + wined3d_uavs[uav_start_idx + i] = view ? view->wined3d_view : NULL; wined3d_initial_counts[uav_start_idx + i] = initial_counts ? initial_counts[i] : ~0u; } - - wined3d_mutex_lock(); - wined3d_device_context_set_unordered_access_views(context->wined3d_context, WINED3D_PIPELINE_GRAPHICS, - 0, ARRAY_SIZE(wined3d_views), wined3d_views, wined3d_initial_counts); - wined3d_mutex_unlock(); } + + wined3d_device_context_set_render_targets_and_unordered_access_views(context->wined3d_context, ARRAY_SIZE(wined3d_rtvs), + wined3d_rtvs, dsv ? dsv->wined3d_view : NULL, ARRAY_SIZE(wined3d_uavs), wined3d_uavs, + wined3d_initial_counts); } static void STDMETHODCALLTYPE d3d11_device_context_OMSetBlendState(ID3D11DeviceContext1 *iface, diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 6b2f18c6996..86945485e20 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -2110,6 +2110,37 @@ out: wined3d_mutex_unlock(); } +void CDECL wined3d_device_context_set_render_targets_and_unordered_access_views(struct wined3d_device_context *context, + unsigned int rtv_count, struct wined3d_rendertarget_view *const *render_target_views, + struct wined3d_rendertarget_view *depth_stencil_view, UINT uav_count, + struct wined3d_unordered_access_view *const *unordered_access_views, const unsigned int *initial_counts) +{ + wined3d_mutex_lock(); + if (rtv_count != ~0u) + { + if (depth_stencil_view && !(depth_stencil_view->resource->bind_flags & WINED3D_BIND_DEPTH_STENCIL)) + { + WARN("View resource %p has incompatible %s bind flags.\n", + depth_stencil_view->resource, wined3d_debug_bind_flags(depth_stencil_view->resource->bind_flags)); + goto out; + } + + if (FAILED(wined3d_device_context_set_rendertarget_views(context, 0, rtv_count, + render_target_views, FALSE))) + goto out; + + wined3d_device_context_set_depth_stencil_view(context, depth_stencil_view); + } + + if (uav_count != ~0u) + { + wined3d_device_context_set_unordered_access_views(context, WINED3D_PIPELINE_GRAPHICS, 0, uav_count, + unordered_access_views, initial_counts); + } +out: + wined3d_mutex_unlock(); +} + static void wined3d_device_context_unbind_srv_for_rtv(struct wined3d_device_context *context, const struct wined3d_rendertarget_view *view, BOOL dsv) { diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 1bce4def265..48bea5980ff 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -139,6 +139,7 @@ @ cdecl wined3d_device_context_set_stream_outputs(ptr ptr) @ cdecl wined3d_device_context_set_stream_sources(ptr long long ptr) @ cdecl wined3d_device_context_set_unordered_access_views(ptr long long long ptr ptr) +@ cdecl wined3d_device_context_set_render_targets_and_unordered_access_views(ptr long ptr ptr long ptr ptr) @ cdecl wined3d_device_context_set_vertex_declaration(ptr ptr) @ cdecl wined3d_device_context_set_viewports(ptr long ptr) @ cdecl wined3d_device_context_unmap(ptr ptr long) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 7be893b8f21..7a6588ea4f4 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2544,6 +2544,10 @@ HRESULT __cdecl wined3d_device_context_set_stream_sources(struct wined3d_device_ void __cdecl wined3d_device_context_set_unordered_access_views(struct wined3d_device_context *context, enum wined3d_pipeline pipeline, unsigned int start_idx, unsigned int count, struct wined3d_unordered_access_view *const *uavs, const unsigned int *initial_counts); +void __cdecl wined3d_device_context_set_render_targets_and_unordered_access_views(struct wined3d_device_context *context, + unsigned int rtv_count, struct wined3d_rendertarget_view *const *render_target_views, + struct wined3d_rendertarget_view *depth_stencil_view, UINT uav_count, + struct wined3d_unordered_access_view *const *unordered_access_views, const unsigned int *initial_counts); void __cdecl wined3d_device_context_set_vertex_declaration(struct wined3d_device_context *context, struct wined3d_vertex_declaration *declaration); void __cdecl wined3d_device_context_set_viewports(struct wined3d_device_context *context, unsigned int viewport_count,