[PATCH 2/2] wined3d: do not call queue_is_empty in wined3d_cs_mt_finish.

Stefan Dösinger stefan at codeweavers.com
Fri Aug 4 03:21:52 CDT 2017


Queue_is_empty assumes it is called from the CS thread because it only
reads queue->head in a cache-safe manner. This breaks on ARM, which has
less strict cache coherency rules than x86.

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

---

Making finish a special case instead of reading both head and tail
through volatile * in queue_is_empty is slightly but measurably faster
on ARM (260 vs 240 fps in a CPU limited test case based on the dx9 sdk).
I did not measure a performance difference on x86.

To reproduce the bug run d3d9 make test on ARM.
---
 dlls/wined3d/cs.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 2c6b572..a1c19ee 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -2346,6 +2346,7 @@ static const struct wined3d_cs_ops wined3d_cs_st_ops =
     wined3d_cs_st_push_constants,
 };
 
+/* This function assumes that it is called from the command stream thread. */
 static BOOL wined3d_cs_queue_is_empty(const struct wined3d_cs_queue *queue)
 {
     return *(volatile LONG *)&queue->head == queue->tail;
@@ -2446,7 +2447,7 @@ static void wined3d_cs_mt_finish(struct wined3d_cs *cs, enum wined3d_cs_queue_id
     if (cs->thread_id == GetCurrentThreadId())
         return wined3d_cs_st_finish(cs, queue_id);
 
-    while (!wined3d_cs_queue_is_empty(&cs->queue[queue_id]))
+    while (cs->queue[queue_id].head != *(volatile LONG *)&cs->queue[queue_id].tail)
         wined3d_pause();
 }
 
-- 
2.10.2




More information about the wine-patches mailing list