[PATCH 1/5] wined3d: Use extra bits in the queue head and tail counters.

Stefan Dösinger stefan at codeweavers.com
Wed Mar 9 04:48:29 CST 2022


Signed-off-by: Stefan Dösinger <stefan at codeweavers.com>

---

The next patches will use them for resource fences. We want as many
extra bits as possible to reduce phantom waits due to wrap-arounds, see
the next patch for details.
---
 dlls/wined3d/cs.c              | 28 ++++++++++++++--------------
 dlls/wined3d/wined3d_private.h |  3 ++-
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index ce297d724f2..c4d68fd8f4f 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -624,7 +624,7 @@ static const char *debug_cs_op(enum wined3d_cs_op op)
 
 static struct wined3d_cs_packet *wined3d_next_cs_packet(const uint8_t *data, SIZE_T *offset)
 {
-    struct wined3d_cs_packet *packet = (struct wined3d_cs_packet *)&data[*offset];
+    struct wined3d_cs_packet *packet = (struct wined3d_cs_packet *)&data[WINED3D_CS_QUEUE_MASK(*offset)];
 
     *offset += offsetof(struct wined3d_cs_packet, data[packet->size]);
 
@@ -3263,7 +3263,7 @@ static const struct wined3d_device_context_ops wined3d_cs_st_ops =
 static BOOL wined3d_cs_queue_is_empty(const struct wined3d_cs *cs, const struct wined3d_cs_queue *queue)
 {
     wined3d_from_cs(cs);
-    return *(volatile LONG *)&queue->head == queue->tail;
+    return *(volatile ULONG *)&queue->head == queue->tail;
 }
 
 static void wined3d_cs_queue_submit(struct wined3d_cs_queue *queue, struct wined3d_cs *cs)
@@ -3271,10 +3271,10 @@ static void wined3d_cs_queue_submit(struct wined3d_cs_queue *queue, struct wined
     struct wined3d_cs_packet *packet;
     size_t packet_size;
 
-    packet = (struct wined3d_cs_packet *)&queue->data[queue->head];
+    packet = (struct wined3d_cs_packet *)&queue->data[WINED3D_CS_QUEUE_MASK(queue->head)];
     TRACE("Queuing op %s at %p.\n", debug_cs_op(*(const enum wined3d_cs_op *)packet->data), packet);
     packet_size = FIELD_OFFSET(struct wined3d_cs_packet, data[packet->size]);
-    InterlockedExchange(&queue->head, (queue->head + packet_size) & (WINED3D_CS_QUEUE_SIZE - 1));
+    InterlockedExchange((LONG *)&queue->head, queue->head + packet_size);
 
     if (InterlockedCompareExchange(&cs->waiting_for_event, FALSE, TRUE))
         SetEvent(cs->event);
@@ -3295,6 +3295,7 @@ static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue *queue, size
     size_t queue_size = ARRAY_SIZE(queue->data);
     size_t header_size, packet_size, remaining;
     struct wined3d_cs_packet *packet;
+    ULONG head = WINED3D_CS_QUEUE_MASK(queue->head);
 
     header_size = FIELD_OFFSET(struct wined3d_cs_packet, data[0]);
     packet_size = FIELD_OFFSET(struct wined3d_cs_packet, data[size]);
@@ -3307,7 +3308,7 @@ static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue *queue, size
         return NULL;
     }
 
-    remaining = queue_size - queue->head;
+    remaining = queue_size - head;
     if (remaining < packet_size)
     {
         size_t nop_size = remaining - header_size;
@@ -3321,19 +3322,19 @@ static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue *queue, size
             nop->opcode = WINED3D_CS_OP_NOP;
 
         wined3d_cs_queue_submit(queue, cs);
-        assert(!queue->head);
+        head = WINED3D_CS_QUEUE_MASK(queue->head);
+        assert(!head);
     }
 
     for (;;)
     {
-        LONG tail = *(volatile LONG *)&queue->tail;
-        LONG head = queue->head;
-        LONG new_pos;
+        ULONG tail = WINED3D_CS_QUEUE_MASK(*(volatile ULONG *)&queue->tail);
+        ULONG new_pos;
 
         /* Empty. */
         if (head == tail)
             break;
-        new_pos = (head + packet_size) & (WINED3D_CS_QUEUE_SIZE - 1);
+        new_pos = WINED3D_CS_QUEUE_MASK(head + packet_size);
         /* Head ahead of tail. We checked the remaining size above, so we only
          * need to make sure we don't make head equal to tail. */
         if (head > tail && (new_pos != tail))
@@ -3347,7 +3348,7 @@ static void *wined3d_cs_queue_require_space(struct wined3d_cs_queue *queue, size
                 head, tail, (unsigned long)packet_size);
     }
 
-    packet = (struct wined3d_cs_packet *)&queue->data[queue->head];
+    packet = (struct wined3d_cs_packet *)&queue->data[head];
     packet->size = size;
     return packet->data;
 }
@@ -3370,7 +3371,7 @@ static void wined3d_cs_mt_finish(struct wined3d_device_context *context, enum wi
     if (cs->thread_id == GetCurrentThreadId())
         return wined3d_cs_st_finish(context, queue_id);
 
-    while (cs->queue[queue_id].head != *(volatile LONG *)&cs->queue[queue_id].tail)
+    while (cs->queue[queue_id].head != *(volatile ULONG *)&cs->queue[queue_id].tail)
         YieldProcessor();
 }
 
@@ -3496,8 +3497,7 @@ static DWORD WINAPI wined3d_cs_run(void *ctx)
             TRACE("%s at %p executed.\n", debug_cs_op(opcode), packet);
         }
 
-        tail &= (WINED3D_CS_QUEUE_SIZE - 1);
-        InterlockedExchange(&queue->tail, tail);
+        InterlockedExchange((LONG *)&queue->tail, tail);
     }
 
     cs->queue[WINED3D_CS_QUEUE_MAP].tail = cs->queue[WINED3D_CS_QUEUE_MAP].head;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 58ef6764f2d..895f7a76a26 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4904,10 +4904,11 @@ enum wined3d_push_constants
 #define WINED3D_CS_QUERY_POLL_INTERVAL  10u
 #define WINED3D_CS_QUEUE_SIZE           0x100000u
 #define WINED3D_CS_SPIN_COUNT           10000000u
+#define WINED3D_CS_QUEUE_MASK(a)        ((a) & (WINED3D_CS_QUEUE_SIZE - 1))
 
 struct wined3d_cs_queue
 {
-    LONG head, tail;
+    ULONG head, tail;
     BYTE data[WINED3D_CS_QUEUE_SIZE];
 };
 
-- 
2.34.1




More information about the wine-devel mailing list