[PATCH] wined3d: Do not use double-buffered dynamic buffers (try 2)

Stefan Dösinger stefan at codeweavers.com
Wed Feb 29 04:12:19 CST 2012


try 2: Invalidate the index buffer state as well, as the buffer might be
an index buffer.

Otherwise unmodified reesend after the discussion from yesterday. This
is for bugs 29079, 29897(suspected) and 30019.

To reiterate the points from the discussion from yesterday: This patch
is the only approach to those bugs that is within reach for Wine 1.4
and I also consider this patch a proper fix in the long run.

After Wine 1.4 we'll want to get rid of the reasons that force dynamic
buffers into double-buffer mode, by implementing proper
instancing(29079, 29897) and a vertex pipeline replacement(30019). After
this is done, we still need a fallback solution for cards that don't
support vertex shaders and/or instancing.

One alternative Henri suggested was uploading only parts of the buffer
referenced by draws. This has two drawbacks in my eyes:
1) It is too complicated for a fallback solution that will get little
test coverage.
2) I have doubts that it'll work. We have proper mapping ranges from
d3d8 and d3d9 apps, but the double-buffered mode with the extra copy
that it requires is still a lot slower than drawing from system memory.
(It is not obvious why this is the case, as system memory draws might
require one or more copy steps by the driver. It probably depends on how
the driver implements draws without VBOs.)

The other alternative was mapping the buffer for those fallback draws
instead of maintaining a system memory copy.
1) I have serious doubts that this would be faster, since reading back
buffers, especially dynamic buffers, is supposed to be slow. I'd expect
that the driver has to wait until the upload is finished before mapping
the buffer for reading.
2) An application might use one buffer for the per-instance stream and
the instanced data streams simultanously. In this case we'd have to map
and unmap the buffer for each instance, which is unlikely to improve
performance.
3) Pointers returned by glMapBuffer cannot be passed to other gl
commands. While we could dereference them manually and pass the values
to opengl, this would require modifications to drawStridedSlow that are
useless otherwise.

Option 3: After implementing a vertex pipeline replacement and proper
instancing eliminate the current codepaths. Ie, require
GL_ARB_instanced_arrays for shader model 3 support, and require the
vertex pipeline replacement for dynamic buffer support. This may be an
option, depending on hardware/driver support for those extensions. I'm
mainly worried about instanced_arrays on r500 cards(and probably geforce
5) and useable vertex shader emulated ffp vertex pipeline on r200 and
geforce 3/4 cards.
---
 dlls/wined3d/buffer.c |   52 +++++++++++++++++++++++++++++-------------------
 1 files changed, 31 insertions(+), 21 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 495fe2f..fc3f465 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -734,6 +734,26 @@ static void buffer_direct_upload(struct wined3d_buffer *This, const struct wined
 }
 
 /* Do not call while under the GL lock. */
+static void wined3d_buffer_drop_bo(struct wined3d_buffer *buffer)
+{
+    struct wined3d_device *device = buffer->resource.device;
+
+    buffer_unload(&buffer->resource);
+    buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
+
+    /* The stream source or index buffer state handler might have read
+     * the memory of the buffer already and got the memory in the vbo
+     * which is not valid any longer. Invalidate the stream source and
+     * index buffer states to force a reload. This happens only once
+     * per changed buffer and should occur rather rarely. */
+    if (buffer->bind_count)
+    {
+        device_invalidate_state(device, STATE_INDEXBUFFER);
+        device_invalidate_state(device, STATE_STREAMSRC);
+    }
+}
+
+/* Do not call while under the GL lock. */
 void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer)
 {
     DWORD flags = buffer->flags & (WINED3D_BUFFER_NOSYNC | WINED3D_BUFFER_DISCARD);
@@ -782,6 +802,12 @@ void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer)
             buffer->full_conversion_count = 0;
         return;
     }
+    if (buffer->resource.usage & WINED3DUSAGE_DYNAMIC)
+    {
+        FIXME("Dropping VBO for double-buffered dynamic buffer %p\n", buffer);
+        wined3d_buffer_drop_bo(buffer);
+        return;
+    }
 
     /* If applications change the declaration over and over, reconverting all the time is a huge
      * performance hit. So count the declaration changes and release the VBO if there are too many
@@ -792,20 +818,10 @@ void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer)
         ++buffer->decl_change_count;
         buffer->draw_count = 0;
 
-        if (buffer->decl_change_count > VB_MAXDECLCHANGES
-                || (buffer->conversion_map && (buffer->resource.usage & WINED3DUSAGE_DYNAMIC)))
+        if (buffer->decl_change_count > VB_MAXDECLCHANGES)
         {
-            FIXME("Too many declaration changes or converting dynamic buffer, stopping converting\n");
-
-            buffer_unload(&buffer->resource);
-            buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
-
-            /* The stream source state handler might have read the memory of
-             * the vertex buffer already and got the memory in the vbo which
-             * is not valid any longer. Dirtify the stream source to force a
-             * reload. This happens only once per changed vertexbuffer and
-             * should occur rather rarely. */
-            device_invalidate_state(device, STATE_STREAMSRC);
+            FIXME("Too many declaration changes, stopping converting\n");
+            wined3d_buffer_drop_bo(buffer);
             return;
         }
 
@@ -834,10 +850,7 @@ void CDECL wined3d_buffer_preload(struct wined3d_buffer *buffer)
             if (buffer->full_conversion_count > VB_MAXFULLCONVERSIONS)
             {
                 FIXME("Too many full buffer conversions, stopping converting.\n");
-                buffer_unload(&buffer->resource);
-                buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
-                if (buffer->bind_count)
-                    device_invalidate_state(device, STATE_STREAMSRC);
+                wined3d_buffer_drop_bo(buffer);
                 return;
             }
         }
@@ -1061,10 +1074,7 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN
                          * that returns unaligned pointers
                          */
                         TRACE("Dynamic buffer, dropping VBO\n");
-                        buffer_unload(&buffer->resource);
-                        buffer->flags &= ~WINED3D_BUFFER_CREATEBO;
-                        if (buffer->bind_count)
-                            device_invalidate_state(device, STATE_STREAMSRC);
+                        wined3d_buffer_drop_bo(buffer);
                     }
                     else
                     {
-- 
1.7.3.4




More information about the wine-patches mailing list