Commit c45b908a authored by Józef Kucia's avatar Józef Kucia Committed by Alexandre Julliard

wined3d: Introduce wined3d fence objects.

Use fences for the APPLESYNC codepath, and implement event queries on top of fences. Signed-off-by: 's avatarJózef Kucia <jkucia@codeweavers.com> Signed-off-by: 's avatarHenri Verbeet <hverbeet@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 11c902eb
...@@ -185,11 +185,10 @@ static void buffer_destroy_buffer_object(struct wined3d_buffer *buffer, struct w ...@@ -185,11 +185,10 @@ static void buffer_destroy_buffer_object(struct wined3d_buffer *buffer, struct w
checkGLcall("glDeleteBuffers"); checkGLcall("glDeleteBuffers");
buffer->buffer_object = 0; buffer->buffer_object = 0;
if (buffer->query) if (buffer->fence)
{ {
struct wined3d_query *query = &buffer->query->query; wined3d_fence_destroy(buffer->fence);
query->query_ops->query_destroy(query); buffer->fence = NULL;
buffer->query = NULL;
} }
buffer->flags &= ~WINED3D_BUFFER_APPLESYNC; buffer->flags &= ~WINED3D_BUFFER_APPLESYNC;
} }
...@@ -814,8 +813,7 @@ void * CDECL wined3d_buffer_get_parent(const struct wined3d_buffer *buffer) ...@@ -814,8 +813,7 @@ void * CDECL wined3d_buffer_get_parent(const struct wined3d_buffer *buffer)
/* The caller provides a context and binds the 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) 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;
struct wined3d_query *query;
HRESULT hr; HRESULT hr;
/* No fencing needs to be done if the app promises not to overwrite /* 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 ...@@ -830,23 +828,18 @@ static void buffer_sync_apple(struct wined3d_buffer *buffer, DWORD flags, const
return; 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, if (FAILED(hr = wined3d_fence_create(buffer->resource.device, &buffer->fence)))
NULL, &wined3d_null_parent_ops, &query);
if (hr == WINED3DERR_NOTAVAILABLE)
{
FIXME("Event queries not supported, dropping async buffer locks.\n");
goto drop_query;
}
if (FAILED(hr))
{ {
ERR("Failed to create event query, hr %#x.\n", hr); if (hr == WINED3DERR_NOTAVAILABLE)
goto drop_query; FIXME("Fences not supported, dropping async buffer locks.\n");
else
ERR("Failed to create fence, hr %#x.\n", hr);
goto drop_fence;
} }
buffer->query = CONTAINING_RECORD(query, struct wined3d_event_query, query);
/* Since we don't know about old draws a glFinish is needed once */ /* Since we don't know about old draws a glFinish is needed once */
gl_info->gl_ops.gl.p_glFinish(); gl_info->gl_ops.gl.p_glFinish();
...@@ -854,29 +847,28 @@ static void buffer_sync_apple(struct wined3d_buffer *buffer, DWORD flags, const ...@@ -854,29 +847,28 @@ static void buffer_sync_apple(struct wined3d_buffer *buffer, DWORD flags, const
} }
TRACE("Synchronizing buffer %p.\n", buffer); 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) switch (ret)
{ {
case WINED3D_EVENT_QUERY_NOT_STARTED: case WINED3D_FENCE_NOT_STARTED:
case WINED3D_EVENT_QUERY_OK: case WINED3D_FENCE_OK:
/* All done */ /* All done */
return; return;
case WINED3D_EVENT_QUERY_WRONG_THREAD: case WINED3D_FENCE_WRONG_THREAD:
WARN("Cannot synchronize buffer lock due to a thread conflict.\n"); WARN("Cannot synchronize buffer lock due to a thread conflict.\n");
goto drop_query; goto drop_fence;
default: default:
ERR("wined3d_event_query_finish returned %u, dropping async buffer locks.\n", ret); ERR("wined3d_fence_wait() returned %u, dropping async buffer locks.\n", ret);
goto drop_query; goto drop_fence;
} }
drop_query: drop_fence:
if (buffer->query) if (buffer->fence)
{ {
struct wined3d_query *query = &buffer->query->query; wined3d_fence_destroy(buffer->fence);
query->query_ops->query_destroy(query); buffer->fence = NULL;
buffer->query = NULL;
} }
gl_info->gl_ops.gl.p_glFinish(); gl_info->gl_ops.gl.p_glFinish();
......
...@@ -794,63 +794,63 @@ void context_free_occlusion_query(struct wined3d_occlusion_query *query) ...@@ -794,63 +794,63 @@ void context_free_occlusion_query(struct wined3d_occlusion_query *query)
} }
/* Context activation is done by the caller. */ /* 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; 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 else
{ {
if (gl_info->supported[ARB_SYNC]) if (gl_info->supported[ARB_SYNC])
{ {
/* Using ARB_sync, not much to do here. */ /* Using ARB_sync, not much to do here. */
query->object.sync = NULL; fence->object.sync = NULL;
TRACE("Allocated event query %p in context %p.\n", query->object.sync, context); TRACE("Allocated sync object in context %p.\n", context);
} }
else if (gl_info->supported[APPLE_FENCE]) else if (gl_info->supported[APPLE_FENCE])
{ {
GL_EXTCALL(glGenFencesAPPLE(1, &query->object.id)); GL_EXTCALL(glGenFencesAPPLE(1, &fence->object.id));
checkGLcall("glGenFencesAPPLE"); 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]) else if(gl_info->supported[NV_FENCE])
{ {
GL_EXTCALL(glGenFencesNV(1, &query->object.id)); GL_EXTCALL(glGenFencesNV(1, &fence->object.id));
checkGLcall("glGenFencesNV"); 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 else
{ {
WARN("Event queries not supported, not allocating query id.\n"); WARN("Fences not supported, not allocating fence.\n");
query->object.id = 0; fence->object.id = 0;
} }
} }
query->context = context; fence->context = context;
list_add_head(&context->event_queries, &query->entry); 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); list_remove(&fence->entry);
query->context = NULL; fence->context = NULL;
if (!wined3d_array_reserve((void **)&context->free_event_queries, if (!wined3d_array_reserve((void **)&context->free_fences,
&context->free_event_query_size, context->free_event_query_count + 1, &context->free_fence_size, context->free_fence_count + 1,
sizeof(*context->free_event_queries))) 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; 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. */ /* Context activation is done by the caller. */
...@@ -1265,8 +1265,8 @@ static void context_destroy_gl_resources(struct wined3d_context *context) ...@@ -1265,8 +1265,8 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
struct wined3d_so_statistics_query *so_statistics_query; struct wined3d_so_statistics_query *so_statistics_query;
struct wined3d_timestamp_query *timestamp_query; struct wined3d_timestamp_query *timestamp_query;
struct wined3d_occlusion_query *occlusion_query; struct wined3d_occlusion_query *occlusion_query;
struct wined3d_event_query *event_query;
struct fbo_entry *entry, *entry2; struct fbo_entry *entry, *entry2;
struct wined3d_fence *fence;
HGLRC restore_ctx; HGLRC restore_ctx;
HDC restore_dc; HDC restore_dc;
unsigned int i; unsigned int i;
...@@ -1309,18 +1309,25 @@ static void context_destroy_gl_resources(struct wined3d_context *context) ...@@ -1309,18 +1309,25 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
occlusion_query->context = NULL; 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 (context->valid)
{ {
if (gl_info->supported[ARB_SYNC]) 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) 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) ...@@ -1368,23 +1375,23 @@ static void context_destroy_gl_resources(struct wined3d_context *context)
if (gl_info->supported[ARB_SYNC]) 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]) 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]) 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) ...@@ -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_pipeline_statistics_queries);
HeapFree(GetProcessHeap(), 0, context->free_timestamp_queries); HeapFree(GetProcessHeap(), 0, context->free_timestamp_queries);
HeapFree(GetProcessHeap(), 0, context->free_occlusion_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); context_restore_pixel_format(context);
if (restore_ctx) if (restore_ctx)
...@@ -1849,11 +1856,10 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, ...@@ -1849,11 +1856,10 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
goto out; goto out;
list_init(&ret->occlusion_queries); list_init(&ret->occlusion_queries);
ret->free_event_query_size = 4; ret->free_fence_size = 4;
if (!(ret->free_event_queries = wined3d_calloc(ret->free_event_query_size, if (!(ret->free_fences = wined3d_calloc(ret->free_fence_size, sizeof(*ret->free_fences))))
sizeof(*ret->free_event_queries))))
goto out; goto out;
list_init(&ret->event_queries); list_init(&ret->fences);
list_init(&ret->so_statistics_queries); list_init(&ret->so_statistics_queries);
...@@ -2211,7 +2217,7 @@ out: ...@@ -2211,7 +2217,7 @@ out:
device->shader_backend->shader_free_context_data(ret); device->shader_backend->shader_free_context_data(ret);
device->adapter->fragment_pipe->free_context_data(ret); device->adapter->fragment_pipe->free_context_data(ret);
HeapFree(GetProcessHeap(), 0, ret->texture_type); 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_occlusion_queries);
HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries); HeapFree(GetProcessHeap(), 0, ret->free_timestamp_queries);
HeapFree(GetProcessHeap(), 0, ret->fbo_key); HeapFree(GetProcessHeap(), 0, ret->fbo_key);
...@@ -3483,7 +3489,7 @@ static void context_update_stream_info(struct wined3d_context *context, const st ...@@ -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); wined3d_stream_info_from_declaration(stream_info, state, gl_info, d3d_info);
stream_info->all_vbo = 1; 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) for (i = 0, map = stream_info->use_map; map; map >>= 1, ++i)
{ {
struct wined3d_stream_info_element *element; struct wined3d_stream_info_element *element;
...@@ -3524,8 +3530,8 @@ static void context_update_stream_info(struct wined3d_context *context, const st ...@@ -3524,8 +3530,8 @@ static void context_update_stream_info(struct wined3d_context *context, const st
if (!element->data.buffer_object) if (!element->data.buffer_object)
stream_info->all_vbo = 0; stream_info->all_vbo = 0;
if (buffer->query) if (buffer->fence)
context->buffer_queries[context->num_buffer_queries++] = buffer->query; context->buffer_fences[context->buffer_fence_count++] = buffer->fence;
TRACE("Load array %u {%#x:%p}.\n", i, element->data.buffer_object, element->data.addr); TRACE("Load array %u {%#x:%p}.\n", i, element->data.buffer_object, element->data.addr);
} }
......
...@@ -469,9 +469,9 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s ...@@ -469,9 +469,9 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
BOOL emulation = FALSE, rasterizer_discard = FALSE; BOOL emulation = FALSE, rasterizer_discard = FALSE;
const struct wined3d_fb_state *fb = state->fb; const struct wined3d_fb_state *fb = state->fb;
const struct wined3d_stream_info *stream_info; const struct wined3d_stream_info *stream_info;
struct wined3d_event_query *ib_query = NULL;
struct wined3d_rendertarget_view *dsv, *rtv; struct wined3d_rendertarget_view *dsv, *rtv;
struct wined3d_stream_info si_emulated; struct wined3d_stream_info si_emulated;
struct wined3d_fence *ib_fence = NULL;
const struct wined3d_gl_info *gl_info; const struct wined3d_gl_info *gl_info;
struct wined3d_context *context; struct wined3d_context *context;
unsigned int i, idx_size = 0; unsigned int i, idx_size = 0;
...@@ -556,7 +556,7 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s ...@@ -556,7 +556,7 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
} }
else else
{ {
ib_query = index_buffer->query; ib_fence = index_buffer->fence;
idx_data = NULL; idx_data = NULL;
} }
idx_data = (const BYTE *)idx_data + state->index_offset; 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 ...@@ -655,10 +655,10 @@ void draw_primitive(struct wined3d_device *device, const struct wined3d_state *s
checkGLcall("disable rasterizer discard"); checkGLcall("disable rasterizer discard");
} }
if (ib_query) if (ib_fence)
wined3d_event_query_issue(ib_query, device); wined3d_fence_issue(ib_fence, device);
for (i = 0; i < context->num_buffer_queries; ++i) for (i = 0; i < context->buffer_fence_count; ++i)
wined3d_event_query_issue(context->buffer_queries[i], device); wined3d_fence_issue(context->buffer_fences[i], device);
if (wined3d_settings.strict_draw_ordering) if (wined3d_settings.strict_draw_ordering)
gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */ gl_info->gl_ops.gl.p_glFlush(); /* Flush to ensure ordering across contexts. */
......
...@@ -83,33 +83,33 @@ static struct wined3d_pipeline_statistics_query *wined3d_pipeline_statistics_que ...@@ -83,33 +83,33 @@ static struct wined3d_pipeline_statistics_query *wined3d_pipeline_statistics_que
return CONTAINING_RECORD(query, struct wined3d_pipeline_statistics_query, query); 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]; 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_device *device, DWORD flags)
{ {
const struct wined3d_gl_info *gl_info; const struct wined3d_gl_info *gl_info;
enum wined3d_event_query_result ret;
struct wined3d_context *context; struct wined3d_context *context;
enum wined3d_fence_result ret;
BOOL fence_result; 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"); TRACE("Fence not issued.\n");
return WINED3D_EVENT_QUERY_NOT_STARTED; 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"); WARN("Fence tested from wrong thread.\n");
return WINED3D_EVENT_QUERY_WRONG_THREAD; return WINED3D_FENCE_WRONG_THREAD;
} }
context = context_acquire(device, NULL, 0); context = context_acquire(device, NULL, 0);
} }
...@@ -117,7 +117,7 @@ static enum wined3d_event_query_result wined3d_event_query_test(const struct win ...@@ -117,7 +117,7 @@ static enum wined3d_event_query_result wined3d_event_query_test(const struct win
if (gl_info->supported[ARB_SYNC]) 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)); (flags & WINED3DGETDATA_FLUSH) ? GL_SYNC_FLUSH_COMMANDS_BIT : 0, 0));
checkGLcall("glClientWaitSync"); checkGLcall("glClientWaitSync");
...@@ -125,68 +125,72 @@ static enum wined3d_event_query_result wined3d_event_query_test(const struct win ...@@ -125,68 +125,72 @@ static enum wined3d_event_query_result wined3d_event_query_test(const struct win
{ {
case GL_ALREADY_SIGNALED: case GL_ALREADY_SIGNALED:
case GL_CONDITION_SATISFIED: case GL_CONDITION_SATISFIED:
ret = WINED3D_EVENT_QUERY_OK; ret = WINED3D_FENCE_OK;
break; break;
case GL_TIMEOUT_EXPIRED: case GL_TIMEOUT_EXPIRED:
ret = WINED3D_EVENT_QUERY_WAITING; ret = WINED3D_FENCE_WAITING;
break; break;
case GL_WAIT_FAILED: case GL_WAIT_FAILED:
default: default:
ERR("glClientWaitSync returned %#x.\n", gl_ret); ERR("glClientWaitSync returned %#x.\n", gl_ret);
ret = WINED3D_EVENT_QUERY_ERROR; ret = WINED3D_FENCE_ERROR;
} }
} }
else if (gl_info->supported[APPLE_FENCE]) 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"); checkGLcall("glTestFenceAPPLE");
if (fence_result) ret = WINED3D_EVENT_QUERY_OK; if (fence_result)
else ret = WINED3D_EVENT_QUERY_WAITING; ret = WINED3D_FENCE_OK;
else
ret = WINED3D_FENCE_WAITING;
} }
else if (gl_info->supported[NV_FENCE]) 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"); checkGLcall("glTestFenceNV");
if (fence_result) ret = WINED3D_EVENT_QUERY_OK; if (fence_result)
else ret = WINED3D_EVENT_QUERY_WAITING; ret = WINED3D_FENCE_OK;
else
ret = WINED3D_FENCE_WAITING;
} }
else else
{ {
ERR("Event query created despite lack of GL support\n"); ERR("Fence created despite lack of GL support.\n");
ret = WINED3D_EVENT_QUERY_ERROR; ret = WINED3D_FENCE_ERROR;
} }
context_release(context); context_release(context);
return ret; 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_device *device)
{ {
const struct wined3d_gl_info *gl_info; const struct wined3d_gl_info *gl_info;
enum wined3d_event_query_result ret;
struct wined3d_context *context; 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"); TRACE("Fence not issued.\n");
return WINED3D_EVENT_QUERY_NOT_STARTED; 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 /* 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 * to find its own way to cope with the thread switch
*/ */
if (!gl_info->supported[ARB_SYNC]) if (!gl_info->supported[ARB_SYNC])
{ {
WARN("Event query finished from wrong thread.\n"); WARN("Fence finished from wrong thread.\n");
return WINED3D_EVENT_QUERY_WRONG_THREAD; return WINED3D_FENCE_WRONG_THREAD;
} }
context = context_acquire(device, NULL, 0); context = context_acquire(device, NULL, 0);
} }
...@@ -197,79 +201,127 @@ enum wined3d_event_query_result wined3d_event_query_finish(const struct wined3d_ ...@@ -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 /* Apple seems to be into arbitrary limits, and timeouts larger than
* 0xfffffffffffffbff immediately return GL_TIMEOUT_EXPIRED. We don't * 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). */ * 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"); checkGLcall("glClientWaitSync");
switch (gl_ret) switch (gl_ret)
{ {
case GL_ALREADY_SIGNALED: case GL_ALREADY_SIGNALED:
case GL_CONDITION_SATISFIED: case GL_CONDITION_SATISFIED:
ret = WINED3D_EVENT_QUERY_OK; ret = WINED3D_FENCE_OK;
break; break;
/* We don't expect a timeout for a ~584 year wait */ /* We don't expect a timeout for a ~584 year wait */
default: default:
ERR("glClientWaitSync returned %#x.\n", gl_ret); ERR("glClientWaitSync returned %#x.\n", gl_ret);
ret = WINED3D_EVENT_QUERY_ERROR; ret = WINED3D_FENCE_ERROR;
} }
} }
else if (context->gl_info->supported[APPLE_FENCE]) else if (context->gl_info->supported[APPLE_FENCE])
{ {
GL_EXTCALL(glFinishFenceAPPLE(query->object.id)); GL_EXTCALL(glFinishFenceAPPLE(fence->object.id));
checkGLcall("glFinishFenceAPPLE"); checkGLcall("glFinishFenceAPPLE");
ret = WINED3D_EVENT_QUERY_OK; ret = WINED3D_FENCE_OK;
} }
else if (context->gl_info->supported[NV_FENCE]) else if (context->gl_info->supported[NV_FENCE])
{ {
GL_EXTCALL(glFinishFenceNV(query->object.id)); GL_EXTCALL(glFinishFenceNV(fence->object.id));
checkGLcall("glFinishFenceNV"); checkGLcall("glFinishFenceNV");
ret = WINED3D_EVENT_QUERY_OK; ret = WINED3D_FENCE_OK;
} }
else else
{ {
ERR("Event query created without GL support\n"); ERR("Fence created without GL support.\n");
ret = WINED3D_EVENT_QUERY_ERROR; ret = WINED3D_FENCE_ERROR;
} }
context_release(context); context_release(context);
return ret; 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; struct wined3d_context *context = NULL;
const struct wined3d_gl_info *gl_info; const struct wined3d_gl_info *gl_info;
if (query->context && !(context = context_reacquire(device, query->context)) if (fence->context && !(context = context_reacquire(device, fence->context))
&& !query->context->gl_info->supported[ARB_SYNC]) && !fence->context->gl_info->supported[ARB_SYNC])
context_free_event_query(query); context_free_fence(fence);
if (!context) if (!context)
context = context_acquire(device, NULL, 0); context = context_acquire(device, NULL, 0);
gl_info = context->gl_info; gl_info = context->gl_info;
if (!query->context) if (!fence->context)
context_alloc_event_query(context, query); context_alloc_fence(context, fence);
if (gl_info->supported[ARB_SYNC]) 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"); 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"); checkGLcall("glFenceSync");
} }
else if (gl_info->supported[APPLE_FENCE]) else if (gl_info->supported[APPLE_FENCE])
{ {
GL_EXTCALL(glSetFenceAPPLE(query->object.id)); GL_EXTCALL(glSetFenceAPPLE(fence->object.id));
checkGLcall("glSetFenceAPPLE"); checkGLcall("glSetFenceAPPLE");
} }
else if (gl_info->supported[NV_FENCE]) 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"); checkGLcall("glSetFenceNV");
} }
context_release(context); 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 CDECL wined3d_query_incref(struct wined3d_query *query)
{ {
ULONG refcount = InterlockedIncrement(&query->ref); ULONG refcount = InterlockedIncrement(&query->ref);
...@@ -407,25 +459,25 @@ static BOOL wined3d_occlusion_query_ops_poll(struct wined3d_query *query, DWORD ...@@ -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) 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); 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); 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) switch (ret)
{ {
case WINED3D_EVENT_QUERY_OK: case WINED3D_FENCE_OK:
case WINED3D_EVENT_QUERY_NOT_STARTED: case WINED3D_FENCE_NOT_STARTED:
return event_query->signalled = TRUE; return event_query->signalled = TRUE;
case WINED3D_EVENT_QUERY_WAITING: case WINED3D_FENCE_WAITING:
return event_query->signalled = FALSE; 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); FIXME("(%p) Wrong thread, reporting GPU idle.\n", query);
return event_query->signalled = TRUE; return event_query->signalled = TRUE;
case WINED3D_EVENT_QUERY_ERROR: case WINED3D_FENCE_ERROR:
ERR("The GL event query failed.\n"); ERR("The GL event query failed.\n");
return event_query->signalled = TRUE; return event_query->signalled = TRUE;
...@@ -457,7 +509,7 @@ static BOOL wined3d_event_query_ops_issue(struct wined3d_query *query, DWORD fla ...@@ -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); 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; return TRUE;
} }
else if (flags & WINED3DISSUE_BEGIN) else if (flags & WINED3DISSUE_BEGIN)
...@@ -864,8 +916,7 @@ static void wined3d_event_query_ops_destroy(struct wined3d_query *query) ...@@ -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); struct wined3d_event_query *event_query = wined3d_event_query_from_query(query);
if (event_query->context) wined3d_fence_free(&event_query->fence);
context_free_event_query(event_query);
HeapFree(GetProcessHeap(), 0, event_query); HeapFree(GetProcessHeap(), 0, event_query);
} }
...@@ -882,19 +933,21 @@ static HRESULT wined3d_event_query_create(struct wined3d_device *device, ...@@ -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; const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
struct wined3d_event_query *object; struct wined3d_event_query *object;
HRESULT hr;
TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n", TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
device, type, parent, parent_ops, query); device, type, parent, parent_ops, query);
if (!wined3d_event_query_supported(gl_info)) 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"); WARN("Event queries not supported.\n");
HeapFree(GetProcessHeap(), 0, object);
return WINED3DERR_NOTAVAILABLE; return WINED3DERR_NOTAVAILABLE;
} }
if (!(object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object))))
return E_OUTOFMEMORY;
wined3d_query_init(&object->query, device, type, &object->signalled, wined3d_query_init(&object->query, device, type, &object->signalled,
sizeof(object->signalled), &event_query_ops, parent, parent_ops); sizeof(object->signalled), &event_query_ops, parent, parent_ops);
......
...@@ -1607,6 +1607,34 @@ enum fogsource { ...@@ -1607,6 +1607,34 @@ enum fogsource {
FOGSOURCE_COORD, 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 /* 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 * 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. */ * because D3D allows GetData() on a created query, but OpenGL doesn't. */
...@@ -1641,35 +1669,14 @@ struct wined3d_query ...@@ -1641,35 +1669,14 @@ struct wined3d_query
struct list poll_list_entry; struct list poll_list_entry;
}; };
union wined3d_gl_query_object
{
GLuint id;
GLsync sync;
};
struct wined3d_event_query struct wined3d_event_query
{ {
struct wined3d_query query; struct wined3d_query query;
struct list entry; struct wined3d_fence fence;
union wined3d_gl_query_object object;
struct wined3d_context *context;
BOOL signalled; 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_occlusion_query
{ {
struct wined3d_query query; struct wined3d_query query;
...@@ -1875,10 +1882,10 @@ struct wined3d_context ...@@ -1875,10 +1882,10 @@ struct wined3d_context
unsigned int free_occlusion_query_count; unsigned int free_occlusion_query_count;
struct list occlusion_queries; struct list occlusion_queries;
union wined3d_gl_query_object *free_event_queries; union wined3d_gl_fence_object *free_fences;
SIZE_T free_event_query_size; SIZE_T free_fence_size;
unsigned int free_event_query_count; unsigned int free_fence_count;
struct list event_queries; struct list fences;
GLuint *free_timestamp_queries; GLuint *free_timestamp_queries;
SIZE_T free_timestamp_query_size; SIZE_T free_timestamp_query_size;
...@@ -1898,8 +1905,8 @@ struct wined3d_context ...@@ -1898,8 +1905,8 @@ struct wined3d_context
struct wined3d_stream_info stream_info; struct wined3d_stream_info stream_info;
/* Fences for GL_APPLE_flush_buffer_range */ /* Fences for GL_APPLE_flush_buffer_range */
struct wined3d_event_query *buffer_queries[MAX_ATTRIBS]; struct wined3d_fence *buffer_fences[MAX_ATTRIBS];
unsigned int num_buffer_queries; unsigned int buffer_fence_count;
DWORD tex_unit_map[MAX_COMBINED_SAMPLERS]; DWORD tex_unit_map[MAX_COMBINED_SAMPLERS];
DWORD rev_tex_unit_map[MAX_GL_FRAGMENT_SAMPLERS + MAX_VERTEX_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 ...@@ -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_context *context_acquire(const struct wined3d_device *device,
struct wined3d_texture *texture, unsigned int sub_resource_idx) DECLSPEC_HIDDEN; struct wined3d_texture *texture, unsigned int sub_resource_idx) DECLSPEC_HIDDEN;
void context_alloc_event_query(struct wined3d_context *context, void context_alloc_fence(struct wined3d_context *context, struct wined3d_fence *fence) DECLSPEC_HIDDEN;
struct wined3d_event_query *query) DECLSPEC_HIDDEN;
void context_alloc_occlusion_query(struct wined3d_context *context, void context_alloc_occlusion_query(struct wined3d_context *context,
struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN; struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
void context_apply_blit_state(struct wined3d_context *context, const struct wined3d_device *device) 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 ...@@ -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; 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_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN;
void context_end_transform_feedback(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; void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;
struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN; struct wined3d_context *context_get_current(void) DECLSPEC_HIDDEN;
GLenum context_get_offscreen_gl_buffer(const struct wined3d_context *context) DECLSPEC_HIDDEN; GLenum context_get_offscreen_gl_buffer(const struct wined3d_context *context) DECLSPEC_HIDDEN;
...@@ -3532,7 +3538,7 @@ struct wined3d_buffer ...@@ -3532,7 +3538,7 @@ struct wined3d_buffer
struct wined3d_map_range *maps; struct wined3d_map_range *maps;
SIZE_T maps_size, modified_areas; SIZE_T maps_size, modified_areas;
struct wined3d_event_query *query; struct wined3d_fence *fence;
/* conversion stuff */ /* conversion stuff */
UINT decl_change_count, full_conversion_count; UINT decl_change_count, full_conversion_count;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment