From 9d948a85c6a38a3e2ff48967643194fec04b1d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20D=C3=B6singer?= Date: Mon, 28 Dec 2009 00:38:40 +0100 Subject: [PATCH 04/13] WineD3D: Implement manual fencing with GL_APPLE_flush_buffer_range --- dlls/wined3d/buffer.c | 47 ++++++++++++++++++++++++++++++++++++++++ dlls/wined3d/device.c | 10 +++++++- dlls/wined3d/drawprim.c | 20 +++++++++++++++++ dlls/wined3d/wined3d_private.h | 5 ++++ 4 files changed, 81 insertions(+), 1 deletions(-) diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index f8135ac..729cd5e 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -97,10 +97,15 @@ static void delete_gl_buffer(struct wined3d_buffer *This) if(!This->buffer_object) return; ENTER_GL(); + if(This->flags & WINED3D_BUFFER_GLFINISH) wine_glFinish(); GL_EXTCALL(glDeleteBuffersARB(1, &This->buffer_object)); checkGLcall("glDeleteBuffersARB"); LEAVE_GL(); This->buffer_object = 0; + + if(This->query.context) context_free_event_query(&This->query); + This->query.context = NULL; + This->flags &= ~(WINED3D_BUFFER_APPLESYNC | WINED3D_BUFFER_GLFINISH); } /* Context activation is done by the caller. */ @@ -168,6 +173,13 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This) 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(This->resource.device->adapter->gl_info.supported[APPLE_FENCE]) + { + 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)"); + } } } @@ -1040,6 +1052,35 @@ static WINED3DRESOURCETYPE STDMETHODCALLTYPE buffer_GetType(IWineD3DBuffer *ifac /* IWineD3DBuffer methods */ +/* The caller provides GL context and locking */ +static inline void buffer_sync_apple(struct wined3d_buffer *This, struct wined3d_context *context, DWORD flags) +{ + /* No fencing needs to be done if the app promises not to override + * existing data */ + if(flags & WINED3DLOCK_NOOVERWRITE) return; + + if(!This->query.context) + { + /* Don't allocate - this is done during the draw. + * The idea is that locks usually can happen on any thread, because apps + * pass WINED3DLOCK_NOOVERRIDE, while the draw isn't that flexible + */ + } + else if(This->query.context != context || This->flags & WINED3D_BUFFER_GLFINISH) + { + FIXME("GL_APPLE_flush_buffer_range buffer used with different contexts\n"); + wine_glFinish(); + /* Should I switch the buffer's context ? */ + This->flags &= ~WINED3D_BUFFER_GLFINISH; + } + else + { + /* TODO: Test and implement D3DLOCK_DONOTWAIT */ + GL_EXTCALL(glFinishFenceAPPLE(This->query.id)); + checkGLcall("glFinishFenceAPPLE(This->query.id)"); + } +} + static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, UINT size, BYTE **data, DWORD flags) { struct wined3d_buffer *This = (struct wined3d_buffer *)iface; @@ -1066,6 +1107,12 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); ENTER_GL(); GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); + + if(This->flags & WINED3D_BUFFER_APPLESYNC) + { + buffer_sync_apple(This, context, flags); + } + 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..c34fe7e 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -686,6 +686,26 @@ void drawPrimitive(IWineD3DDevice *iface, UINT index_count, UINT StartIdx, UINT } else { drawStridedFast(iface, glPrimType, index_count, idxSize, idxData, StartIdx); } + + for(i = 0; i < This->num_buffer_fences; i++) + { + struct wined3d_buffer *cur = (struct wined3d_buffer *) This->buffer_fences[i]; + + if(!cur->query.context) + { + context_alloc_event_query(context, &cur->query); + } + + if(cur->query.context != context) + { + cur->flags |= WINED3D_BUFFER_GLFINISH; + } + else + { + GL_EXTCALL(glSetFenceAPPLE(cur->query.id)); + checkGLcall("glSetFenceAPPLE(cur->query.id)"); + } + } } /* Finished updating the screen, restore lock */ diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index de0bcdc..bb9a98c 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,8 @@ 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 */ +#define WINED3D_BUFFER_GLFINISH 0x40 /* Call glFinish before mapping this buffer */ struct wined3d_buffer { @@ -2387,6 +2391,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