Last active
August 5, 2016 17:19
-
-
Save laino/efa26c7cbd6fb70c6cb94eeb2219c25e to your computer and use it in GitHub Desktop.
Wine CSMT patches
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 44d5f8a..c7c80c6 100644 | |
--- a/dlls/wined3d/cs.c | |
+++ b/dlls/wined3d/cs.c | |
@@ -2495,7 +2495,10 @@ static UINT wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data) | |
TRACE("Adding new light\n"); | |
object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)); | |
if (!object) | |
- return E_OUTOFMEMORY; | |
+ { | |
+ ERR("Out of memory!\n"); | |
+ return sizeof(*op); | |
+ } | |
list_add_head(&cs->state.light_map[hash_idx], &object->entry); | |
object->glIndex = -1; |
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 34085d3..44d5f8a 100644 | |
--- a/dlls/wined3d/cs.c | |
+++ b/dlls/wined3d/cs.c | |
@@ -80,6 +80,7 @@ enum wined3d_cs_op | |
WINED3D_CS_OP_TEXTURE_CHANGED, | |
WINED3D_CS_OP_TEXTURE_MAP, | |
WINED3D_CS_OP_TEXTURE_UNMAP, | |
+ WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION, | |
WINED3D_CS_OP_BUFFER_SWAP_MEM, | |
WINED3D_CS_OP_BUFFER_INVALIDATE_RANGE, | |
WINED3D_CS_OP_BUFFER_PRELOAD, | |
@@ -425,6 +426,13 @@ struct wined3d_cs_texture_unmap | |
unsigned int sub_resource_idx; | |
}; | |
+struct wined3d_cs_texture_add_dirty_region | |
+{ | |
+ enum wined3d_cs_op opcode; | |
+ struct wined3d_texture *texture; | |
+ unsigned int sub_resource_idx; | |
+}; | |
+ | |
struct wined3d_cs_texture_changed | |
{ | |
enum wined3d_cs_op opcode; | |
@@ -2760,6 +2771,49 @@ void wined3d_cs_emit_texture_unmap(struct wined3d_cs *cs, struct wined3d_texture | |
cs->ops->submit_prio(cs, sizeof(*op)); | |
} | |
+static UINT wined3d_cs_exec_texture_add_dirty_region(struct wined3d_cs *cs, const void *data) | |
+{ | |
+ const struct wined3d_cs_texture_add_dirty_region *op = data; | |
+ | |
+ struct wined3d_texture *texture = op->texture; | |
+ struct wined3d_context *context = context_acquire(cs->device, NULL); | |
+ | |
+ if (!wined3d_texture_load_location(texture, op->sub_resource_idx, context, texture->resource.map_binding)) | |
+ { | |
+ ERR("Failed to load location %s.\n", wined3d_debug_location(texture->resource.map_binding)); | |
+ } | |
+ else | |
+ { | |
+ wined3d_texture_invalidate_location(texture, op->sub_resource_idx, ~texture->resource.map_binding); | |
+ } | |
+ | |
+ context_release(context); | |
+ | |
+ wined3d_resource_release(&texture->resource); | |
+ | |
+ return sizeof(*op); | |
+} | |
+ | |
+void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, | |
+ struct wined3d_texture *texture, unsigned int sub_resource_idx, | |
+ const struct wined3d_box *dirty_region) | |
+{ | |
+ | |
+ if (dirty_region) | |
+ WARN("Ignoring dirty_region %s.\n", debug_box(dirty_region)); | |
+ | |
+ struct wined3d_cs_texture_add_dirty_region *op; | |
+ | |
+ op = cs->ops->require_space(cs, sizeof(*op)); | |
+ op->opcode = WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION; | |
+ op->texture = texture; | |
+ op->sub_resource_idx = sub_resource_idx; | |
+ | |
+ wined3d_resource_acquire(&texture->resource); | |
+ | |
+ cs->ops->submit(cs, sizeof(*op)); | |
+} | |
+ | |
static UINT wined3d_cs_exec_texture_preload(struct wined3d_cs *cs, const void *data) | |
{ | |
const struct wined3d_cs_texture_preload *op = data; | |
@@ -3237,6 +3291,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void | |
/* WINED3D_CS_OP_TEXTURE_CHANGED */ wined3d_cs_exec_texture_changed, | |
/* WINED3D_CS_OP_TEXTURE_MAP */ wined3d_cs_exec_texture_map, | |
/* WINED3D_CS_OP_TEXTURE_UNMAP */ wined3d_cs_exec_texture_unmap, | |
+ /* WINED3D_CS_OP_TEXTURE_ADD_DIRTY_REGION */ wined3d_cs_exec_texture_add_dirty_region, | |
/* WINED3D_CS_OP_BUFFER_SWAP_MEM */ wined3d_cs_exec_buffer_swap_mem, | |
/* WINED3D_CS_OP_BUFFER_INVALIDATE_RANGE */ wined3d_cs_exec_buffer_invalidate_bo_range, | |
/* WINED3D_CS_OP_BUFFER_PRELOAD */ wined3d_cs_exec_buffer_preload, | |
diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c | |
index a4380e6..2cbee1c 100644 | |
--- a/dlls/wined3d/texture.c | |
+++ b/dlls/wined3d/texture.c | |
@@ -1693,6 +1693,9 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, | |
} | |
sub_resource_idx = layer * texture->level_count; | |
+#if defined(STAGING_CSMT) | |
+ wined3d_cs_emit_texture_add_dirty_region(texture->resource.device->cs, texture, sub_resource_idx, dirty_region); | |
+#else | |
if (dirty_region) | |
WARN("Ignoring dirty_region %s.\n", debug_box(dirty_region)); | |
@@ -1705,6 +1708,7 @@ HRESULT CDECL wined3d_texture_add_dirty_region(struct wined3d_texture *texture, | |
} | |
wined3d_texture_invalidate_location(texture, sub_resource_idx, ~texture->resource.map_binding); | |
context_release(context); | |
+#endif | |
return WINED3D_OK; | |
} | |
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h | |
index ecb728a..224189c 100644 | |
--- a/dlls/wined3d/wined3d_private.h | |
+++ b/dlls/wined3d/wined3d_private.h | |
@@ -3314,6 +3332,8 @@ void *wined3d_cs_emit_texture_map(struct wined3d_cs *cs, struct wined3d_texture | |
unsigned int sub_resource_idx, DWORD flags) DECLSPEC_HIDDEN; | |
void wined3d_cs_emit_texture_unmap(struct wined3d_cs *cs, struct wined3d_texture *texture, | |
unsigned int sub_resource_idx) DECLSPEC_HIDDEN; | |
+void wined3d_cs_emit_texture_add_dirty_region(struct wined3d_cs *cs, struct wined3d_texture *texture, | |
+ unsigned int sub_resource_idx, const struct wined3d_box *dirty_region) DECLSPEC_HIDDEN; | |
void wined3d_cs_emit_texture_preload(struct wined3d_cs *cs, struct wined3d_texture *texture) DECLSPEC_HIDDEN; | |
void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src, | |
struct wined3d_texture *dst) DECLSPEC_HIDDEN; |
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 34085d3..44d5f8a 100644 | |
--- a/dlls/wined3d/cs.c | |
+++ b/dlls/wined3d/cs.c | |
@@ -669,7 +677,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(); | |
pending = InterlockedCompareExchange(&cs->pending_presents, 0, 0); | |
+ } | |
} | |
static UINT wined3d_cs_exec_clear(struct wined3d_cs *cs, const void *data) | |
@@ -3338,7 +3393,8 @@ static void wined3d_cs_mt_finish(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(); | |
} | |
static void wined3d_cs_mt_finish_prio(struct wined3d_cs *cs) | |
@@ -3360,7 +3416,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(); | |
} | |
static const struct wined3d_cs_ops wined3d_cs_mt_ops = | |
@@ -3478,7 +3535,9 @@ 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_time, now, diff; | |
+ spin_time.QuadPart = 0; | |
TRACE("Started.\n"); | |
@@ -3501,19 +3560,37 @@ 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)) | |
+ NtQuerySystemTime(&now); | |
+ | |
+ if (spin_time.QuadPart == 0) | |
+ { | |
+ spin_time.QuadPart = now.QuadPart; | |
+ } | |
+ | |
+ diff.QuadPart = now.QuadPart - spin_time.QuadPart; | |
+ | |
+ if (diff.QuadPart < WINED3D_CS_SPIN_TIME || | |
+ !list_empty(&cs->query_poll_list)) | |
+ { | |
+ wined3d_cs_mt_yield(); | |
+ } | |
+ else | |
+ { | |
wined3d_cs_wait_event(cs); | |
+ } | |
continue; | |
} | |
- spin_count = 0; | |
+ spin_time.QuadPart = 0; | |
tail = queue->tail; | |
opcode = *(const enum wined3d_cs_op *)&queue->data[tail]; | |
diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c | |
index ac6aa6e..f262fca 100644 | |
--- a/dlls/wined3d/wined3d_main.c | |
+++ b/dlls/wined3d/wined3d_main.c | |
@@ -93,6 +93,7 @@ struct wined3d_settings wined3d_settings = | |
FALSE, /* 3D support enabled by default. */ | |
#if defined(STAGING_CSMT) | |
TRUE, /* Multithreaded CS by default. */ | |
+ 2, /* 0 = Busy wait, 1 = usleep, 2 = SwitchToThread */ | |
#endif /* STAGING_CSMT */ | |
}; | |
@@ -346,6 +347,22 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL) | |
TRACE("Disabling multithreaded command stream.\n"); | |
wined3d_settings.cs_multithreaded = FALSE; | |
} | |
+ if (!get_config_key(hkey, appkey, "CSMTYield", buffer, size)) | |
+ { | |
+ if (!strcmp(buffer, "nothing")) | |
+ { | |
+ TRACE("CSMT will use busy-wait loops.\n"); | |
+ wined3d_settings.cs_multithreaded_yield = 0; | |
+ } else if (!strcmp(buffer, "usleep")) | |
+ { | |
+ TRACE("CSMT will use usleep in wait loops.\n"); | |
+ wined3d_settings.cs_multithreaded_yield = 1; | |
+ } else if (!strcmp(buffer, "SwitchToThread")) | |
+ { | |
+ TRACE("CSMT will use SwitchToThread in wait loops.\n"); | |
+ wined3d_settings.cs_multithreaded_yield = 2; | |
+ } | |
+ } | |
} | |
FIXME_(winediag)("Experimental wined3d CSMT feature is currently %s.\n", | |
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h | |
index ecb728a..224189c 100644 | |
--- a/dlls/wined3d/wined3d_private.h | |
+++ b/dlls/wined3d/wined3d_private.h | |
@@ -315,6 +315,7 @@ struct wined3d_settings | |
BOOL no_3d; | |
#if defined(STAGING_CSMT) | |
BOOL cs_multithreaded; | |
+ int cs_multithreaded_yield; | |
#endif /* STAGING_CSMT */ | |
}; | |
@@ -2678,9 +2679,26 @@ static inline void wined3d_resource_release(struct wined3d_resource *resource) | |
InterlockedDecrement(&resource->access_count); | |
} | |
+#if defined(STAGING_CSMT) | |
+static inline void wined3d_cs_mt_yield(void) | |
+{ | |
+ int yield_strategy = wined3d_settings.cs_multithreaded_yield; | |
+ | |
+ if (yield_strategy == 1) | |
+ usleep(0); | |
+ else if (yield_strategy == 2) | |
+ SwitchToThread(); | |
+} | |
+#endif /* STAGING_CSMT */ | |
+ | |
static inline void wined3d_resource_wait_idle(struct wined3d_resource *resource) | |
{ | |
- while (InterlockedCompareExchange(&resource->access_count, 0, 0)); | |
+ while (InterlockedCompareExchange(&resource->access_count, 0, 0)) | |
+ { | |
+#if defined(STAGING_CSMT) | |
+ wined3d_cs_mt_yield(); | |
+#endif /* STAGING_CSMT */ | |
+ } | |
} | |
void resource_cleanup(struct wined3d_resource *resource) DECLSPEC_HIDDEN; | |
@@ -3169,7 +3187,7 @@ struct wined3d_cs_list | |
}; | |
#define WINED3D_CS_QUEUE_SIZE 0x100000 | |
-#define WINED3D_CS_SPIN_COUNT 10000000 | |
+#define WINED3D_CS_SPIN_TIME 40000 /* 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