wined3d: Explicitly track locations for buffers.

Signed-off-by: Józef Kucia <jkucia@codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Józef Kucia 2016-10-16 21:46:48 +02:00 committed by Alexandre Julliard
parent fc866d88f3
commit 2a385e420a
3 changed files with 77 additions and 8 deletions

View File

@ -93,6 +93,46 @@ static BOOL buffer_is_fully_dirty(const struct wined3d_buffer *buffer)
&& !buffer->maps->offset && buffer->maps->size == buffer->resource.size; && !buffer->maps->offset && buffer->maps->size == buffer->resource.size;
} }
void wined3d_buffer_validate_location(struct wined3d_buffer *buffer, DWORD location)
{
TRACE("buffer %p, location %s.\n", buffer, wined3d_debug_location(location));
if (location & WINED3D_LOCATION_BUFFER)
buffer_clear_dirty_areas(buffer);
buffer->locations |= location;
TRACE("New locations flags are %s.\n", wined3d_debug_location(buffer->locations));
}
static void wined3d_buffer_invalidate_range(struct wined3d_buffer *buffer, DWORD location,
unsigned int offset, unsigned int size)
{
TRACE("buffer %p, location %s, offset %u, size %u.\n",
buffer, wined3d_debug_location(location), offset, size);
if ((offset || size) && (location & ~WINED3D_LOCATION_BUFFER))
{
ERR("Range can be invalidated only for WINED3D_LOCATION_BUFFER.\n");
return;
}
if (location & WINED3D_LOCATION_BUFFER)
buffer_invalidate_bo_range(buffer, offset, size);
buffer->locations &= ~location;
TRACE("New locations flags are %s.\n", wined3d_debug_location(buffer->locations));
if (!buffer->locations)
ERR("Buffer %p does not have any up to date location.\n", buffer);
}
void wined3d_buffer_invalidate_location(struct wined3d_buffer *buffer, DWORD location)
{
wined3d_buffer_invalidate_range(buffer, location, 0, 0);
}
/* Context activation is done by the caller. */ /* Context activation is done by the caller. */
static void buffer_bind(struct wined3d_buffer *buffer, struct wined3d_context *context) static void buffer_bind(struct wined3d_buffer *buffer, struct wined3d_context *context)
{ {
@ -192,15 +232,21 @@ static void buffer_create_buffer_object(struct wined3d_buffer *This, struct wine
This->buffer_object_usage = gl_usage; This->buffer_object_usage = gl_usage;
if (This->flags & WINED3D_BUFFER_DOUBLEBUFFER) if (This->flags & WINED3D_BUFFER_DOUBLEBUFFER)
{
buffer_invalidate_bo_range(This, 0, 0); buffer_invalidate_bo_range(This, 0, 0);
}
else else
{
wined3d_resource_free_sysmem(&This->resource); wined3d_resource_free_sysmem(&This->resource);
wined3d_buffer_validate_location(This, WINED3D_LOCATION_BUFFER);
wined3d_buffer_invalidate_location(This, WINED3D_LOCATION_SYSMEM);
}
return; return;
fail: fail:
/* Clean up all VBO init, but continue because we can work without a VBO :-) */ /* Clean up all VBO init, but continue because we can work without a VBO :-) */
ERR("Failed to create a vertex buffer object. Continuing, but performance issues may occur\n"); ERR("Failed to create a vertex buffer object. Continuing, but performance issues may occur.\n");
This->flags &= ~WINED3D_BUFFER_USE_BO; This->flags &= ~WINED3D_BUFFER_USE_BO;
delete_gl_buffer(This, gl_info); delete_gl_buffer(This, gl_info);
buffer_clear_dirty_areas(This); buffer_clear_dirty_areas(This);
@ -509,6 +555,8 @@ BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_c
checkGLcall("buffer download"); checkGLcall("buffer download");
buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER; buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER;
wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_SYSMEM);
return buffer->resource.heap_memory; return buffer->resource.heap_memory;
} }
@ -532,6 +580,7 @@ static void buffer_unload(struct wined3d_resource *resource)
buffer->flags &= ~WINED3D_BUFFER_DOUBLEBUFFER; buffer->flags &= ~WINED3D_BUFFER_DOUBLEBUFFER;
} }
wined3d_buffer_invalidate_location(buffer, WINED3D_LOCATION_BUFFER);
delete_gl_buffer(buffer, context->gl_info); delete_gl_buffer(buffer, context->gl_info);
buffer_clear_dirty_areas(buffer); buffer_clear_dirty_areas(buffer);
@ -707,7 +756,7 @@ static void buffer_direct_upload(struct wined3d_buffer *This, struct wined3d_con
} }
if (!map) if (!map)
{ {
ERR("Failed to map opengl buffer\n"); ERR("Failed to map OpenGL buffer.\n");
return; return;
} }
@ -732,6 +781,8 @@ static void buffer_direct_upload(struct wined3d_buffer *This, struct wined3d_con
} }
GL_EXTCALL(glUnmapBuffer(This->buffer_type_hint)); GL_EXTCALL(glUnmapBuffer(This->buffer_type_hint));
checkGLcall("glUnmapBuffer"); checkGLcall("glUnmapBuffer");
wined3d_buffer_validate_location(This, WINED3D_LOCATION_BUFFER);
} }
void buffer_mark_used(struct wined3d_buffer *buffer) void buffer_mark_used(struct wined3d_buffer *buffer)
@ -924,6 +975,8 @@ void wined3d_buffer_load(struct wined3d_buffer *buffer, struct wined3d_context *
} }
HeapFree(GetProcessHeap(), 0, data); HeapFree(GetProcessHeap(), 0, data);
wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_BUFFER);
} }
struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer) struct wined3d_resource * CDECL wined3d_buffer_get_resource(struct wined3d_buffer *buffer)
@ -952,17 +1005,28 @@ static HRESULT wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UI
if (buffer->buffer_object) if (buffer->buffer_object)
{ {
unsigned int dirty_offset = offset, dirty_size = size;
/* DISCARD invalidates the entire buffer, regardless of the specified /* DISCARD invalidates the entire buffer, regardless of the specified
* offset and size. Some applications also depend on the entire buffer * offset and size. Some applications also depend on the entire buffer
* being uploaded in that case. Two such applications are Port Royale * being uploaded in that case. Two such applications are Port Royale
* and Darkstar One. */ * and Darkstar One. */
if (flags & WINED3D_MAP_DISCARD) if (flags & WINED3D_MAP_DISCARD)
buffer_invalidate_bo_range(buffer, 0, 0);
else if (!(flags & WINED3D_MAP_READONLY))
buffer_invalidate_bo_range(buffer, offset, size);
if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER))
{ {
dirty_offset = 0;
dirty_size = 0;
}
if (buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER)
{
if (!(flags & WINED3D_MAP_READONLY))
wined3d_buffer_invalidate_range(buffer, WINED3D_LOCATION_BUFFER, dirty_offset, dirty_size);
}
else
{
if (!(flags & WINED3D_MAP_READONLY))
buffer_invalidate_bo_range(buffer, dirty_offset, dirty_size);
if (count == 1) if (count == 1)
{ {
struct wined3d_device *device = buffer->resource.device; struct wined3d_device *device = buffer->resource.device;
@ -1171,7 +1235,7 @@ HRESULT wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_
} }
if (dst_buffer_mem) if (dst_buffer_mem)
buffer_invalidate_bo_range(dst_buffer, dst_offset, size); wined3d_buffer_invalidate_range(dst_buffer, WINED3D_LOCATION_BUFFER, dst_offset, size);
context_release(context); context_release(context);
return WINED3D_OK; return WINED3D_OK;
@ -1300,6 +1364,7 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device
return hr; return hr;
} }
buffer->buffer_type_hint = bind_hint; buffer->buffer_type_hint = bind_hint;
buffer->locations = WINED3D_LOCATION_SYSMEM;
TRACE("size %#x, usage %#x, format %s, memory @ %p, iface @ %p.\n", buffer->resource.size, buffer->resource.usage, TRACE("size %#x, usage %#x, format %s, memory @ %p, iface @ %p.\n", buffer->resource.size, buffer->resource.usage,
debug_d3dformat(buffer->resource.format->id), buffer->resource.heap_memory, buffer); debug_d3dformat(buffer->resource.format->id), buffer->resource.heap_memory, buffer);

View File

@ -3179,6 +3179,7 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device,
{ {
GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object)); GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object));
buffer->buffer_object = 0; buffer->buffer_object = 0;
wined3d_buffer_invalidate_location(buffer, WINED3D_LOCATION_BUFFER);
} }
if (e->data.addr) if (e->data.addr)
e->data.addr += e->stride * src_start_idx; e->data.addr += e->stride * src_start_idx;

View File

@ -3163,6 +3163,7 @@ struct wined3d_buffer
struct wined3d_map_range *maps; struct wined3d_map_range *maps;
ULONG maps_size, modified_areas; ULONG maps_size, modified_areas;
DWORD locations;
struct wined3d_event_query *query; struct wined3d_event_query *query;
/* conversion stuff */ /* conversion stuff */
@ -3181,6 +3182,7 @@ static inline struct wined3d_buffer *buffer_from_resource(struct wined3d_resourc
void buffer_get_memory(struct wined3d_buffer *buffer, struct wined3d_context *context, void buffer_get_memory(struct wined3d_buffer *buffer, struct wined3d_context *context,
struct wined3d_bo_address *data) DECLSPEC_HIDDEN; struct wined3d_bo_address *data) DECLSPEC_HIDDEN;
void buffer_mark_used(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; void buffer_mark_used(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN;
void wined3d_buffer_invalidate_location(struct wined3d_buffer *buffer, DWORD location) DECLSPEC_HIDDEN;
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) DECLSPEC_HIDDEN; const struct wined3d_state *state) DECLSPEC_HIDDEN;
BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) DECLSPEC_HIDDEN; BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_context *context) DECLSPEC_HIDDEN;
@ -3188,6 +3190,7 @@ HRESULT wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_
struct wined3d_buffer *src_buffer, unsigned int src_offset, unsigned int size) DECLSPEC_HIDDEN; struct wined3d_buffer *src_buffer, unsigned int src_offset, unsigned int size) DECLSPEC_HIDDEN;
HRESULT wined3d_buffer_upload_data(struct wined3d_buffer *buffer, HRESULT wined3d_buffer_upload_data(struct wined3d_buffer *buffer,
const struct wined3d_box *box, const void *data) DECLSPEC_HIDDEN; const struct wined3d_box *box, const void *data) DECLSPEC_HIDDEN;
void wined3d_buffer_validate_location(struct wined3d_buffer *buffer, DWORD location) DECLSPEC_HIDDEN;
struct wined3d_rendertarget_view struct wined3d_rendertarget_view
{ {