From 88c471ea0b63c5cff33363d1f3ee44e88533bce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Sun, 21 Mar 2010 13:26:36 +0100 Subject: [PATCH 04/15] WineD3D: Implement manual buffer fencing --- dlls/wined3d/buffer.c | 69 ++++++++++++++++++++++++++++++++++++--- dlls/wined3d/device.c | 8 +++++ dlls/wined3d/drawprim.c | 5 +++ dlls/wined3d/query.c | 8 ++-- dlls/wined3d/wined3d_private.h | 9 +++++ 5 files changed, 89 insertions(+), 10 deletions(-) diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 1b1c4c2..68417ff 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -108,6 +108,11 @@ static void delete_gl_buffer(struct wined3d_buffer *This) LEAVE_GL(); This->buffer_object = 0; + if(This->query) + { + wined3d_event_query_destroy(This->query); + This->query = NULL; + } This->flags &= ~WINED3D_BUFFER_APPLESYNC; } @@ -774,23 +779,68 @@ static DWORD STDMETHODCALLTYPE buffer_GetPriority(IWineD3DBuffer *iface) return resource_get_priority((IWineD3DResource *)iface); } -/* The caller provides a context and GL locking and binds the buffer */ -static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags) +/* 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) { + enum wined3d_event_query_result ret; + /* No fencing needs to be done if the app promises not to overwrite * existing data */ if(flags & WINED3DLOCK_NOOVERWRITE) return; if(flags & WINED3DLOCK_DISCARD) { + ENTER_GL(); GL_EXTCALL(glBufferDataARB(This->buffer_type_hint, This->resource.size, NULL, This->buffer_object_usage)); checkGLcall("glBufferDataARB\n"); + LEAVE_GL(); return; } - /* Drop the unserialized updates for now */ - FIXME("Implement fences for unserialized buffers\n"); + if(!This->query) + { + HRESULT hr; + TRACE("Creating event query for buffer %p\n", This); + + hr = wined3d_event_query_init(gl_info, &This->query); + if(FAILED(hr)) + { + ERR("Failed to create an event query, dropping async buffer locks\n"); + goto drop_query; + } + /* Since we don't know about old draws a glFinish is needed once */ + wglFinish(); + return; + } + TRACE("Synchronizing buffer %p\n", This); + ret = wined3d_event_query_finish(This->query, This->resource.device); + switch(ret) + { + case WINED3D_EVENT_QUERY_NOT_STARTED: + case WINED3D_EVENT_QUERY_OK: + /* All done */ + return; + + case WINED3D_EVENT_QUERY_WRONG_THREAD: + WARN("Cannot synchronize buffer lock due to a thread conflict\n"); + goto drop_query; + + default: + ERR("wined3d_event_query_finish returned %u, dropping async buffer locks\n", ret); + goto drop_query; + } + +drop_query: + if(This->query) + { + wined3d_event_query_destroy(This->query); + This->query = NULL; + } + + wglFinish(); + ENTER_GL(); 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)"); + LEAVE_GL(); This->flags &= ~WINED3D_BUFFER_APPLESYNC; } @@ -826,7 +876,9 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined DWORD syncflags = 0; if (flags & WINED3D_BUFFER_DISCARD) syncflags |= WINED3DLOCK_DISCARD; if (flags & WINED3D_BUFFER_NOSYNC) syncflags |= WINED3DLOCK_NOOVERWRITE; - buffer_sync_apple(This, syncflags); + LEAVE_GL(); + buffer_sync_apple(This, syncflags, gl_info); + ENTER_GL(); } map = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_WRITE_ONLY_ARB)); checkGLcall("glMapBufferARB"); @@ -1216,7 +1268,12 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, } else { - if(This->flags & WINED3D_BUFFER_APPLESYNC) buffer_sync_apple(This, flags); + if(This->flags & WINED3D_BUFFER_APPLESYNC) + { + LEAVE_GL(); + buffer_sync_apple(This, flags, gl_info); + ENTER_GL(); + } This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB)); checkGLcall("glMapBufferARB"); } diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 5355f51..d48acf2 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -305,6 +305,7 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, } } + This->num_buffer_queries = 0; if (!This->stateBlock->streamIsUP) { WORD map = stream_info->use_map; @@ -314,6 +315,7 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, { struct wined3d_stream_info_element *element; struct wined3d_buffer *buffer; + struct wined3d_event_query *query; if (!(map & 1)) continue; @@ -327,6 +329,12 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, element->buffer_object = 0; element->data = buffer_get_sysmem(buffer) + (ptrdiff_t)element->data; } + + query = ((struct wined3d_buffer *) buffer)->query; + if(query) + { + This->buffer_queries[This->num_buffer_queries++] = query; + } } } } diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index da7aab4..201aa54 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -689,6 +689,11 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT /* Finished updating the screen, restore lock */ LEAVE_GL(); + for(i = 0; i < This->num_buffer_queries; i++) + { + wined3d_event_query_issue(This->buffer_queries[i], This); + } + wglFlush(); /* Flush to ensure ordering across contexts. */ context_release(context); diff --git a/dlls/wined3d/query.c b/dlls/wined3d/query.c index 0eb2544..59e385e 100644 --- a/dlls/wined3d/query.c +++ b/dlls/wined3d/query.c @@ -27,7 +27,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); #define GLINFO_LOCATION (*gl_info) -static HRESULT wined3d_event_query_init(const struct wined3d_gl_info *gl_info, struct wined3d_event_query **query) +HRESULT wined3d_event_query_init(const struct wined3d_gl_info *gl_info, struct wined3d_event_query **query) { struct wined3d_event_query *ret; *query = NULL; @@ -45,13 +45,13 @@ static HRESULT wined3d_event_query_init(const struct wined3d_gl_info *gl_info, s return WINED3D_OK; } -static void wined3d_event_query_destroy(struct wined3d_event_query *query) +void wined3d_event_query_destroy(struct wined3d_event_query *query) { if (query->context) context_free_event_query(query); HeapFree(GetProcessHeap(), 0, query); } -static enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) +enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) { struct wined3d_context *context; const struct wined3d_gl_info *gl_info; @@ -193,7 +193,7 @@ enum wined3d_event_query_result wined3d_event_query_finish(struct wined3d_event_ return ret; } -static void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) +void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) { const struct wined3d_gl_info *gl_info; struct wined3d_context *context; diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 66ea1e3..deee639 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1033,6 +1033,12 @@ enum wined3d_event_query_result WINED3D_EVENT_QUERY_ERROR }; +HRESULT wined3d_event_query_init(const struct wined3d_gl_info *gl_info, struct wined3d_event_query **query) DECLSPEC_HIDDEN; +void wined3d_event_query_destroy(struct wined3d_event_query *query) DECLSPEC_HIDDEN; +enum wined3d_event_query_result wined3d_event_query_test(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN; +enum wined3d_event_query_result wined3d_event_query_finish(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN; +void wined3d_event_query_issue(struct wined3d_event_query *query, IWineD3DDeviceImpl *device) DECLSPEC_HIDDEN; + struct wined3d_context { const struct wined3d_gl_info *gl_info; @@ -1695,6 +1701,8 @@ struct IWineD3DDeviceImpl /* Stream source management */ struct wined3d_stream_info strided_streams; const WineDirect3DVertexStridedData *up_strided; + struct wined3d_event_query *buffer_queries[MAX_ATTRIBS]; + unsigned int num_buffer_queries; /* Context management */ struct wined3d_context **contexts; @@ -2495,6 +2503,7 @@ struct wined3d_buffer LONG lock_count; struct wined3d_map_range *maps; ULONG maps_size, modified_areas; + struct wined3d_event_query *query; /* conversion stuff */ UINT decl_change_count, full_conversion_count; -- 1.6.4.4