Last active
August 18, 2016 18:11
-
-
Save laino/e12311899763060b500e16c5f9b3d5e6 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
From a87eae71e37b967afb2ee58bcab342f4cbffa8f5 Mon Sep 17 00:00:00 2001 | |
From: Nils Kuhnhenn <kuhnhenn.nils@gmail.com> | |
Date: Sat, 6 Aug 2016 16:25:27 +0200 | |
Subject: [PATCH] wined3d: use SwitchToThread() and calls to select() in | |
busy-loops | |
--- | |
dlls/wined3d/cs.c | 39 +++++++++++++++++++++++++++++++-------- | |
dlls/wined3d/wined3d_private.h | 42 ++++++++++++++++++++++++++++++++++++++++-- | |
2 files changed, 71 insertions(+), 10 deletions(-) | |
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..d89ee03 100644 | |
--- a/dlls/wined3d/wined3d_private.h | |
+++ b/dlls/wined3d/wined3d_private.h | |
@@ -2678,9 +2678,47 @@ static inline void wined3d_resource_release(struct wined3d_resource *resource) | |
InterlockedDecrement(&resource->access_count); | |
} | |
+#if defined(STAGING_CSMT) | |
+#define WINED3D_YIELD_SPIN_TIME 1000 /* 1000 = 0.1 milliseconds = 100 microseconds */ | |
+ | |
+static LARGE_INTEGER wined3d_cs_mt_yield(LARGE_INTEGER *spin_start) | |
+{ | |
+ struct timeval tv; | |
+ 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) | |
+ { | |
+ tv.tv_sec = 0; | |
+ tv.tv_usec = 9; | |
+ select( 0, NULL, NULL, NULL, &tv); | |
+ } | |
+ else | |
+ SwitchToThread(); | |
+ | |
+ 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 +3207,7 @@ struct wined3d_cs_list | |
}; | |
#define WINED3D_CS_QUEUE_SIZE 0x100000 | |
-#define WINED3D_CS_SPIN_COUNT 10000000 | |
+#define WINED3D_CS_SPIN_TIME 200000 /* 20000 = 20 milliseconds */ | |
struct wined3d_cs_queue | |
{ | |
-- | |
2.9.2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment