From c45b908abc0c4d163dbff0e4e8456c155286f04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B3zef=20Kucia?= Date: Sun, 9 Jul 2017 13:25:49 +0200 Subject: [PATCH] wined3d: Introduce wined3d fence objects. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use fences for the APPLESYNC codepath, and implement event queries on top of fences. Signed-off-by: Józef Kucia Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/wined3d/buffer.c | 54 ++++------ dlls/wined3d/context.c | 92 ++++++++-------- dlls/wined3d/drawprim.c | 12 +-- dlls/wined3d/query.c | 189 +++++++++++++++++++++------------ dlls/wined3d/wined3d_private.h | 70 ++++++------ 5 files changed, 237 insertions(+), 180 deletions(-) diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 26f3dea806d..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; } @@ -814,8 +813,7 @@ 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 *buffer, DWORD flags, const struct wined3d_gl_info *gl_info) { - enum wined3d_event_query_result ret; - struct wined3d_query *query; + enum wined3d_fence_result ret; HRESULT hr; /* No fencing needs to be done if the app promises not to overwrite @@ -830,23 +828,18 @@ static void buffer_sync_apple(struct wined3d_buffer *buffer, DWORD flags, const return; } - if (!buffer->query) + if (!buffer->fence) { - TRACE("Creating event query for buffer %p.\n", buffer); + TRACE("Creating fence for buffer %p.\n", buffer); - hr = wined3d_query_create(buffer->resource.device, WINED3D_QUERY_TYPE_EVENT, - NULL, &wined3d_null_parent_ops, &query); - if (hr == WINED3DERR_NOTAVAILABLE) + if (FAILED(hr = wined3d_fence_create(buffer->resource.device, &buffer->fence))) { - FIXME("Event queries not supported, 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; } - if (FAILED(hr)) - { - ERR("Failed to create event query, hr %#x.\n", hr); - goto drop_query; - } - buffer->query = CONTAINING_RECORD(query, struct wined3d_event_query, query); /* Since we don't know about old draws a glFinish is needed once */ gl_info->gl_ops.gl.p_glFinish(); @@ -854,29 +847,28 @@ static void buffer_sync_apple(struct wined3d_buffer *buffer, DWORD flags, const } TRACE("Synchronizing buffer %p.\n", buffer); - ret = wined3d_event_query_finish(buffer->query, buffer->resource.device); + 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: + case WINED3D_FENCE_WRONG_THREAD: WARN("Cannot synchronize buffer lock due to a thread conflict.\n"); - goto drop_query; + 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 (buffer->query) +drop_fence: + 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; } gl_info->gl_ops.gl.p_glFinish(); 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 e76011ce2cf..7d726d08832 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); } -static 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,127 @@ 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); +} + +static HRESULT wined3d_fence_init(struct wined3d_fence *fence, const struct wined3d_gl_info *gl_info) +{ + if (!wined3d_fence_supported(gl_info)) + { + WARN("Fences not supported.\n"); + return WINED3DERR_NOTAVAILABLE; + } + + return WINED3D_OK; +} + +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; + HRESULT hr; + + TRACE("device %p, fence %p.\n", device, fence); + + if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = wined3d_fence_init(object, gl_info))) + { + HeapFree(GetProcessHeap(), 0, object); + return hr; + } + + 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 +459,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 +509,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 +916,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); } @@ -882,19 +933,21 @@ static HRESULT wined3d_event_query_create(struct wined3d_device *device, { const struct wined3d_gl_info *gl_info = &device->adapter->gl_info; struct wined3d_event_query *object; + HRESULT hr; 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)) - { - WARN("Event queries not supported.\n"); - return WINED3DERR_NOTAVAILABLE; - } - if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object)))) return E_OUTOFMEMORY; + if (FAILED(hr = wined3d_fence_init(&object->fence, gl_info))) + { + WARN("Event queries not supported.\n"); + HeapFree(GetProcessHeap(), 0, object); + return WINED3DERR_NOTAVAILABLE; + } + wined3d_query_init(&object->query, device, type, &object->signalled, sizeof(object->signalled), &event_query_ops, parent, parent_ops); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index d687e780eaa..ccf05635f0e 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1607,6 +1607,34 @@ 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,35 +1669,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; - struct wined3d_occlusion_query { struct wined3d_query query; @@ -1875,10 +1882,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; @@ -1898,8 +1905,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]; @@ -2046,8 +2053,7 @@ 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; @@ -2071,7 +2077,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; @@ -3532,7 +3538,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;