Commit 6c53871d authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Implement unfenced updates of double buffered buffers.

parent 1691a6d7
...@@ -767,7 +767,7 @@ static DWORD STDMETHODCALLTYPE buffer_GetPriority(IWineD3DBuffer *iface) ...@@ -767,7 +767,7 @@ static DWORD STDMETHODCALLTYPE buffer_GetPriority(IWineD3DBuffer *iface)
} }
/* The caller provides a GL context */ /* The caller provides a GL context */
static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info) static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined3d_gl_info *gl_info, DWORD flags)
{ {
BYTE *map; BYTE *map;
UINT start = 0, len = 0; UINT start = 0, len = 0;
...@@ -779,6 +779,14 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined ...@@ -779,6 +779,14 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
{ {
GLbitfield mapflags; GLbitfield mapflags;
mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
if (flags & WINED3D_BUFFER_DISCARD)
{
mapflags |= GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
}
else if (flags & WINED3D_BUFFER_NOSYNC)
{
mapflags |= GL_MAP_UNSYNCHRONIZED_BIT;
}
map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0, map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
This->resource.size, mapflags)); This->resource.size, mapflags));
checkGLcall("glMapBufferRange"); checkGLcall("glMapBufferRange");
...@@ -828,8 +836,10 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) ...@@ -828,8 +836,10 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
BOOL decl_changed = FALSE; BOOL decl_changed = FALSE;
unsigned int i, j; unsigned int i, j;
BYTE *data; BYTE *data;
DWORD flags = This->flags & (WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
TRACE("iface %p\n", iface); TRACE("iface %p\n", iface);
This->flags &= ~(WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
...@@ -927,6 +937,10 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) ...@@ -927,6 +937,10 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
ERR("buffer_add_dirty_area failed, this is not expected\n"); ERR("buffer_add_dirty_area failed, this is not expected\n");
return; return;
} }
/* Avoid unfenced updates, we might overwrite more areas of the buffer than the application
* cleared for unsynchronized updates
*/
flags = 0;
} }
if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB) if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
...@@ -949,7 +963,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface) ...@@ -949,7 +963,7 @@ static void STDMETHODCALLTYPE buffer_PreLoad(IWineD3DBuffer *iface)
return; return;
} }
buffer_direct_upload(This, context->gl_info); buffer_direct_upload(This, context->gl_info, flags);
context_release(context); context_release(context);
return; return;
...@@ -1129,6 +1143,7 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, ...@@ -1129,6 +1143,7 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset,
{ {
struct wined3d_buffer *This = (struct wined3d_buffer *)iface; struct wined3d_buffer *This = (struct wined3d_buffer *)iface;
LONG count; LONG count;
BOOL dirty = buffer_is_dirty(This);
TRACE("iface %p, offset %u, size %u, data %p, flags %#x\n", iface, offset, size, data, flags); TRACE("iface %p, offset %u, size %u, data %p, flags %#x\n", iface, offset, size, data, flags);
...@@ -1140,36 +1155,58 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset, ...@@ -1140,36 +1155,58 @@ static HRESULT STDMETHODCALLTYPE buffer_Map(IWineD3DBuffer *iface, UINT offset,
count = InterlockedIncrement(&This->lock_count); count = InterlockedIncrement(&This->lock_count);
if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER) && This->buffer_object) if (This->buffer_object)
{ {
if(count == 1) if(!(This->flags & WINED3D_BUFFER_DOUBLEBUFFER))
{ {
IWineD3DDeviceImpl *device = This->resource.device; if(count == 1)
struct wined3d_context *context;
const struct wined3d_gl_info *gl_info;
if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
{ {
IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER); IWineD3DDeviceImpl *device = This->resource.device;
} struct wined3d_context *context;
const struct wined3d_gl_info *gl_info;
context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD); if(This->buffer_type_hint == GL_ELEMENT_ARRAY_BUFFER_ARB)
gl_info = context->gl_info; {
ENTER_GL(); IWineD3DDeviceImpl_MarkStateDirty(This->resource.device, STATE_INDEXBUFFER);
GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object)); }
if (gl_info->supported[ARB_MAP_BUFFER_RANGE]) context = context_acquire(device, NULL, CTXUSAGE_RESOURCELOAD);
gl_info = context->gl_info;
ENTER_GL();
GL_EXTCALL(glBindBufferARB(This->buffer_type_hint, This->buffer_object));
if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
{
GLbitfield mapflags = buffer_gl_map_flags(flags);
This->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
This->resource.size, mapflags));
}
else
{
This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB));
}
LEAVE_GL();
context_release(context);
}
}
else
{
if (dirty)
{ {
GLbitfield mapflags = buffer_gl_map_flags(flags); if (This->flags & WINED3D_BUFFER_NOSYNC && !(flags & WINED3DLOCK_NOOVERWRITE))
This->resource.allocatedMemory = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0, {
This->resource.size, mapflags)); This->flags &= ~WINED3D_BUFFER_NOSYNC;
}
} }
else else if(flags & WINED3DLOCK_NOOVERWRITE)
{ {
This->resource.allocatedMemory = GL_EXTCALL(glMapBufferARB(This->buffer_type_hint, GL_READ_WRITE_ARB)); This->flags |= WINED3D_BUFFER_NOSYNC;
}
if (flags & WINED3DLOCK_DISCARD)
{
This->flags |= WINED3D_BUFFER_DISCARD;
} }
LEAVE_GL();
context_release(context);
} }
} }
......
...@@ -2478,6 +2478,8 @@ struct wined3d_map_range ...@@ -2478,6 +2478,8 @@ struct wined3d_map_range
#define WINED3D_BUFFER_CREATEBO 0x04 /* Attempt to create a buffer object next PreLoad */ #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_DOUBLEBUFFER 0x08 /* Use a vbo and local allocated memory */
#define WINED3D_BUFFER_FLUSH 0x10 /* Manual unmap flushing */ #define WINED3D_BUFFER_FLUSH 0x10 /* Manual unmap flushing */
#define WINED3D_BUFFER_DISCARD 0x20 /* A DISCARD lock has occured since the last PreLoad */
#define WINED3D_BUFFER_NOSYNC 0x40 /* All locks since the last PreLoad had NOOVERWRITE set */
struct wined3d_buffer struct wined3d_buffer
{ {
......
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