Skip to content

Instantly share code, notes, and snippets.

@laino
Last active August 6, 2016 00:35
Show Gist options
  • Save laino/60aa3c024d1f052c77d63481760ad7b2 to your computer and use it in GitHub Desktop.
Save laino/60aa3c024d1f052c77d63481760ad7b2 to your computer and use it in GitHub Desktop.
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 505661d..a099c33 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -642,6 +642,8 @@ void wined3d_cs_emit_present(struct wined3d_cs *cs, struct wined3d_swapchain *sw
unsigned int i;
#if defined(STAGING_CSMT)
LONG pending;
+ LARGE_INTEGER spin_start;
+ spin_start.QuadPart = 0;
#endif /* STAGING_CSMT */
op = cs->ops->require_space(cs, sizeof(*op));
@@ -677,7 +679,10 @@ static void wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data)
* In Counter-Strike: Source a frame difference of 3 causes noticable
* input delay that makes the game unplayable. */
while (pending > 1)
+ {
+ wined3d_cs_mt_yield(&spin_start);
pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0);
+ }
}
static UINT wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data)
@@ -3389,17 +3394,25 @@ static void wined3d_cs_emit_stop(struct wined3d_cs *cs)
static void wined3d_cs_mt_finish(struct wined3d_cs *cs)
{
BOOL fence;
+
+ LARGE_INTEGER spin_start;
+ spin_start.QuadPart = 0;
+
wined3d_cs_emit_fence(cs, &fence);
/* A busy wait should be fine, we're not supposed to have to wait very
* long. */
- while (!InterlockedCompareExchange(&fence, TRUE, TRUE));
+ while (!InterlockedCompareExchange(&fence, TRUE, TRUE))
+ wined3d_cs_mt_yield(&spin_start);
}
static void wined3d_cs_mt_finish_prio(struct wined3d_cs *cs)
{
BOOL fence;
+ LARGE_INTEGER spin_start;
+ spin_start.QuadPart = 0;
+
if (cs->thread_id == GetCurrentThreadId())
{
static BOOL once;
@@ -3415,7 +3428,8 @@ static void wined3d_cs_mt_finish_prio(struct wined3d_cs *cs)
/* A busy wait should be fine, we're not supposed to have to wait very
* long. */
- while (!InterlockedCompareExchange(&fence, TRUE, TRUE));
+ while (!InterlockedCompareExchange(&fence, TRUE, TRUE))
+ wined3d_cs_mt_yield(&spin_start);
}
static const struct wined3d_cs_ops wined3d_cs_mt_ops =
@@ -3533,7 +3547,11 @@ static DWORD WINAPI wined3d_cs_run(void *thread_param)
LONG tail;
char poll = 0;
struct wined3d_cs_queue *queue;
- unsigned int spin_count = 0;
+
+ LARGE_INTEGER spin_start;
+ spin_start.QuadPart = 0;
+
+ BOOL spin_time_exeeded = FALSE;
TRACE("Started.\n");
@@ -3556,19 +3574,24 @@ static DWORD WINAPI wined3d_cs_run(void *thread_param)
else if (!queue_is_empty(&cs->queue))
{
queue = &cs->queue;
- if (!queue_is_empty(&cs->prio_queue))
- queue = &cs->prio_queue;
+ }
+ else if (poll != 0)
+ {
+ poll = 10;
+ continue;
}
else
{
- spin_count++;
- if (spin_count >= WINED3D_CS_SPIN_COUNT && list_empty(&cs->query_poll_list))
+ if (!spin_time_exeeded || !list_empty(&cs->query_poll_list))
+ spin_time_exeeded = wined3d_cs_mt_yield(&spin_start).QuadPart > WINED3D_CS_SPIN_TIME;
+ else
wined3d_cs_wait_event(cs);
continue;
}
- spin_count = 0;
+ spin_start.QuadPart = 0;
+ spin_time_exeeded = FALSE;
tail = queue->tail;
opcode = *(const enum wined3d_cs_op *)&queue->data[tail];
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 4247449..7af247b 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2678,9 +2678,42 @@ static inline void wined3d_resource_release(struct wined3d_resource *resource)
InterlockedDecrement(&resource->access_count);
}
+#if defined(STAGING_CSMT)
+#define WINED3D_YIELD_SPIN_TIME 2000 /* 10000 = 1 millisecond */
+
+static inline LARGE_INTEGER wined3d_cs_mt_yield(LARGE_INTEGER *spin_start)
+{
+ LARGE_INTEGER now, diff;
+
+ NtQuerySystemTime(&now);
+
+ if (spin_start->QuadPart == 0)
+ spin_start->QuadPart = now.QuadPart;
+
+ diff.QuadPart = now.QuadPart - spin_start->QuadPart;
+
+ if (diff.QuadPart < WINED3D_YIELD_SPIN_TIME)
+ SwitchToThread();
+ else
+ usleep(0);
+
+ return diff;
+}
+#endif /* STAGING_CSMT */
+
static inline void wined3d_resource_wait_idle(struct wined3d_resource *resource)
{
- while (InterlockedCompareExchange(&resource->access_count, 0, 0));
+#if defined(STAGING_CSMT)
+ LARGE_INTEGER spin_start;
+ spin_start.QuadPart = 0;
+#endif /* STAGING_CSMT */
+
+ while (InterlockedCompareExchange(&resource->access_count, 0, 0))
+ {
+#if defined(STAGING_CSMT)
+ wined3d_cs_mt_yield(&spin_start);
+#endif /* STAGING_CSMT */
+ }
}
void resource_cleanup(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
@@ -3169,7 +3202,7 @@ struct wined3d_cs_list
};
#define WINED3D_CS_QUEUE_SIZE 0x100000
-#define WINED3D_CS_SPIN_COUNT 10000000
+#define WINED3D_CS_SPIN_TIME 10000 /* 10000 = 1 millisecond */
struct wined3d_cs_queue
{
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment