Last active
August 6, 2016 00:35
-
-
Save laino/60aa3c024d1f052c77d63481760ad7b2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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