From b1cb4553ec6b9200aaee6943d40aa5c8db43591a Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Thu, 22 Jun 2017 14:38:12 +0200 Subject: [PATCH] Added patch to fix regression related to buffer_sync_apple handling. --- patches/patchinstall.sh | 20 + .../wined3d-CSMT_Main/9999-IfDefined.patch | 12 +- ...ned3d-Fix-buffer_sync_apple-handling.patch | 871 ++++++++++++++++++ patches/wined3d-buffer_sync_apple/definition | 1 + 4 files changed, 898 insertions(+), 6 deletions(-) create mode 100644 patches/wined3d-buffer_sync_apple/0001-wined3d-Fix-buffer_sync_apple-handling.patch create mode 100644 patches/wined3d-buffer_sync_apple/definition diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 3562e549..40b56441 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -438,6 +438,7 @@ patch_enable_all () enable_wined3d_Silence_FIXMEs="$1" enable_wined3d_WINED3DFMT_R32G32_UINT="$1" enable_wined3d_buffer_create="$1" + enable_wined3d_buffer_sync_apple="$1" enable_wined3d_wined3d_guess_gl_vendor="$1" enable_winedbg_Process_Arguments="$1" enable_winedevice_Default_Drivers="$1" @@ -1557,6 +1558,9 @@ patch_enable () wined3d-buffer_create) enable_wined3d_buffer_create="$2" ;; + wined3d-buffer_sync_apple) + enable_wined3d_buffer_sync_apple="$2" + ;; wined3d-wined3d_guess_gl_vendor) enable_wined3d_wined3d_guess_gl_vendor="$2" ;; @@ -9102,6 +9106,22 @@ if test "$enable_wined3d_buffer_create" -eq 1; then ) >> "$patchlist" fi +# Patchset wined3d-buffer_sync_apple +# | +# | This patchset fixes the following Wine bugs: +# | * [#43196] Fix regression related to buffer_sync_apple handling +# | +# | Modified files: +# | * dlls/wined3d/buffer.c, dlls/wined3d/context.c, dlls/wined3d/drawprim.c, dlls/wined3d/query.c, +# | dlls/wined3d/wined3d_private.h +# | +if test "$enable_wined3d_buffer_sync_apple" -eq 1; then + patch_apply wined3d-buffer_sync_apple/0001-wined3d-Fix-buffer_sync_apple-handling.patch + ( + printf '%s\n' '+ { "Józef Kucia", "wined3d: Fix regression related to buffer_sync_apple handling.", 1 },'; + ) >> "$patchlist" +fi + # Patchset wined3d-wined3d_guess_gl_vendor # | # | This patchset fixes the following Wine bugs: diff --git a/patches/wined3d-CSMT_Main/9999-IfDefined.patch b/patches/wined3d-CSMT_Main/9999-IfDefined.patch index af7ffcdd..85c51877 100644 --- a/patches/wined3d-CSMT_Main/9999-IfDefined.patch +++ b/patches/wined3d-CSMT_Main/9999-IfDefined.patch @@ -9,7 +9,7 @@ Based on patches by: diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c -@@ -1267,6 +1267,9 @@ HRESULT wined3d_buffer_upload_data(struct wined3d_buffer *buffer, +@@ -1263,6 +1263,9 @@ HRESULT wined3d_buffer_upload_data(struct wined3d_buffer *buffer, const struct wined3d_box *box, const void *data) { UINT offset, size; @@ -19,7 +19,7 @@ diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c HRESULT hr; BYTE *ptr; -@@ -1281,7 +1284,14 @@ HRESULT wined3d_buffer_upload_data(struct wined3d_buffer *buffer, +@@ -1277,7 +1280,14 @@ HRESULT wined3d_buffer_upload_data(struct wined3d_buffer *buffer, size = buffer->resource.size; } @@ -619,7 +619,7 @@ diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h -@@ -2766,6 +2766,16 @@ struct wined3d_state +@@ -2773,6 +2773,16 @@ struct wined3d_state struct wined3d_rasterizer_state *rasterizer_state; }; @@ -636,7 +636,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h #define WINED3D_UNMAPPED_STAGE ~0u /* Multithreaded flag. Removed from the public header to signal that -@@ -2877,6 +2887,12 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL +@@ -2884,6 +2894,12 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN; void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN; @@ -649,7 +649,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state) { -@@ -3064,7 +3080,11 @@ struct wined3d_texture +@@ -3071,7 +3087,11 @@ struct wined3d_texture unsigned int map_count; DWORD locations; @@ -661,7 +661,7 @@ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h } sub_resources[1]; }; -@@ -3379,6 +3399,9 @@ struct wined3d_cs_queue +@@ -3386,6 +3406,9 @@ struct wined3d_cs_queue struct wined3d_cs_ops { diff --git a/patches/wined3d-buffer_sync_apple/0001-wined3d-Fix-buffer_sync_apple-handling.patch b/patches/wined3d-buffer_sync_apple/0001-wined3d-Fix-buffer_sync_apple-handling.patch new file mode 100644 index 00000000..87dc4987 --- /dev/null +++ b/patches/wined3d-buffer_sync_apple/0001-wined3d-Fix-buffer_sync_apple-handling.patch @@ -0,0 +1,871 @@ +From 948c88721841364030eed86ec0e54b90b5a333c5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B3zef=20Kucia?= +Date: Thu, 22 Jun 2017 14:34:34 +0200 +Subject: wined3d: Fix regression related to buffer_sync_apple handling. + +--- + dlls/wined3d/buffer.c | 68 ++++++++--------- + dlls/wined3d/context.c | 92 ++++++++++++----------- + dlls/wined3d/drawprim.c | 12 +-- + dlls/wined3d/query.c | 165 +++++++++++++++++++++++++---------------- + dlls/wined3d/wined3d_private.h | 73 +++++++++--------- + 5 files changed, 229 insertions(+), 181 deletions(-) + +diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c +index 5740d65bc49..f9cb251ad53 100644 +--- a/dlls/wined3d/buffer.c ++++ b/dlls/wined3d/buffer.c +@@ -185,11 +185,10 @@ static void buffer_destroy_buffer_object(struct wined3d_buffer *buffer, struct w + checkGLcall("glDeleteBuffers"); + buffer->buffer_object = 0; + +- if (buffer->query) ++ if (buffer->fence) + { +- struct wined3d_query *query = &buffer->query->query; +- query->query_ops->query_destroy(query); +- buffer->query = NULL; ++ wined3d_fence_destroy(buffer->fence); ++ buffer->fence = NULL; + } + buffer->flags &= ~WINED3D_BUFFER_APPLESYNC; + } +@@ -812,9 +811,10 @@ void * CDECL wined3d_buffer_get_parent(const struct wined3d_buffer *buffer) + } + + /* The caller provides a context and binds the buffer */ +-static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags, const struct wined3d_gl_info *gl_info) ++static void buffer_sync_apple(struct wined3d_buffer *buffer, DWORD flags, const struct wined3d_gl_info *gl_info) + { +- enum wined3d_event_query_result ret; ++ enum wined3d_fence_result ret; ++ HRESULT hr; + + /* No fencing needs to be done if the app promises not to overwrite + * existing data. */ +@@ -823,62 +823,58 @@ static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags, const st + + if (flags & WINED3D_MAP_DISCARD) + { +- GL_EXTCALL(glBufferData(This->buffer_type_hint, This->resource.size, NULL, This->buffer_object_usage)); ++ GL_EXTCALL(glBufferData(buffer->buffer_type_hint, buffer->resource.size, NULL, buffer->buffer_object_usage)); + checkGLcall("glBufferData"); + return; + } + +- if (!This->query) ++ if (!buffer->fence) + { +- TRACE("Creating event query for buffer %p\n", This); +- +- if (!wined3d_event_query_supported(gl_info)) +- { +- FIXME("Event queries not supported, dropping async buffer locks.\n"); +- goto drop_query; +- } ++ TRACE("Creating fence for buffer %p.\n", buffer); + +- This->query = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->query)); +- if (!This->query) ++ if (FAILED(hr = wined3d_fence_create(buffer->resource.device, &buffer->fence))) + { +- ERR("Failed to allocate event query memory, dropping async buffer locks.\n"); +- goto drop_query; ++ if (hr == WINED3DERR_NOTAVAILABLE) ++ FIXME("Fences not supported, dropping async buffer locks.\n"); ++ else ++ ERR("Failed to create fence, hr %#x.\n", hr); ++ goto drop_fence; + } + + /* Since we don't know about old draws a glFinish is needed once */ + gl_info->gl_ops.gl.p_glFinish(); + return; + } +- TRACE("Synchronizing buffer %p\n", This); +- ret = wined3d_event_query_finish(This->query, This->resource.device); ++ ++ TRACE("Synchronizing buffer %p.\n", buffer); ++ ret = wined3d_fence_wait(buffer->fence, buffer->resource.device); + switch (ret) + { +- case WINED3D_EVENT_QUERY_NOT_STARTED: +- case WINED3D_EVENT_QUERY_OK: ++ case WINED3D_FENCE_NOT_STARTED: ++ case WINED3D_FENCE_OK: + /* All done */ + return; + +- case WINED3D_EVENT_QUERY_WRONG_THREAD: +- WARN("Cannot synchronize buffer lock due to a thread conflict\n"); +- goto drop_query; ++ case WINED3D_FENCE_WRONG_THREAD: ++ WARN("Cannot synchronize buffer lock due to a thread conflict.\n"); ++ goto drop_fence; + + default: +- ERR("wined3d_event_query_finish returned %u, dropping async buffer locks\n", ret); +- goto drop_query; ++ ERR("wined3d_fence_wait() returned %u, dropping async buffer locks.\n", ret); ++ goto drop_fence; + } + +-drop_query: +- if (This->query) ++drop_fence: ++ if (buffer->fence) + { +- struct wined3d_query *query = &This->query->query; +- query->query_ops->query_destroy(query); +- This->query = NULL; ++ wined3d_fence_destroy(buffer->fence); ++ buffer->fence = NULL; + } + + gl_info->gl_ops.gl.p_glFinish(); +- GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)); +- checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)"); +- This->flags &= ~WINED3D_BUFFER_APPLESYNC; ++ GL_EXTCALL(glBufferParameteriAPPLE(buffer->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)); ++ checkGLcall("glBufferParameteriAPPLE(buffer->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_TRUE)"); ++ buffer->flags &= ~WINED3D_BUFFER_APPLESYNC; + } + + static void buffer_mark_used(struct wined3d_buffer *buffer) +diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c +index fbc73ca9a1e..b5b788f2fdb 100644 +--- a/dlls/wined3d/context.c ++++ b/dlls/wined3d/context.c +@@ -794,63 +794,63 @@ void context_free_occlusion_query(struct wined3d_occlusion_query *query) + } + + /* Context activation is done by the caller. */ +-void context_alloc_event_query(struct wined3d_context *context, struct wined3d_event_query *query) ++void context_alloc_fence(struct wined3d_context *context, struct wined3d_fence *fence) + { + const struct wined3d_gl_info *gl_info = context->gl_info; + +- if (context->free_event_query_count) ++ if (context->free_fence_count) + { +- query->object = context->free_event_queries[--context->free_event_query_count]; ++ fence->object = context->free_fences[--context->free_fence_count]; + } + else + { + if (gl_info->supported[ARB_SYNC]) + { + /* Using ARB_sync, not much to do here. */ +- query->object.sync = NULL; +- TRACE("Allocated event query %p in context %p.\n", query->object.sync, context); ++ fence->object.sync = NULL; ++ TRACE("Allocated sync object in context %p.\n", context); + } + else if (gl_info->supported[APPLE_FENCE]) + { +- GL_EXTCALL(glGenFencesAPPLE(1, &query->object.id)); ++ GL_EXTCALL(glGenFencesAPPLE(1, &fence->object.id)); + checkGLcall("glGenFencesAPPLE"); + +- TRACE("Allocated event query %u in context %p.\n", query->object.id, context); ++ TRACE("Allocated fence %u in context %p.\n", fence->object.id, context); + } + else if(gl_info->supported[NV_FENCE]) + { +- GL_EXTCALL(glGenFencesNV(1, &query->object.id)); ++ GL_EXTCALL(glGenFencesNV(1, &fence->object.id)); + checkGLcall("glGenFencesNV"); + +- TRACE("Allocated event query %u in context %p.\n", query->object.id, context); ++ TRACE("Allocated fence %u in context %p.\n", fence->object.id, context); + } + else + { +- WARN("Event queries not supported, not allocating query id.\n"); +- query->object.id = 0; ++ WARN("Fences not supported, not allocating fence.\n"); ++ fence->object.id = 0; + } + } + +- query->context = context; +- list_add_head(&context->event_queries, &query->entry); ++ fence->context = context; ++ list_add_head(&context->fences, &fence->entry); + } + +-void context_free_event_query(struct wined3d_event_query *query) ++void context_free_fence(struct wined3d_fence *fence) + { +- struct wined3d_context *context = query->context; ++ struct wined3d_context *context = fence->context; + +- list_remove(&query->entry); +- query->context = NULL; ++ list_remove(&fence->entry); ++ fence->context = NULL; + +- if (!wined3d_array_reserve((void **)&context->free_event_queries, +- &context->free_event_query_size, context->free_event_query_count + 1, +- sizeof(*context->free_event_queries))) ++ if (!wined3d_array_reserve((void **)&context->free_fences, ++ &context->free_fence_size, context->free_fence_count + 1, ++ sizeof(*context->free_fences))) + { +- ERR("Failed to grow free list, leaking query %u in context %p.\n", query->object.id, context); ++ ERR("Failed to grow free list, leaking fence %u in context %p.\n", fence->object.id, context); + return; + } + +- context->free_event_queries[context->free_event_query_count++] = query->object; ++ context->free_fences[context->free_fence_count++] = fence->object; + } + + /* Context activation is done by the caller. */ +@@ -1265,8 +1265,8 @@ static void context_destroy_gl_resources(struct wined3d_context *context) + struct wined3d_so_statistics_query *so_statistics_query; + struct wined3d_timestamp_query *timestamp_query; + struct wined3d_occlusion_query *occlusion_query; +- struct wined3d_event_query *event_query; + struct fbo_entry *entry, *entry2; ++ struct wined3d_fence *fence; + HGLRC restore_ctx; + HDC restore_dc; + unsigned int i; +@@ -1309,18 +1309,25 @@ static void context_destroy_gl_resources(struct wined3d_context *context) + occlusion_query->context = NULL; + } + +- LIST_FOR_EACH_ENTRY(event_query, &context->event_queries, struct wined3d_event_query, entry) ++ LIST_FOR_EACH_ENTRY(fence, &context->fences, struct wined3d_fence, entry) + { + if (context->valid) + { + if (gl_info->supported[ARB_SYNC]) + { +- if (event_query->object.sync) GL_EXTCALL(glDeleteSync(event_query->object.sync)); ++ if (fence->object.sync) ++ GL_EXTCALL(glDeleteSync(fence->object.sync)); ++ } ++ else if (gl_info->supported[APPLE_FENCE]) ++ { ++ GL_EXTCALL(glDeleteFencesAPPLE(1, &fence->object.id)); ++ } ++ else if (gl_info->supported[NV_FENCE]) ++ { ++ GL_EXTCALL(glDeleteFencesNV(1, &fence->object.id)); + } +- else if (gl_info->supported[APPLE_FENCE]) GL_EXTCALL(glDeleteFencesAPPLE(1, &event_query->object.id)); +- else if (gl_info->supported[NV_FENCE]) GL_EXTCALL(glDeleteFencesNV(1, &event_query->object.id)); + } +- event_query->context = NULL; ++ fence->context = NULL; + } + + LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &context->fbo_destroy_list, struct fbo_entry, entry) +@@ -1368,23 +1375,23 @@ static void context_destroy_gl_resources(struct wined3d_context *context) + + if (gl_info->supported[ARB_SYNC]) + { +- for (i = 0; i < context->free_event_query_count; ++i) ++ for (i = 0; i < context->free_fence_count; ++i) + { +- GL_EXTCALL(glDeleteSync(context->free_event_queries[i].sync)); ++ GL_EXTCALL(glDeleteSync(context->free_fences[i].sync)); + } + } + else if (gl_info->supported[APPLE_FENCE]) + { +- for (i = 0; i < context->free_event_query_count; ++i) ++ for (i = 0; i < context->free_fence_count; ++i) + { +- GL_EXTCALL(glDeleteFencesAPPLE(1, &context->free_event_queries[i].id)); ++ GL_EXTCALL(glDeleteFencesAPPLE(1, &context->free_fences[i].id)); + } + } + else if (gl_info->supported[NV_FENCE]) + { +- for (i = 0; i < context->free_event_query_count; ++i) ++ for (i = 0; i < context->free_fence_count; ++i) + { +- GL_EXTCALL(glDeleteFencesNV(1, &context->free_event_queries[i].id)); ++ GL_EXTCALL(glDeleteFencesNV(1, &context->free_fences[i].id)); + } + } + +@@ -1395,7 +1402,7 @@ static void context_destroy_gl_resources(struct wined3d_context *context) + HeapFree(GetProcessHeap(), 0, context->free_pipeline_statistics_queries); + HeapFree(GetProcessHeap(), 0, context->free_timestamp_queries); + HeapFree(GetProcessHeap(), 0, context->free_occlusion_queries); +- HeapFree(GetProcessHeap(), 0, context->free_event_queries); ++ HeapFree(GetProcessHeap(), 0, context->free_fences); + + context_restore_pixel_format(context); + if (restore_ctx) +@@ -1849,11 +1856,10 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, + goto out; + list_init(&ret->occlusion_queries); + +- ret->free_event_query_size = 4; +- if (!(ret->free_event_queries = wined3d_calloc(ret->free_event_query_size, +- sizeof(*ret->free_event_queries)))) ++ ret->free_fence_size = 4; ++ if (!(ret->free_fences = wined3d_calloc(ret->free_fence_size, sizeof(*ret->free_fences)))) + goto out; +- list_init(&ret->event_queries); ++ list_init(&ret->fences); + + list_init(&ret->so_statistics_queries); + +@@ -2211,7 +2217,7 @@ out: + device->shader_backend->shader_free_context_data(ret); + device->adapter->fragment_pipe->free_context_data(ret); + HeapFree(GetProcessHeap(), 0, ret->texture_type); +- HeapFree(GetProcessHeap(), 0, ret->free_event_queries); ++ HeapFree(GetProcessHeap(), 0, ret->free_fences); + HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries); + HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries); + HeapFree(GetProcessHeap(), 0, ret->fbo_key); +@@ -3483,7 +3489,7 @@ static void context_update_stream_info(struct wined3d_context *context, const st + wined3d_stream_info_from_declaration(stream_info, state, gl_info, d3d_info); + + stream_info->all_vbo = 1; +- context->num_buffer_queries = 0; ++ context->buffer_fence_count = 0; + for (i = 0, map = stream_info->use_map; map; map >>= 1, ++i) + { + struct wined3d_stream_info_element *element; +@@ -3524,8 +3530,8 @@ static void context_update_stream_info(struct wined3d_context *context, const st + if (!element->data.buffer_object) + stream_info->all_vbo = 0; + +- if (buffer->query) +- context->buffer_queries[context->num_buffer_queries++] = buffer->query; ++ if (buffer->fence) ++ context->buffer_fences[context->buffer_fence_count++] = buffer->fence; + + TRACE("Load array %u {%#x:%p}.\n", i, element->data.buffer_object, element->data.addr); + } +diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c +index f844b25b695..e9bce44a422 100644 +--- a/dlls/wined3d/drawprim.c ++++ b/dlls/wined3d/drawprim.c +@@ -469,9 +469,9 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s + BOOL emulation = FALSE, rasterizer_discard = FALSE; + const struct wined3d_fb_state *fb = state->fb; + const struct wined3d_stream_info *stream_info; +- struct wined3d_event_query *ib_query = NULL; + struct wined3d_rendertarget_view *dsv, *rtv; + struct wined3d_stream_info si_emulated; ++ struct wined3d_fence *ib_fence = NULL; + const struct wined3d_gl_info *gl_info; + struct wined3d_context *context; + unsigned int i, idx_size = 0; +@@ -556,7 +556,7 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s + } + else + { +- ib_query = index_buffer->query; ++ ib_fence = index_buffer->fence; + idx_data = NULL; + } + idx_data = (const BYTE *)idx_data + state->index_offset; +@@ -655,10 +655,10 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s + checkGLcall("disable rasterizer discard"); + } + +- if (ib_query) +- wined3d_event_query_issue(ib_query, device); +- for (i = 0; i < context->num_buffer_queries; ++i) +- wined3d_event_query_issue(context->buffer_queries[i], device); ++ if (ib_fence) ++ wined3d_fence_issue(ib_fence, device); ++ for (i = 0; i < context->buffer_fence_count; ++i) ++ wined3d_fence_issue(context->buffer_fences[i], device); + + if (wined3d_settings.strict_draw_ordering) + gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ +diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c +index 8445922423f..d5acdf0ef5d 100644 +--- a/dlls/wined3d/query.c ++++ b/dlls/wined3d/query.c +@@ -83,33 +83,33 @@ static struct wined3d_pipeline_statistics_query *wined3d_pipeline_statistics_que + return CONTAINING_RECORD(query, struct wined3d_pipeline_statistics_query, query); + } + +-BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info) ++static BOOL wined3d_fence_supported(const struct wined3d_gl_info *gl_info) + { + return gl_info->supported[ARB_SYNC] || gl_info->supported[NV_FENCE] || gl_info->supported[APPLE_FENCE]; + } + +-static enum wined3d_event_query_result wined3d_event_query_test(const struct wined3d_event_query *query, ++static enum wined3d_fence_result wined3d_fence_test(const struct wined3d_fence *fence, + const struct wined3d_device *device, DWORD flags) + { + const struct wined3d_gl_info *gl_info; +- enum wined3d_event_query_result ret; + struct wined3d_context *context; ++ enum wined3d_fence_result ret; + BOOL fence_result; + +- TRACE("query %p, device %p, flags %#x.\n", query, device, flags); ++ TRACE("fence %p, device %p, flags %#x.\n", fence, device, flags); + +- if (!query->context) ++ if (!fence->context) + { +- TRACE("Query not started.\n"); +- return WINED3D_EVENT_QUERY_NOT_STARTED; ++ TRACE("Fence not issued.\n"); ++ return WINED3D_FENCE_NOT_STARTED; + } + +- if (!(context = context_reacquire(device, query->context))) ++ if (!(context = context_reacquire(device, fence->context))) + { +- if (!query->context->gl_info->supported[ARB_SYNC]) ++ if (!fence->context->gl_info->supported[ARB_SYNC]) + { +- WARN("Event query tested from wrong thread.\n"); +- return WINED3D_EVENT_QUERY_WRONG_THREAD; ++ WARN("Fence tested from wrong thread.\n"); ++ return WINED3D_FENCE_WRONG_THREAD; + } + context = context_acquire(device, NULL, 0); + } +@@ -117,7 +117,7 @@ static enum wined3d_event_query_result wined3d_event_query_test(const struct win + + if (gl_info->supported[ARB_SYNC]) + { +- GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, ++ GLenum gl_ret = GL_EXTCALL(glClientWaitSync(fence->object.sync, + (flags & WINED3DGETDATA_FLUSH) ? GL_SYNC_FLUSH_COMMANDS_BIT : 0, 0)); + checkGLcall("glClientWaitSync"); + +@@ -125,68 +125,72 @@ static enum wined3d_event_query_result wined3d_event_query_test(const struct win + { + case GL_ALREADY_SIGNALED: + case GL_CONDITION_SATISFIED: +- ret = WINED3D_EVENT_QUERY_OK; ++ ret = WINED3D_FENCE_OK; + break; + + case GL_TIMEOUT_EXPIRED: +- ret = WINED3D_EVENT_QUERY_WAITING; ++ ret = WINED3D_FENCE_WAITING; + break; + + case GL_WAIT_FAILED: + default: + ERR("glClientWaitSync returned %#x.\n", gl_ret); +- ret = WINED3D_EVENT_QUERY_ERROR; ++ ret = WINED3D_FENCE_ERROR; + } + } + else if (gl_info->supported[APPLE_FENCE]) + { +- fence_result = GL_EXTCALL(glTestFenceAPPLE(query->object.id)); ++ fence_result = GL_EXTCALL(glTestFenceAPPLE(fence->object.id)); + checkGLcall("glTestFenceAPPLE"); +- if (fence_result) ret = WINED3D_EVENT_QUERY_OK; +- else ret = WINED3D_EVENT_QUERY_WAITING; ++ if (fence_result) ++ ret = WINED3D_FENCE_OK; ++ else ++ ret = WINED3D_FENCE_WAITING; + } + else if (gl_info->supported[NV_FENCE]) + { +- fence_result = GL_EXTCALL(glTestFenceNV(query->object.id)); ++ fence_result = GL_EXTCALL(glTestFenceNV(fence->object.id)); + checkGLcall("glTestFenceNV"); +- if (fence_result) ret = WINED3D_EVENT_QUERY_OK; +- else ret = WINED3D_EVENT_QUERY_WAITING; ++ if (fence_result) ++ ret = WINED3D_FENCE_OK; ++ else ++ ret = WINED3D_FENCE_WAITING; + } + else + { +- ERR("Event query created despite lack of GL support\n"); +- ret = WINED3D_EVENT_QUERY_ERROR; ++ ERR("Fence created despite lack of GL support.\n"); ++ ret = WINED3D_FENCE_ERROR; + } + + context_release(context); + return ret; + } + +-enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_event_query *query, ++enum wined3d_fence_result wined3d_fence_wait(const struct wined3d_fence *fence, + const struct wined3d_device *device) + { + const struct wined3d_gl_info *gl_info; +- enum wined3d_event_query_result ret; + struct wined3d_context *context; ++ enum wined3d_fence_result ret; + +- TRACE("query %p, device %p.\n", query, device); ++ TRACE("fence %p, device %p.\n", fence, device); + +- if (!query->context) ++ if (!fence->context) + { +- TRACE("Query not started.\n"); +- return WINED3D_EVENT_QUERY_NOT_STARTED; ++ TRACE("Fence not issued.\n"); ++ return WINED3D_FENCE_NOT_STARTED; + } +- gl_info = query->context->gl_info; ++ gl_info = fence->context->gl_info; + +- if (!(context = context_reacquire(device, query->context))) ++ if (!(context = context_reacquire(device, fence->context))) + { + /* A glFinish does not reliably wait for draws in other contexts. The caller has + * to find its own way to cope with the thread switch + */ + if (!gl_info->supported[ARB_SYNC]) + { +- WARN("Event query finished from wrong thread.\n"); +- return WINED3D_EVENT_QUERY_WRONG_THREAD; ++ WARN("Fence finished from wrong thread.\n"); ++ return WINED3D_FENCE_WRONG_THREAD; + } + context = context_acquire(device, NULL, 0); + } +@@ -197,79 +201,115 @@ enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_ + /* Apple seems to be into arbitrary limits, and timeouts larger than + * 0xfffffffffffffbff immediately return GL_TIMEOUT_EXPIRED. We don't + * really care and can live with waiting a few μs less. (OS X 10.7.4). */ +- GLenum gl_ret = GL_EXTCALL(glClientWaitSync(query->object.sync, GL_SYNC_FLUSH_COMMANDS_BIT, ~(GLuint64)0xffff)); ++ GLenum gl_ret = GL_EXTCALL(glClientWaitSync(fence->object.sync, ++ GL_SYNC_FLUSH_COMMANDS_BIT, ~(GLuint64)0xffff)); + checkGLcall("glClientWaitSync"); + + switch (gl_ret) + { + case GL_ALREADY_SIGNALED: + case GL_CONDITION_SATISFIED: +- ret = WINED3D_EVENT_QUERY_OK; ++ ret = WINED3D_FENCE_OK; + break; + + /* We don't expect a timeout for a ~584 year wait */ + default: + ERR("glClientWaitSync returned %#x.\n", gl_ret); +- ret = WINED3D_EVENT_QUERY_ERROR; ++ ret = WINED3D_FENCE_ERROR; + } + } + else if (context->gl_info->supported[APPLE_FENCE]) + { +- GL_EXTCALL(glFinishFenceAPPLE(query->object.id)); ++ GL_EXTCALL(glFinishFenceAPPLE(fence->object.id)); + checkGLcall("glFinishFenceAPPLE"); +- ret = WINED3D_EVENT_QUERY_OK; ++ ret = WINED3D_FENCE_OK; + } + else if (context->gl_info->supported[NV_FENCE]) + { +- GL_EXTCALL(glFinishFenceNV(query->object.id)); ++ GL_EXTCALL(glFinishFenceNV(fence->object.id)); + checkGLcall("glFinishFenceNV"); +- ret = WINED3D_EVENT_QUERY_OK; ++ ret = WINED3D_FENCE_OK; + } + else + { +- ERR("Event query created without GL support\n"); +- ret = WINED3D_EVENT_QUERY_ERROR; ++ ERR("Fence created without GL support.\n"); ++ ret = WINED3D_FENCE_ERROR; + } + + context_release(context); + return ret; + } + +-void wined3d_event_query_issue(struct wined3d_event_query *query, const struct wined3d_device *device) ++void wined3d_fence_issue(struct wined3d_fence *fence, const struct wined3d_device *device) + { + struct wined3d_context *context = NULL; + const struct wined3d_gl_info *gl_info; + +- if (query->context && !(context = context_reacquire(device, query->context)) +- && !query->context->gl_info->supported[ARB_SYNC]) +- context_free_event_query(query); ++ if (fence->context && !(context = context_reacquire(device, fence->context)) ++ && !fence->context->gl_info->supported[ARB_SYNC]) ++ context_free_fence(fence); + if (!context) + context = context_acquire(device, NULL, 0); + gl_info = context->gl_info; +- if (!query->context) +- context_alloc_event_query(context, query); ++ if (!fence->context) ++ context_alloc_fence(context, fence); + + if (gl_info->supported[ARB_SYNC]) + { +- if (query->object.sync) GL_EXTCALL(glDeleteSync(query->object.sync)); ++ if (fence->object.sync) ++ GL_EXTCALL(glDeleteSync(fence->object.sync)); + checkGLcall("glDeleteSync"); +- query->object.sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)); ++ fence->object.sync = GL_EXTCALL(glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)); + checkGLcall("glFenceSync"); + } + else if (gl_info->supported[APPLE_FENCE]) + { +- GL_EXTCALL(glSetFenceAPPLE(query->object.id)); ++ GL_EXTCALL(glSetFenceAPPLE(fence->object.id)); + checkGLcall("glSetFenceAPPLE"); + } + else if (gl_info->supported[NV_FENCE]) + { +- GL_EXTCALL(glSetFenceNV(query->object.id, GL_ALL_COMPLETED_NV)); ++ GL_EXTCALL(glSetFenceNV(fence->object.id, GL_ALL_COMPLETED_NV)); + checkGLcall("glSetFenceNV"); + } + + context_release(context); + } + ++static void wined3d_fence_free(struct wined3d_fence *fence) ++{ ++ if (fence->context) ++ context_free_fence(fence); ++} ++ ++void wined3d_fence_destroy(struct wined3d_fence *fence) ++{ ++ wined3d_fence_free(fence); ++ HeapFree(GetProcessHeap(), 0, fence); ++} ++ ++HRESULT wined3d_fence_create(struct wined3d_device *device, struct wined3d_fence **fence) ++{ ++ const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; ++ struct wined3d_fence *object; ++ ++ TRACE("device %p, fence %p.\n", device, fence); ++ ++ if (!wined3d_fence_supported(gl_info)) ++ { ++ WARN("Fences not supported.\n"); ++ return WINED3DERR_NOTAVAILABLE; ++ } ++ ++ if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) ++ return E_OUTOFMEMORY; ++ ++ TRACE("Created fence %p.\n", object); ++ *fence = object; ++ ++ return WINED3D_OK; ++} ++ + ULONG CDECL wined3d_query_incref(struct wined3d_query *query) + { + ULONG refcount = InterlockedIncrement(&query->ref); +@@ -407,25 +447,25 @@ static BOOL wined3d_occlusion_query_ops_poll(struct wined3d_query *query, DWORD + static BOOL wined3d_event_query_ops_poll(struct wined3d_query *query, DWORD flags) + { + struct wined3d_event_query *event_query = wined3d_event_query_from_query(query); +- enum wined3d_event_query_result ret; ++ enum wined3d_fence_result ret; + + TRACE("query %p, flags %#x.\n", query, flags); + +- ret = wined3d_event_query_test(event_query, query->device, flags); ++ ret = wined3d_fence_test(&event_query->fence, query->device, flags); + switch (ret) + { +- case WINED3D_EVENT_QUERY_OK: +- case WINED3D_EVENT_QUERY_NOT_STARTED: ++ case WINED3D_FENCE_OK: ++ case WINED3D_FENCE_NOT_STARTED: + return event_query->signalled = TRUE; + +- case WINED3D_EVENT_QUERY_WAITING: ++ case WINED3D_FENCE_WAITING: + return event_query->signalled = FALSE; + +- case WINED3D_EVENT_QUERY_WRONG_THREAD: ++ case WINED3D_FENCE_WRONG_THREAD: + FIXME("(%p) Wrong thread, reporting GPU idle.\n", query); + return event_query->signalled = TRUE; + +- case WINED3D_EVENT_QUERY_ERROR: ++ case WINED3D_FENCE_ERROR: + ERR("The GL event query failed.\n"); + return event_query->signalled = TRUE; + +@@ -457,7 +497,7 @@ static BOOL wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD fla + { + struct wined3d_event_query *event_query = wined3d_event_query_from_query(query); + +- wined3d_event_query_issue(event_query, query->device); ++ wined3d_fence_issue(&event_query->fence, query->device); + return TRUE; + } + else if (flags & WINED3DISSUE_BEGIN) +@@ -864,8 +904,7 @@ static void wined3d_event_query_ops_destroy(struct wined3d_query *query) + { + struct wined3d_event_query *event_query = wined3d_event_query_from_query(query); + +- if (event_query->context) +- context_free_event_query(event_query); ++ wined3d_fence_free(&event_query->fence); + HeapFree(GetProcessHeap(), 0, event_query); + } + +@@ -886,7 +925,7 @@ static HRESULT wined3d_event_query_create(struct wined3d_device *device, + TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n", + device, type, parent, parent_ops, query); + +- if (!wined3d_event_query_supported(gl_info)) ++ if (!wined3d_fence_supported(gl_info)) + { + WARN("Event queries not supported.\n"); + return WINED3DERR_NOTAVAILABLE; +diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h +index 1025c98f180..fc6af2e2a14 100644 +--- a/dlls/wined3d/wined3d_private.h ++++ b/dlls/wined3d/wined3d_private.h +@@ -1607,6 +1607,35 @@ enum fogsource { + FOGSOURCE_COORD, + }; + ++union wined3d_gl_fence_object ++{ ++ GLuint id; ++ GLsync sync; ++}; ++ ++enum wined3d_fence_result ++{ ++ WINED3D_FENCE_OK, ++ WINED3D_FENCE_WAITING, ++ WINED3D_FENCE_NOT_STARTED, ++ WINED3D_FENCE_WRONG_THREAD, ++ WINED3D_FENCE_ERROR, ++}; ++ ++struct wined3d_fence ++{ ++ struct list entry; ++ union wined3d_gl_fence_object object; ++ struct wined3d_context *context; ++}; ++ ++HRESULT wined3d_fence_create(struct wined3d_device *device, struct wined3d_fence **fence) DECLSPEC_HIDDEN; ++void wined3d_fence_destroy(struct wined3d_fence *fence) DECLSPEC_HIDDEN; ++void wined3d_fence_issue(struct wined3d_fence *fence, ++ const struct wined3d_device *device) DECLSPEC_HIDDEN; ++enum wined3d_fence_result wined3d_fence_wait(const struct wined3d_fence *fence, ++ const struct wined3d_device *device) DECLSPEC_HIDDEN; ++ + /* Direct3D terminology with little modifications. We do not have an issued + * state because only the driver knows about it, but we have a created state + * because D3D allows GetData() on a created query, but OpenGL doesn't. */ +@@ -1641,36 +1670,14 @@ struct wined3d_query + struct list poll_list_entry; + }; + +-union wined3d_gl_query_object +-{ +- GLuint id; +- GLsync sync; +-}; +- + struct wined3d_event_query + { + struct wined3d_query query; + +- struct list entry; +- union wined3d_gl_query_object object; +- struct wined3d_context *context; ++ struct wined3d_fence fence; + BOOL signalled; + }; + +-enum wined3d_event_query_result +-{ +- WINED3D_EVENT_QUERY_OK, +- WINED3D_EVENT_QUERY_WAITING, +- WINED3D_EVENT_QUERY_NOT_STARTED, +- WINED3D_EVENT_QUERY_WRONG_THREAD, +- WINED3D_EVENT_QUERY_ERROR +-}; +- +-enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_event_query *query, +- const struct wined3d_device *device) DECLSPEC_HIDDEN; +-void wined3d_event_query_issue(struct wined3d_event_query *query, const struct wined3d_device *device) DECLSPEC_HIDDEN; +-BOOL wined3d_event_query_supported(const struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN; +- + struct wined3d_occlusion_query + { + struct wined3d_query query; +@@ -1876,10 +1883,10 @@ struct wined3d_context + unsigned int free_occlusion_query_count; + struct list occlusion_queries; + +- union wined3d_gl_query_object *free_event_queries; +- SIZE_T free_event_query_size; +- unsigned int free_event_query_count; +- struct list event_queries; ++ union wined3d_gl_fence_object *free_fences; ++ SIZE_T free_fence_size; ++ unsigned int free_fence_count; ++ struct list fences; + + GLuint *free_timestamp_queries; + SIZE_T free_timestamp_query_size; +@@ -1899,8 +1906,8 @@ struct wined3d_context + struct wined3d_stream_info stream_info; + + /* Fences for GL_APPLE_flush_buffer_range */ +- struct wined3d_event_query *buffer_queries[MAX_ATTRIBS]; +- unsigned int num_buffer_queries; ++ struct wined3d_fence *buffer_fences[MAX_ATTRIBS]; ++ unsigned int buffer_fence_count; + + DWORD tex_unit_map[MAX_COMBINED_SAMPLERS]; + DWORD rev_tex_unit_map[MAX_GL_FRAGMENT_SAMPLERS + MAX_VERTEX_SAMPLERS]; +@@ -2047,8 +2054,8 @@ BOOL wined3d_clip_blit(const RECT *clip_rect, RECT *clipped, RECT *other) DECLSP + + struct wined3d_context *context_acquire(const struct wined3d_device *device, + struct wined3d_texture *texture, unsigned int sub_resource_idx) DECLSPEC_HIDDEN; +-void context_alloc_event_query(struct wined3d_context *context, +- struct wined3d_event_query *query) DECLSPEC_HIDDEN; ++void context_alloc_fence(struct wined3d_context *context, ++ struct wined3d_fence *fence) DECLSPEC_HIDDEN; + void context_alloc_occlusion_query(struct wined3d_context *context, + struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; + void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) DECLSPEC_HIDDEN; +@@ -2072,7 +2079,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, stru + HGLRC context_create_wgl_attribs(const struct wined3d_gl_info *gl_info, HDC hdc, HGLRC share_ctx) DECLSPEC_HIDDEN; + void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; + void context_end_transform_feedback(struct wined3d_context *context) DECLSPEC_HIDDEN; +-void context_free_event_query(struct wined3d_event_query *query) DECLSPEC_HIDDEN; ++void context_free_fence(struct wined3d_fence *fence) DECLSPEC_HIDDEN; + void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; + struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN; + GLenum context_get_offscreen_gl_buffer(const struct wined3d_context *context) DECLSPEC_HIDDEN; +@@ -3533,7 +3540,7 @@ struct wined3d_buffer + + struct wined3d_map_range *maps; + SIZE_T maps_size, modified_areas; +- struct wined3d_event_query *query; ++ struct wined3d_fence *fence; + + /* conversion stuff */ + UINT decl_change_count, full_conversion_count; +-- +2.13.1 + diff --git a/patches/wined3d-buffer_sync_apple/definition b/patches/wined3d-buffer_sync_apple/definition new file mode 100644 index 00000000..19347df1 --- /dev/null +++ b/patches/wined3d-buffer_sync_apple/definition @@ -0,0 +1 @@ +Fixes: [43196] Fix regression related to buffer_sync_apple handling