Conor McCarthy : vkd3d: Delay adding a command queue to the blocked list until after the op is written.

Alexandre Julliard julliard at winehq.org
Wed Jul 20 15:30:52 CDT 2022


Module: vkd3d
Branch: master
Commit: c1071fda524741682057b7c7992fe81c3f427bef
URL:    https://gitlab.winehq.org/wine/vkd3d/-/commit/c1071fda524741682057b7c7992fe81c3f427bef

Author: Conor McCarthy <cmccarthy at codeweavers.com>
Date:   Mon Jul 18 13:08:00 2022 +1000

vkd3d: Delay adding a command queue to the blocked list until after the op is written.

Otherwise the following sequence can occur:
1. A command queue is added to the blocked list during a Wait() call.
2. An unblocking Signal() occurs on the CPU in another thread, flushing the
   blocked ops, but as no op has been written, the queue is removed from the
   blocked list.
3. The blocked op is written.
3. Another op is queued and the queue is not re-added to the blocked
   list because this only happens for the first op.

World of Warcraft triggers this issue.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 libs/vkd3d/command.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index d0782e5a..eb163848 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -6812,12 +6812,6 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *if
      * where multiple queues alias over the same physical queue, so effectively,
      * we need to manage out-of-order submits ourselves. */
 
-    if (!command_queue->ops_count)
-        hr = d3d12_device_add_blocked_command_queues(command_queue->device, &command_queue, 1);
-
-    if (FAILED(hr))
-        goto done;
-
     if (!(op = d3d12_command_queue_require_space_locked(command_queue)))
     {
         hr = E_OUTOFMEMORY;
@@ -6829,6 +6823,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *if
 
     d3d12_fence_incref(fence);
 
+    /* Add the queue to the blocked list after writing the op to ensure the queue isn't
+     * removed again in another thread because it has no ops. */
+    if (command_queue->ops_count == 1)
+        hr = d3d12_device_add_blocked_command_queues(command_queue->device, &command_queue, 1);
+
 done:
     vkd3d_mutex_unlock(&command_queue->op_mutex);
     return hr;




More information about the wine-cvs mailing list