=?UTF-8?Q?J=C3=B3zef=20Kucia=20?=: wined3d: Explicitly track locations for buffers.

Alexandre Julliard julliard at winehq.org
Wed Oct 19 20:47:57 CDT 2016


Module: wine
Branch: master
Commit: 2a385e420a2bafd7ca868ae57428798bb941d0a2
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2a385e420a2bafd7ca868ae57428798bb941d0a2

Author: Józef Kucia <jkucia at codeweavers.com>
Date:   Sun Oct 16 21:46:48 2016 +0200

wined3d: Explicitly track locations for buffers.

Signed-off-by: Józef Kucia <jkucia at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/wined3d/buffer.c          | 79 ++++++++++++++++++++++++++++++++++++++----
 dlls/wined3d/device.c          |  1 +
 dlls/wined3d/wined3d_private.h |  3 ++
 3 files changed, 76 insertions(+), 7 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index b6338d1..c7f0d81 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -93,6 +93,46 @@ static BOOL buffer_is_fully_dirty(const struct wined3d_buffer *buffer)
             && !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. */
 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;
 
     if (This->flags & WINED3D_BUFFER_DOUBLEBUFFER)
+    {
         buffer_invalidate_bo_range(This, 0, 0);
+    }
     else
+    {
         wined3d_resource_free_sysmem(&This->resource);
+        wined3d_buffer_validate_location(This, WINED3D_LOCATION_BUFFER);
+        wined3d_buffer_invalidate_location(This, WINED3D_LOCATION_SYSMEM);
+    }
 
     return;
 
 fail:
     /* 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;
     delete_gl_buffer(This, gl_info);
     buffer_clear_dirty_areas(This);
@@ -509,6 +555,8 @@ BYTE *wined3d_buffer_load_sysmem(struct wined3d_buffer *buffer, struct wined3d_c
     checkGLcall("buffer download");
     buffer->flags |= WINED3D_BUFFER_DOUBLEBUFFER;
 
+    wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_SYSMEM);
+
     return buffer->resource.heap_memory;
 }
 
@@ -532,6 +580,7 @@ static void buffer_unload(struct wined3d_resource *resource)
             buffer->flags &= ~WINED3D_BUFFER_DOUBLEBUFFER;
         }
 
+        wined3d_buffer_invalidate_location(buffer, WINED3D_LOCATION_BUFFER);
         delete_gl_buffer(buffer, context->gl_info);
         buffer_clear_dirty_areas(buffer);
 
@@ -707,7 +756,7 @@ static void buffer_direct_upload(struct wined3d_buffer *This, struct wined3d_con
     }
     if (!map)
     {
-        ERR("Failed to map opengl buffer\n");
+        ERR("Failed to map OpenGL buffer.\n");
         return;
     }
 
@@ -732,6 +781,8 @@ static void buffer_direct_upload(struct wined3d_buffer *This, struct wined3d_con
     }
     GL_EXTCALL(glUnmapBuffer(This->buffer_type_hint));
     checkGLcall("glUnmapBuffer");
+
+    wined3d_buffer_validate_location(This, WINED3D_LOCATION_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);
+
+    wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_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)
     {
+        unsigned int dirty_offset = offset, dirty_size = size;
+
         /* DISCARD invalidates the entire buffer, regardless of the specified
          * offset and size. Some applications also depend on the entire buffer
          * being uploaded in that case. Two such applications are Port Royale
          * and Darkstar One. */
         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);
+        {
+            dirty_offset = 0;
+            dirty_size = 0;
+        }
 
-        if (!(buffer->flags & WINED3D_BUFFER_DOUBLEBUFFER))
+        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)
             {
                 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)
-        buffer_invalidate_bo_range(dst_buffer, dst_offset, size);
+        wined3d_buffer_invalidate_range(dst_buffer, WINED3D_LOCATION_BUFFER, dst_offset, size);
 
     context_release(context);
     return WINED3D_OK;
@@ -1300,6 +1364,7 @@ static HRESULT buffer_init(struct wined3d_buffer *buffer, struct wined3d_device
         return hr;
     }
     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,
             debug_d3dformat(buffer->resource.format->id), buffer->resource.heap_memory, buffer);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 89b781c..a611531 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3179,6 +3179,7 @@ HRESULT CDECL wined3d_device_process_vertices(struct wined3d_device *device,
         {
             GL_EXTCALL(glDeleteBuffers(1, &buffer->buffer_object));
             buffer->buffer_object = 0;
+            wined3d_buffer_invalidate_location(buffer, WINED3D_LOCATION_BUFFER);
         }
         if (e->data.addr)
             e->data.addr += e->stride * src_start_idx;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index c3152a2..45a24f1 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3163,6 +3163,7 @@ struct wined3d_buffer
 
     struct wined3d_map_range *maps;
     ULONG maps_size, modified_areas;
+    DWORD locations;
     struct wined3d_event_query *query;
 
     /* 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,
         struct wined3d_bo_address *data) 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,
         const struct wined3d_state *state) 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;
 HRESULT wined3d_buffer_upload_data(struct wined3d_buffer *buffer,
         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
 {




More information about the wine-cvs mailing list