[19/20] WineD3D: Do not try to read the vertex decl when the stateblock isn't finalized

Stefan Dösinger stefan at codeweavers.com
Sat Jan 6 11:41:43 CST 2007


An application can call PreLoad on vertex buffers at any time, and PreLoad 
reads the declaration from the device when it is called, so it might read an 
old declaration if the app changes the decl between the preload call and the 
draw. While it shouldn't cause rendering issues it can cause performance 
troubles if incorrect declaration changes are detected.

The new rules are:

* If PreLoad is called during a draw, and the buffer is bound, read the 
declaration and detect changes
* Otherwise reuse the decl stored in the buffer if it exists. PreLoad will be 
called before the buffer is really used again
* If no declaration exits, do nothing. PreLoad will be called again before the 
buffer is really used the first time.

The device->isInDraw flag might come handy for srgb texture handling too
-------------- next part --------------
From 07efe2ccdb46dd7c63c27123f46aaaaab06bc99f Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Sat, 6 Jan 2007 00:04:39 +0100
Subject: [PATCH] WineD3D: Do not try to read the vertex buffer declaration when the
stateblock is not finalized
---
 dlls/wined3d/drawprim.c        |    6 ++++++
 dlls/wined3d/vertexbuffer.c    |   15 ++++++++++++++-
 dlls/wined3d/wined3d_private.h |    1 +
 3 files changed, 21 insertions(+), 1 deletions(-)

diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 8319364..2f880fd 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1247,6 +1247,9 @@ void drawPrimitive(IWineD3DDevice *iface
     DWORD                         dirtyState, idx;
     BYTE                          shift;
 
+    /* Signals other modules that a drawing is in progress and the stateblock finalized */
+    This->isInDraw = TRUE;
+
     /* Invalidate the back buffer memory so LockRect will read it the next time */
     for(i = 0; i < IWineD3DDevice_GetNumberOfSwapChains(iface); i++) {
         IWineD3DDevice_GetSwapChain(iface, i, (IWineD3DSwapChain **) &swapchain);
@@ -1340,4 +1343,7 @@ #endif
         ++primCounter;
     }
 #endif
+
+    /* Control goes back to the device, stateblock values may change again */
+    This->isInDraw = FALSE;
 }
diff --git a/dlls/wined3d/vertexbuffer.c b/dlls/wined3d/vertexbuffer.c
index b89d922..181c244 100644
--- a/dlls/wined3d/vertexbuffer.c
+++ b/dlls/wined3d/vertexbuffer.c
@@ -258,7 +258,20 @@ static void     WINAPI IWineD3DVertexBuf
         return; /* Not doing any conversion */
     }
 
-    declChanged = IWineD3DVertexBufferImpl_FindDecl(This);
+    /* Reading the declaration makes only sense if the stateblock is finalized and the buffer bound to a stream */
+    if(This->resource.wineD3DDevice->isInDraw && This->Flags & VBFLAG_STREAM) {
+        declChanged = IWineD3DVertexBufferImpl_FindDecl(This);
+    } else if(This->Flags & VBFLAG_HASDESC) {
+        /* Reuse the declaration stored in the buffer. It will most likely not change, and if it does
+         * the stream source state handler will call PreLoad again and the change will be cought
+         */
+    } else {
+        /* Cannot get a declaration, and no declaration is stored in the buffer. It is pointless to preload
+         * now. When the buffer is used, PreLoad will be called by the stream source state handler and a valid
+         * declaration for the buffer can be found
+         */
+        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 much
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e8b60de..f50182a 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -588,6 +588,7 @@ #define                         NEEDS_DI
     BOOL                    isRecordingState;
     IWineD3DStateBlockImpl *stateBlock;
     IWineD3DStateBlockImpl *updateStateBlock;
+    BOOL                   isInDraw;
 
     /* Internal use fields  */
     WINED3DDEVICE_CREATION_PARAMETERS createParms;
-- 
1.4.2.4



More information about the wine-patches mailing list