Module: vkd3d
Branch: master
Commit: 98624f2e8fdfa9e86218e1738f72a989503ef7f7
URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/98624f2e8fdfa9e86218e1738f72a…
Author: Zebediah Figura <zfigura(a)codeweavers.com>
Date: Wed Feb 22 17:41:12 2023 -0600
include: Document that vkd3d_shader_signature may contain pointers into the input shader blob.
---
include/vkd3d_shader.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/include/vkd3d_shader.h b/include/vkd3d_shader.h
index ee8ce8d0..bf5e1387 100644
--- a/include/vkd3d_shader.h
+++ b/include/vkd3d_shader.h
@@ -1839,6 +1839,9 @@ VKD3D_SHADER_API void vkd3d_shader_free_scan_descriptor_info(
* Members of \a signature may be allocated by vkd3d-shader. The signature
* should be freed with vkd3d_shader_free_shader_signature() when no longer
* needed.
+ * \n
+ * The signature may contain pointers into the input shader, and should only be
+ * accessed while the input shader remains valid.
*
* \param messages Optional output location for error or informational messages
* produced by the parser.
Module: vkd3d
Branch: master
Commit: bb2fa97c33fd1591097741b809854763c0623697
URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/bb2fa97c33fd1591097741b809854…
Author: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Date: Thu Feb 9 12:16:34 2023 +0100
vkd3d: Do not keep the CS queue locked while processing it.
d3d12_command_queue_flush_ops() can renter itself while processing signal
events. Since we don't use recursive mutexes, we currently have to check
some of the queue variables without holding the mutex, which is not safe.
This is solved by allowing the queue to release its mutex while it is
processing entries: when flushing, the queue is briefly locked, the
is_flushing flag is set, the queue content is copied away and the
queue is unlocked again. After having processed the entries, the
queue is locked again to check is something else was added in the
meantime. This is repeated until the queue is empty (or a wait operation
is blocking it).
This should also remove some latency when a thread pushes to the queue
while another one is processing it, but I didn't try to measure any
impact. While it is expected that with this patch the queue mutex
will be locked and unlocked more frequently, it should also remain
locked for less time, hopefully creating little contention.
---
libs/vkd3d/command.c | 170 +++++++++++++++++++++++++++++++--------------
libs/vkd3d/vkd3d_private.h | 18 ++++-
2 files changed, 134 insertions(+), 54 deletions(-)
Module: vkd3d
Branch: master
Commit: 09d2c8d1909aac06091403a6691c0037de10b698
URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/09d2c8d1909aac06091403a6691c0…
Author: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Date: Thu Mar 2 12:11:55 2023 +0100
vkd3d: Always enqueue wait operations, even when they can be executed right away.
---
libs/vkd3d/command.c | 24 +-----------------------
1 file changed, 1 insertion(+), 23 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 5d8eb3e9..2ee1e8d5 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -6611,23 +6611,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *if
TRACE("iface %p, fence %p, value %#"PRIx64".\n", iface, fence_iface, value);
vkd3d_mutex_lock(&command_queue->op_mutex);
- vkd3d_mutex_lock(&fence->mutex);
-
- if (!command_queue->ops_count && value <= fence->max_pending_value)
- {
- hr = d3d12_command_queue_wait_locked(command_queue, fence, value);
- goto done;
- }
-
- /* This is the critical part required to support out-of-order signal.
- * Normally we would be able to submit waits and signals out of order, but
- * we don't have virtualized queues in Vulkan, so we need to handle the case
- * where multiple queues alias over the same physical queue, so effectively,
- * we need to manage out-of-order submits ourselves. */
if (!(op = d3d12_command_queue_require_space_locked(command_queue)))
{
- vkd3d_mutex_unlock(&fence->mutex);
hr = E_OUTOFMEMORY;
goto done;
}
@@ -6637,15 +6623,7 @@ 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_command_queue_record_as_blocked(command_queue);
-
- /* The fence must remain locked until the op is created and the queue is added to the blocked list,
- * because if an unblocking d3d12_fence_Signal() call occurs on another thread before the above
- * work is done, flushing will be delayed until the next signal, if one occurs at all. */
- vkd3d_mutex_unlock(&fence->mutex);
+ d3d12_command_queue_submit_locked(command_queue);
done:
vkd3d_mutex_unlock(&command_queue->op_mutex);
Module: vkd3d
Branch: master
Commit: 0c6df4956093cf16c8b40cb1e2c83e9e2585f63a
URL: https://gitlab.winehq.org/wine/vkd3d/-/commit/0c6df4956093cf16c8b40cb1e2c83…
Author: Giovanni Mascellani <gmascellani(a)codeweavers.com>
Date: Wed Feb 8 15:23:56 2023 +0100
vkd3d: Hold the queue mutex when adding the queue to a blocked list.
Otherwise it could be added more than once.
Note that the deleted comment is wrong: between when d3d12_command_queue_flush_ops()
returns and when the queue is added back to the blocked list, the queue
might have been pushed to and flushed an arbitrary number of times.
---
libs/vkd3d/command.c | 60 ++++++++++++++++++++++++----------------------------
1 file changed, 28 insertions(+), 32 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 2d3007cf..772649cd 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -26,7 +26,7 @@ static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkF
static void d3d12_fence_signal_timeline_semaphore(struct d3d12_fence *fence, uint64_t timeline_value);
static HRESULT d3d12_command_queue_signal(struct d3d12_command_queue *command_queue,
struct d3d12_fence *fence, uint64_t value);
-static bool d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, bool *flushed_any);
+static HRESULT d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, bool *flushed_any);
HRESULT vkd3d_queue_create(struct d3d12_device *device,
uint32_t family_index, const VkQueueFamilyProperties *properties, struct vkd3d_queue **queue)
@@ -636,27 +636,23 @@ static HRESULT d3d12_fence_update_pending_value(struct d3d12_fence *fence)
return S_OK;
}
-static HRESULT d3d12_device_add_blocked_command_queues(struct d3d12_device *device,
- struct d3d12_command_queue * const *command_queues, unsigned int count)
+static HRESULT d3d12_command_queue_record_as_blocked(struct d3d12_command_queue *command_queue)
{
+ struct d3d12_device *device = command_queue->device;
HRESULT hr = S_OK;
- unsigned int i;
-
- if (count == 0)
- return S_OK;
vkd3d_mutex_lock(&device->blocked_queues_mutex);
- if ((i = ARRAY_SIZE(device->blocked_queues) - device->blocked_queue_count) < count)
+ if (device->blocked_queue_count < ARRAY_SIZE(device->blocked_queues))
{
- FIXME("Failed to add %u blocked command queue(s) to device %p.\n", count - i, device);
- count = i;
+ device->blocked_queues[device->blocked_queue_count++] = command_queue;
+ }
+ else
+ {
+ WARN("Failed to add blocked command queue %p to device %p.\n", command_queue, device);
hr = E_FAIL;
}
- for (i = 0; i < count; ++i)
- device->blocked_queues[device->blocked_queue_count++] = command_queues[i];
-
vkd3d_mutex_unlock(&device->blocked_queues_mutex);
return hr;
}
@@ -665,6 +661,7 @@ static HRESULT d3d12_device_flush_blocked_queues_once(struct d3d12_device *devic
{
struct d3d12_command_queue *blocked_queues[VKD3D_MAX_DEVICE_BLOCKED_QUEUES];
unsigned int i, blocked_queue_count;
+ HRESULT hr = S_OK;
*flushed_any = false;
@@ -679,18 +676,17 @@ static HRESULT d3d12_device_flush_blocked_queues_once(struct d3d12_device *devic
vkd3d_mutex_unlock(&device->blocked_queues_mutex);
- i = 0;
- while (i < blocked_queue_count)
+ for (i = 0; i < blocked_queue_count; ++i)
{
- if (d3d12_command_queue_flush_ops(blocked_queues[i], flushed_any))
- blocked_queues[i] = blocked_queues[--blocked_queue_count];
- else
- ++i;
+ HRESULT new_hr;
+
+ new_hr = d3d12_command_queue_flush_ops(blocked_queues[i], flushed_any);
+
+ if (SUCCEEDED(hr))
+ hr = new_hr;
}
- /* None of these queues could have been re-added during the above loop because
- * blocked queues always have a nonzero op count. */
- return d3d12_device_add_blocked_command_queues(device, blocked_queues, blocked_queue_count);
+ return hr;
}
static HRESULT d3d12_device_flush_blocked_queues(struct d3d12_device *device)
@@ -6640,7 +6636,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *if
/* 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);
+ hr = d3d12_command_queue_record_as_blocked(command_queue);
/* The fence must remain locked until the op is created and the queue is added to the blocked list,
* because if an unblocking d3d12_fence_Signal() call occurs on another thread before the above
@@ -6774,21 +6770,21 @@ static const struct ID3D12CommandQueueVtbl d3d12_command_queue_vtbl =
};
/* flushed_any is initialised by the caller. */
-static bool d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, bool *flushed_any)
+static HRESULT d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, bool *flushed_any)
{
struct vkd3d_cs_op_data *op;
struct d3d12_fence *fence;
- bool flushed_all = false;
+ HRESULT hr = S_OK;
unsigned int i;
if (!queue->ops_count)
- return true;
+ return S_OK;
- /* This function may be re-entered during a call below to d3d12_command_queue_signal().
- * We return true because the first caller is responsible for re-adding this queue to
- * the flush list if it ends up returning false. */
+ /* This function may be re-entered when invoking
+ * d3d12_command_queue_signal(). The first call is responsible
+ * for re-adding the queue to the flush list. */
if (queue->is_flushing)
- return true;
+ return S_OK;
vkd3d_mutex_lock(&queue->op_mutex);
@@ -6808,6 +6804,7 @@ static bool d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, boo
vkd3d_mutex_unlock(&fence->mutex);
queue->ops_count -= i;
memmove(queue->ops, op, queue->ops_count * sizeof(*op));
+ hr = d3d12_command_queue_record_as_blocked(queue);
goto done;
}
d3d12_command_queue_wait_locked(queue, fence, op->u.wait.value);
@@ -6831,13 +6828,12 @@ static bool d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, boo
}
queue->ops_count = 0;
- flushed_all = true;
done:
queue->is_flushing = false;
vkd3d_mutex_unlock(&queue->op_mutex);
- return flushed_all;
+ return hr;
}
static HRESULT d3d12_command_queue_init(struct d3d12_command_queue *queue,