wined3d: Just use glBufferSubData() in buffer_direct_upload().

It might seem like a good idea to try to use glMapBufferRange() in
buffer_direct_upload(), but it really isn't. The interesting cases for
glMapBufferRange() are GL_MAP_INVALIDATE_BUFFER_BIT or
GL_MAP_UNSYNCHRONIZED_BIT, but the only way for those to be set here
would be for the buffer to be mapped with WINED3D_MAP_DISCARD or
WINED3D_MAP_NOOVERWRITE before the buffer object was created. In that
case the GPU is obviously not using the buffer object, so
glMapBufferRange() doesn't help. On the other hand, if the buffer is
currently in use by the application and neither WINED3D_MAP_DISCARD nor
WINED3D_MAP_NOOVERWRITE is set, glMapBufferRange() would need to wait
for the GPU to finish using the buffer object, while glBufferSubData()
may decide not to.

Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Henri Verbeet 2017-01-27 11:36:31 +01:00 committed by Alexandre Julliard
parent 542998ee24
commit 602a23a60a
1 changed files with 6 additions and 61 deletions

View File

@ -33,9 +33,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d);
#define WINED3D_BUFFER_USE_BO 0x02 /* Use a buffer object for this buffer. */ #define WINED3D_BUFFER_USE_BO 0x02 /* Use a buffer object for this buffer. */
#define WINED3D_BUFFER_DOUBLEBUFFER 0x04 /* Keep both a buffer object and a system memory copy for this buffer. */ #define WINED3D_BUFFER_DOUBLEBUFFER 0x04 /* Keep both a buffer object and a system memory copy for this buffer. */
#define WINED3D_BUFFER_DISCARD 0x08 /* A DISCARD lock has occurred since the last preload. */ #define WINED3D_BUFFER_DISCARD 0x08 /* A DISCARD lock has occurred since the last preload. */
#define WINED3D_BUFFER_SYNC 0x10 /* There has been at least one synchronized map since the last preload. */ #define WINED3D_BUFFER_APPLESYNC 0x10 /* Using sync as in GL_APPLE_flush_buffer_range. */
#define WINED3D_BUFFER_MAP 0x20 /* There has been at least one map since the last preload. */
#define WINED3D_BUFFER_APPLESYNC 0x40 /* Using sync as in GL_APPLE_flush_buffer_range. */
#define VB_MAXDECLCHANGES 100 /* After that number of decl changes we stop converting */ #define VB_MAXDECLCHANGES 100 /* After that number of decl changes we stop converting */
#define VB_RESETDECLCHANGE 1000 /* Reset the decl changecount after that number of draws */ #define VB_RESETDECLCHANGE 1000 /* Reset the decl changecount after that number of draws */
@ -807,44 +805,12 @@ drop_query:
} }
/* The caller provides a GL context */ /* The caller provides a GL context */
static void buffer_direct_upload(struct wined3d_buffer *This, struct wined3d_context *context, DWORD flags) static void buffer_direct_upload(struct wined3d_buffer *This, struct wined3d_context *context)
{ {
const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_gl_info *gl_info = context->gl_info;
unsigned int start, len; unsigned int start, len;
BYTE *map;
buffer_bind(This, context); buffer_bind(This, context);
if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
{
GLbitfield mapflags;
mapflags = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
if (flags & WINED3D_BUFFER_DISCARD)
mapflags |= GL_MAP_INVALIDATE_BUFFER_BIT;
else if (flags & WINED3D_BUFFER_MAP && !(flags & WINED3D_BUFFER_SYNC))
mapflags |= GL_MAP_UNSYNCHRONIZED_BIT;
map = GL_EXTCALL(glMapBufferRange(This->buffer_type_hint, 0,
This->resource.size, mapflags));
checkGLcall("glMapBufferRange");
}
else
{
if (This->flags & WINED3D_BUFFER_APPLESYNC)
{
DWORD syncflags = 0;
if (flags & WINED3D_BUFFER_DISCARD)
syncflags |= WINED3D_MAP_DISCARD;
else if (flags & WINED3D_BUFFER_MAP && !(flags & WINED3D_BUFFER_SYNC))
syncflags |= WINED3D_MAP_NOOVERWRITE;
buffer_sync_apple(This, syncflags, gl_info);
}
map = GL_EXTCALL(glMapBuffer(This->buffer_type_hint, GL_WRITE_ONLY));
checkGLcall("glMapBuffer");
}
if (!map)
{
ERR("Failed to map OpenGL buffer.\n");
return;
}
while (This->modified_areas) while (This->modified_areas)
{ {
@ -852,21 +818,9 @@ static void buffer_direct_upload(struct wined3d_buffer *This, struct wined3d_con
start = This->maps[This->modified_areas].offset; start = This->maps[This->modified_areas].offset;
len = This->maps[This->modified_areas].size; len = This->maps[This->modified_areas].size;
memcpy(map + start, (BYTE *)This->resource.heap_memory + start, len); GL_EXTCALL(glBufferSubData(This->buffer_type_hint, start, len, (BYTE *)This->resource.heap_memory + start));
checkGLcall("glBufferSubData");
if (gl_info->supported[ARB_MAP_BUFFER_RANGE])
{
GL_EXTCALL(glFlushMappedBufferRange(This->buffer_type_hint, start, len));
checkGLcall("glFlushMappedBufferRange");
}
else if (This->flags & WINED3D_BUFFER_APPLESYNC)
{
GL_EXTCALL(glFlushMappedBufferRangeAPPLE(This->buffer_type_hint, start, len));
checkGLcall("glFlushMappedBufferRangeAPPLE");
}
} }
GL_EXTCALL(glUnmapBuffer(This->buffer_type_hint));
checkGLcall("glUnmapBuffer");
wined3d_buffer_validate_location(This, WINED3D_LOCATION_BUFFER); wined3d_buffer_validate_location(This, WINED3D_LOCATION_BUFFER);
} }
@ -931,14 +885,13 @@ static void buffer_conversion_upload(struct wined3d_buffer *buffer, struct wined
void buffer_mark_used(struct wined3d_buffer *buffer) void buffer_mark_used(struct wined3d_buffer *buffer)
{ {
buffer->flags &= ~(WINED3D_BUFFER_MAP | WINED3D_BUFFER_SYNC | WINED3D_BUFFER_DISCARD); buffer->flags &= ~WINED3D_BUFFER_DISCARD;
} }
/* Context activation is done by the caller. */ /* Context activation is done by the caller. */
void wined3d_buffer_load(struct wined3d_buffer *buffer, struct wined3d_context *context, void wined3d_buffer_load(struct wined3d_buffer *buffer, struct wined3d_context *context,
const struct wined3d_state *state) const struct wined3d_state *state)
{ {
DWORD flags = buffer->flags & (WINED3D_BUFFER_MAP | WINED3D_BUFFER_SYNC | WINED3D_BUFFER_DISCARD);
const struct wined3d_gl_info *gl_info = context->gl_info; const struct wined3d_gl_info *gl_info = context->gl_info;
BOOL decl_changed = FALSE; BOOL decl_changed = FALSE;
@ -1009,11 +962,6 @@ void wined3d_buffer_load(struct wined3d_buffer *buffer, struct wined3d_context *
/* The declaration changed, reload the whole buffer. */ /* The declaration changed, reload the whole buffer. */
WARN("Reloading buffer because of a vertex declaration change.\n"); WARN("Reloading buffer because of a vertex declaration change.\n");
buffer_invalidate_bo_range(buffer, 0, 0); buffer_invalidate_bo_range(buffer, 0, 0);
/* Avoid unfenced updates, we might overwrite more areas of the buffer than the application
* cleared for unsynchronized updates.
*/
flags = 0;
} }
else else
{ {
@ -1054,7 +1002,7 @@ void wined3d_buffer_load(struct wined3d_buffer *buffer, struct wined3d_context *
if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER)) if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER))
return; return;
buffer_direct_upload(buffer, context, flags); buffer_direct_upload(buffer, context);
} }
else else
{ {
@ -1173,11 +1121,8 @@ static HRESULT wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UI
} }
} }
buffer->flags |= WINED3D_BUFFER_MAP;
if (flags & WINED3D_MAP_DISCARD) if (flags & WINED3D_MAP_DISCARD)
buffer->flags |= WINED3D_BUFFER_DISCARD; buffer->flags |= WINED3D_BUFFER_DISCARD;
else if (!(flags & WINED3D_MAP_NOOVERWRITE))
buffer->flags |= WINED3D_BUFFER_SYNC;
} }
base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.heap_memory; base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.heap_memory;