From 333dbe266f5563614638d0d0511ea01697f0e45e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Tue, 5 Jan 2010 16:14:49 +0100 Subject: [PATCH 5/6] WineD3D: Implement manual fencing with GL_APPLE_flush_buffer_range --- dlls/wined3d/buffer.c | 37 +++++++++++++++++++++++++++++++++++++ dlls/wined3d/device.c | 10 +++++++++- dlls/wined3d/drawprim.c | 18 ++++++++++++++++++ dlls/wined3d/wined3d_private.h | 4 ++++ 4 files changed, 68 insertions(+), 1 deletions(-) diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index f8135ac..905c140 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -101,6 +101,10 @@ static void delete_gl_buffer(struct wined3d_buffer *This) checkGLcall("glDeleteBuffersARB"); LEAVE_GL(); This->buffer_object = 0; + + if(This->query) IWineD3DQuery_Release(This->query); + This->query = NULL; + This->flags &= ~WINED3D_BUFFER_APPLESYNC; } /* Context activation is done by the caller. */ @@ -165,9 +169,18 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This) if(gl_info->supported[APPLE_FLUSH_BUFFER_RANGE]) { + IWineD3DDevice *device = (IWineD3DDevice *) This->resource.device; + GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)); checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE)"); This->flags |= WINED3D_BUFFER_FLUSH; + + if(SUCCEEDED(IWineD3DDevice_CreateQuery(device, WINED3DQUERYTYPE_EVENT, NULL, NULL))) + { + This->flags |= WINED3D_BUFFER_APPLESYNC; + GL_EXTCALL(glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)); + checkGLcall("glBufferParameteriAPPLE(This->buffer_type_hint, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE)"); + } } } @@ -1039,6 +1052,27 @@ static WINED3DRESOURCETYPE STDMETHODCALLTYPE buffer_GetType(IWineD3DBuffer *ifac } /* IWineD3DBuffer methods */ +static void buffer_sync_apple(struct wined3d_buffer *This, DWORD flags) +{ + HRESULT hr; + + /* No fencing needs to be done if the app promises not to override + * existing data */ + if(flags & WINED3DLOCK_NOOVERWRITE) return; + + if(!This->query) return; /* No draw yet */ + do + { + hr = IWineD3DQuery_GetData(This->query, NULL, 0, 0); + if(FAILED(hr)) + { + ERR("IWineD3DQuery_GetData failed, calling glFinish()\n"); + wglFinish(); + break; + } + } + while(hr != S_OK); +} static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, UINT size, BYTE **data, DWORD flags) { @@ -1063,9 +1097,12 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER); } + if(This->flags & WINED3D_BUFFER_APPLESYNC) buffer_sync_apple(This, flags); + context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); + This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB)); LEAVE_GL(); context_release(context); diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 34495d3..94d9532 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -314,10 +314,18 @@ void device_stream_info_from_declaration(IWineD3DDeviceImpl *This, * * NULL streams won't be recorded in the array, UP streams won't be either. A stream is only * once in there. */ + This->num_buffer_fences = 0; for (i = 0; i < stream_count; ++i) { IWineD3DBuffer *vb = This->stateBlock->streamSource[streams[i]]; - if (vb) IWineD3DBuffer_PreLoad(vb); + if (vb) + { + IWineD3DBuffer_PreLoad(vb); + if(((struct wined3d_buffer *) vb)->flags & WINED3D_BUFFER_APPLESYNC) + { + This->buffer_fences[This->num_buffer_fences++] = vb; + } + } } } diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index dbeb799..160b73c 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -692,6 +692,24 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT LEAVE_GL(); context_release(context); + for(i = 0; i < This->num_buffer_fences; i++) + { + struct wined3d_buffer *cur = (struct wined3d_buffer *) This->buffer_fences[i]; + + if(!cur->query) + { + HRESULT hr; + hr = IWineD3DDevice_CreateQuery(iface, WINED3DQUERYTYPE_EVENT, &cur->query, NULL); + if(FAILED(hr)) + { + ERR("Creating an event query for the buffer failed\n"); + continue; + } + } + + IWineD3DQuery_Issue(cur->query, WINED3DISSUE_END); + } + TRACE("Done all gl drawing\n"); /* Diagnostics */ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index de0bcdc..e4f0374 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1585,6 +1585,8 @@ struct IWineD3DDeviceImpl /* Stream source management */ struct wined3d_stream_info strided_streams; const WineDirect3DVertexStridedData *up_strided; + IWineD3DBuffer *buffer_fences[MAX_ATTRIBS]; + unsigned int num_buffer_fences; /* Context management */ struct wined3d_context **contexts; @@ -2369,6 +2371,7 @@ struct wined3d_map_range #define WINED3D_BUFFER_CREATEBO 0x04 /* Attempt to create a buffer object next PreLoad */ #define WINED3D_BUFFER_DOUBLEBUFFER 0x08 /* Use a vbo and local allocated memory */ #define WINED3D_BUFFER_FLUSH 0x10 /* Manual unmap flushing */ +#define WINED3D_BUFFER_APPLESYNC 0x20 /* Using sync as in GL_APPLE_flush_buffer_range */ struct wined3d_buffer { @@ -2387,6 +2390,7 @@ struct wined3d_buffer LONG lock_count; struct wined3d_map_range *maps; ULONG maps_size, modified_areas; + IWineD3DQuery *query; /* conversion stuff */ UINT decl_change_count, full_conversion_count; -- 1.6.4.4