From: Matteo Bruni mbruni@codeweavers.com
This avoids triggering a Mesa slowpath introduced by Mesa commit e7f3a8d6959c74f63c877dd8776fe519d54f946f.
Additionally, it helps applications using multiple swapchains and queries (e.g. the one in bug 43773) by not requiring extra context switches when polling queries. For the records, the actual issue from bug 43773 was probably fixed a long time ago, maybe already by 7b62a970e9ad3b4179394cf54f0232475fe2388a or thereabouts.
The downside of this change is that we'll now end up calling glFinish() when there are multiple threads using the same device when CSMT is disabled. That's a non-default setting and one that should only be used for troubleshooting purposes at this point, so it shouldn't be too bad of an issue. It might also make sense to just get rid of that glFinish() entirely, it's never going to be a complete fix. --- dlls/wined3d/adapter_gl.c | 2 +- dlls/wined3d/context_gl.c | 10 +++++ dlls/wined3d/device.c | 14 ++---- dlls/wined3d/swapchain.c | 81 +++++----------------------------- dlls/wined3d/wined3d_private.h | 7 --- 5 files changed, 26 insertions(+), 88 deletions(-)
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c index 60a168b5cef..3131fdadeae 100644 --- a/dlls/wined3d/adapter_gl.c +++ b/dlls/wined3d/adapter_gl.c @@ -4567,7 +4567,7 @@ static HRESULT adapter_gl_init_3d(struct wined3d_device *device)
wined3d_cs_init_object(device->cs, wined3d_device_gl_create_primary_opengl_context_cs, wined3d_device_gl(device)); wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); - if (!wined3d_swapchain_gl(device->swapchains[0])->context_count) + if (!device->context_count) return E_FAIL;
return WINED3D_OK; diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 66e4321dd12..2f6db56a961 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -1261,6 +1261,8 @@ static BOOL wined3d_context_gl_set_gl_context(struct wined3d_context_gl *context struct wined3d_device_gl *device_gl = wined3d_device_gl(context_gl->c.device); BOOL backup = FALSE;
+ TRACE("context_gl %p.\n", context_gl); + if (!wined3d_context_gl_set_pixel_format(context_gl)) { WARN("Failed to set pixel format %d on device context %p.\n", @@ -1366,6 +1368,8 @@ static void wined3d_context_gl_cleanup(struct wined3d_context_gl *context_gl) HDC restore_dc; unsigned int i;
+ TRACE("context_gl %p.\n", context_gl); + restore_ctx = wglGetCurrentContext(); restore_dc = wglGetCurrentDC();
@@ -4481,6 +4485,12 @@ static void wined3d_context_gl_activate(struct wined3d_context_gl *context_gl, struct wined3d_texture *texture, unsigned int sub_resource_idx) { wined3d_context_gl_enter(context_gl); + if (texture && texture->swapchain && texture->swapchain != context_gl->c.swapchain) + { + TRACE("Switching context_gl %p from swapchain %p to swapchain %p.\n", + context_gl, context_gl->c.swapchain, texture->swapchain); + context_gl->c.swapchain = texture->swapchain; + } wined3d_context_gl_update_window(context_gl); wined3d_context_gl_setup_target(context_gl, texture, sub_resource_idx); if (!context_gl->valid) diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 5e64cf9487c..02ac8ef2c6a 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1187,7 +1187,6 @@ bool wined3d_device_gl_create_bo(struct wined3d_device_gl *device_gl, struct win void wined3d_device_gl_delete_opengl_contexts_cs(void *object) { struct wined3d_device_gl *device_gl = object; - struct wined3d_swapchain_gl *swapchain_gl; struct wined3d_context_gl *context_gl; struct wined3d_context *context; struct wined3d_device *device; @@ -1219,12 +1218,7 @@ void wined3d_device_gl_delete_opengl_contexts_cs(void *object) context_release(context);
while (device->context_count) - { - if ((swapchain_gl = wined3d_swapchain_gl(device->contexts[0]->swapchain))) - wined3d_swapchain_gl_destroy_contexts(swapchain_gl); - else - wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0])); - } + wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0]));
if (device_gl->backup_dc) { @@ -1262,7 +1256,7 @@ void wined3d_device_gl_create_primary_opengl_context_cs(void *object) { WARN("Failed to initialise allocator.\n"); context_release(context); - wined3d_swapchain_gl_context_destroy(wined3d_swapchain_gl(swapchain), context_gl); + wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0])); return; }
@@ -1272,7 +1266,7 @@ void wined3d_device_gl_create_primary_opengl_context_cs(void *object) ERR("Failed to allocate shader private data, hr %#x.\n", hr); wined3d_allocator_cleanup(&device_gl->allocator); context_release(context); - wined3d_swapchain_gl_context_destroy(wined3d_swapchain_gl(swapchain), context_gl); + wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0])); return; }
@@ -1282,7 +1276,7 @@ void wined3d_device_gl_create_primary_opengl_context_cs(void *object) device->shader_backend->shader_free_private(device, NULL); wined3d_allocator_cleanup(&device_gl->allocator); context_release(context); - wined3d_swapchain_gl_context_destroy(wined3d_swapchain_gl(swapchain), context_gl); + wined3d_context_gl_destroy(wined3d_context_gl(device->contexts[0])); return; }
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 0fd082fac7b..acf8eab924e 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -23,6 +23,7 @@ #include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d); +WINE_DECLARE_DEBUG_CHANNEL(d3d_perf);
void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain) { @@ -85,19 +86,9 @@ void wined3d_swapchain_cleanup(struct wined3d_swapchain *swapchain) } }
-static void wined3d_swapchain_gl_destroy_object(void *object) -{ - wined3d_swapchain_gl_destroy_contexts(object); -} - void wined3d_swapchain_gl_cleanup(struct wined3d_swapchain_gl *swapchain_gl) { - struct wined3d_cs *cs = swapchain_gl->s.device->cs; - wined3d_swapchain_cleanup(&swapchain_gl->s); - - wined3d_cs_destroy_object(cs, wined3d_swapchain_gl_destroy_object, swapchain_gl); - wined3d_cs_finish(cs, WINED3D_CS_QUEUE_DEFAULT); }
static void wined3d_swapchain_vk_destroy_vulkan_swapchain(struct wined3d_swapchain_vk *swapchain_vk) @@ -583,7 +574,6 @@ static bool swapchain_present_is_partial_copy(struct wined3d_swapchain *swapchai static void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect, const RECT *dst_rect, unsigned int swap_interval, uint32_t flags) { - struct wined3d_swapchain_gl *swapchain_gl = wined3d_swapchain_gl(swapchain); struct wined3d_texture *back_buffer = swapchain->back_buffers[0]; const struct wined3d_pixel_format *pixel_format; const struct wined3d_gl_info *gl_info; @@ -619,8 +609,11 @@ static void swapchain_gl_present(struct wined3d_swapchain *swapchain, if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) swapchain_blit(swapchain, context, src_rect, dst_rect);
- if (swapchain_gl->context_count > 1) + if (swapchain->device->context_count > 1) + { + WARN_(d3d_perf)("Multiple contexts, calling glFinish() to enforce ordering.\n"); gl_info->gl_ops.gl.p_glFinish(); + }
/* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */ gl_info->gl_ops.wgl.p_wglSwapBuffers(context_gl->dc); @@ -1688,20 +1681,11 @@ HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl, str struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent, void *parent, const struct wined3d_parent_ops *parent_ops) { - HRESULT hr; - TRACE("swapchain_gl %p, device %p, desc %p, state_parent %p, parent %p, parent_ops %p.\n", swapchain_gl, device, desc, state_parent, parent, parent_ops);
- if (FAILED(hr = wined3d_swapchain_init(&swapchain_gl->s, device, desc, state_parent, parent, - parent_ops, &swapchain_gl_ops))) - { - /* Cleanup any context that may have been created for the swapchain. */ - wined3d_cs_destroy_object(device->cs, wined3d_swapchain_gl_destroy_object, swapchain_gl); - wined3d_cs_finish(device->cs, WINED3D_CS_QUEUE_DEFAULT); - } - - return hr; + return wined3d_swapchain_init(&swapchain_gl->s, device, desc, state_parent, parent, + parent_ops, &swapchain_gl_ops); }
HRESULT wined3d_swapchain_vk_init(struct wined3d_swapchain_vk *swapchain_vk, struct wined3d_device *device, @@ -1792,62 +1776,19 @@ static struct wined3d_context_gl *wined3d_swapchain_gl_create_context(struct win
context_release(&context_gl->c);
- if (!wined3d_array_reserve((void **)&swapchain_gl->contexts, &swapchain_gl->contexts_size, - swapchain_gl->context_count + 1, sizeof(*swapchain_gl->contexts))) - { - ERR("Failed to allocate new context array memory.\n"); - wined3d_context_gl_destroy(context_gl); - return NULL; - } - swapchain_gl->contexts[swapchain_gl->context_count++] = context_gl; - return context_gl; }
-void wined3d_swapchain_gl_context_destroy(struct wined3d_swapchain_gl *swapchain_gl, struct wined3d_context_gl *context_gl) -{ - unsigned int i, j; - - TRACE("swapchain_gl %p, context_gl %p.\n", swapchain_gl, context_gl); - - for (i = 0; i < swapchain_gl->context_count; ++i) - { - if (swapchain_gl->contexts[i] == context_gl) - { - wined3d_context_gl_destroy(swapchain_gl->contexts[i]); - for (j = i; j < --swapchain_gl->context_count; ++j) - swapchain_gl->contexts[j] = swapchain_gl->contexts[j + 1]; - return; - } - } - ERR("context_gl %p not found in the swapchain list.\n", context_gl); -} - -void wined3d_swapchain_gl_destroy_contexts(struct wined3d_swapchain_gl *swapchain_gl) -{ - unsigned int i; - - TRACE("swapchain_gl %p.\n", swapchain_gl); - - for (i = 0; i < swapchain_gl->context_count; ++i) - { - wined3d_context_gl_destroy(swapchain_gl->contexts[i]); - } - heap_free(swapchain_gl->contexts); - swapchain_gl->contexts_size = 0; - swapchain_gl->context_count = 0; - swapchain_gl->contexts = NULL; -} - struct wined3d_context_gl *wined3d_swapchain_gl_get_context(struct wined3d_swapchain_gl *swapchain_gl) { + struct wined3d_device *device = swapchain_gl->s.device; DWORD tid = GetCurrentThreadId(); unsigned int i;
- for (i = 0; i < swapchain_gl->context_count; ++i) + for (i = 0; i < device->context_count; ++i) { - if (swapchain_gl->contexts[i]->tid == tid) - return swapchain_gl->contexts[i]; + if (wined3d_context_gl(device->contexts[i])->tid == tid) + return wined3d_context_gl(device->contexts[i]); }
/* Create a new context for the thread. */ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 20194887b7a..f7c9c75364c 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -5708,10 +5708,6 @@ HRESULT wined3d_swapchain_no3d_init(struct wined3d_swapchain *swapchain_no3d, struct wined3d_swapchain_gl { struct wined3d_swapchain s; - - struct wined3d_context_gl **contexts; - SIZE_T contexts_size; - SIZE_T context_count; };
static inline struct wined3d_swapchain_gl *wined3d_swapchain_gl(struct wined3d_swapchain *swapchain) @@ -5720,9 +5716,6 @@ static inline struct wined3d_swapchain_gl *wined3d_swapchain_gl(struct wined3d_s }
void wined3d_swapchain_gl_cleanup(struct wined3d_swapchain_gl *swapchain_gl) DECLSPEC_HIDDEN; -void wined3d_swapchain_gl_context_destroy(struct wined3d_swapchain_gl *swapchain_gl, - struct wined3d_context_gl *context_gl) DECLSPEC_HIDDEN; -void wined3d_swapchain_gl_destroy_contexts(struct wined3d_swapchain_gl *swapchain_gl) DECLSPEC_HIDDEN; struct wined3d_context_gl *wined3d_swapchain_gl_get_context(struct wined3d_swapchain_gl *swapchain_gl) DECLSPEC_HIDDEN; HRESULT wined3d_swapchain_gl_init(struct wined3d_swapchain_gl *swapchain_gl, struct wined3d_device *device, struct wined3d_swapchain_desc *desc,