Stefan Dösinger : wined3d: Vertex buffers can use the declaration from the device.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Jan 8 14:44:24 CST 2007


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

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Sat Jan  6 18:31:43 2007 +0100

wined3d: Vertex buffers can use the declaration from the device.

---

 dlls/wined3d/drawprim.c     |   39 +++++++++++++++++++++++++++++++-
 dlls/wined3d/vertexbuffer.c |   51 ++++++++++++++++---------------------------
 2 files changed, 56 insertions(+), 34 deletions(-)

diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 3b14c4a..129c42e 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -219,6 +219,10 @@ void primitiveDeclarationConvertToStride
     WINED3DVERTEXELEMENT *element;
     DWORD stride;
     int reg;
+    char isPreLoaded[MAX_STREAMS];
+    DWORD preLoadStreams[MAX_STREAMS], numPreloadStreams = 0;
+
+    memset(isPreLoaded, 0, sizeof(isPreLoaded));
 
     /* Locate the vertex declaration */
     if (This->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration) {
@@ -249,7 +253,11 @@ void primitiveDeclarationConvertToStride
             if(fixup && *fixup) FIXME("Missing fixed and unfixed vertices, expect graphics glitches\n");
         } else {
             TRACE("Stream isn't up %d, %p\n", element->Stream, This->stateBlock->streamSource[element->Stream]);
-            IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[element->Stream]);
+            if(!isPreLoaded[element->Stream]) {
+                preLoadStreams[numPreloadStreams] = element->Stream;
+                numPreloadStreams++;
+                isPreLoaded[element->Stream] = 1;
+            }
             data    = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[element->Stream], 0, &streamVBO);
             if(fixup) {
                 if( streamVBO != 0) *fixup = TRUE;
@@ -287,6 +295,17 @@ void primitiveDeclarationConvertToStride
            }
         }
     };
+    /* Now call PreLoad on all the vertex buffers. In the very rare case
+     * that the buffers stopps converting PreLoad will dirtify the VDECL again.
+     * The vertex buffer can now use the strided structure in the device instead of finding its
+     * own again.
+     *
+     * NULL streams won't be recorded in the array, UP streams won't be either. A stream is only
+     * once in there.
+     */
+    for(i=0; i < numPreloadStreams; i++) {
+            IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[preLoadStreams[i]]);
+    }
 }
 
 void primitiveConvertFVFtoOffset(DWORD thisFVF, DWORD stride, BYTE *data, WineDirect3DVertexStridedData *strided, GLint streamVBO) {
@@ -413,6 +432,7 @@ void primitiveConvertToStridedData(IWine
     short         LoopThroughTo = 0;
     short         nStream;
     GLint         streamVBO = 0;
+    DWORD preLoadStreams[MAX_STREAMS], numPreloadStreams = 0;
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
 
@@ -443,7 +463,11 @@ void primitiveConvertToStridedData(IWine
                 streamVBO = 0;
                 data    = (BYTE *)This->stateBlock->streamSource[nStream];
             } else {
-                IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[nStream]);
+                /* The for loop should iterate through here only once per stream, so we don't need magic to prevent double loading
+                 * buffers
+                 */
+                preLoadStreams[numPreloadStreams] = nStream;
+                numPreloadStreams++;
                 /* GetMemory binds the VBO */
                 data = IWineD3DVertexBufferImpl_GetMemory(This->stateBlock->streamSource[nStream], 0, &streamVBO);
                 if(fixup) {
@@ -462,6 +486,17 @@ void primitiveConvertToStridedData(IWine
         /* Now convert the stream into pointers */
         primitiveConvertFVFtoOffset(thisFVF, stride, data, strided, streamVBO);
     }
+    /* Now call PreLoad on all the vertex buffers. In the very rare case
+     * that the buffers stopps converting PreLoad will dirtify the VDECL again.
+     * The vertex buffer can now use the strided structure in the device instead of finding its
+     * own again.
+     *
+     * NULL streams won't be recorded in the array, UP streams won't be either. A stream is only
+     * once in there.
+     */
+    for(nStream=0; nStream < numPreloadStreams; nStream++) {
+            IWineD3DVertexBuffer_PreLoad(This->stateBlock->streamSource[preLoadStreams[nStream]]);
+    }
 }
 
 #if 0 /* TODO: Software Shaders */
diff --git a/dlls/wined3d/vertexbuffer.c b/dlls/wined3d/vertexbuffer.c
index 2f8a4f7..b89d922 100644
--- a/dlls/wined3d/vertexbuffer.c
+++ b/dlls/wined3d/vertexbuffer.c
@@ -164,7 +164,6 @@ inline BOOL WINAPI IWineD3DVertexBufferI
 {
     WineDirect3DVertexStridedData strided;
     IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
-    BOOL ret;
 
     memset(&strided, 0, sizeof(strided));
     /* There are certain vertex data types that need to be fixed up. The Vertex Buffers FVF doesn't
@@ -191,38 +190,18 @@ inline BOOL WINAPI IWineD3DVertexBufferI
      *  FALSE: otherwise
      */
 
-    if(device->stateBlock->vertexShader != NULL && wined3d_settings.vs_mode != VS_NONE 
-       &&((IWineD3DVertexShaderImpl *)device->stateBlock->vertexShader)->baseShader.function != NULL
-       && GL_SUPPORT(ARB_VERTEX_PROGRAM)) {
-        /* Case 1: Vertex Shader: No conversion */
-        TRACE("Vertex Shader, no conversion needed\n");
-    } else if(device->stateBlock->vertexDecl || device->stateBlock->vertexShader) {
-        /* Case 2: Vertex Declaration */
-        TRACE("Using vertex declaration\n");
-
-        This->Flags |= VBFLAG_LOAD;
-        primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
-                FALSE,
-                &strided,
-                &ret /* buffer contains fixed data, ignored here */);
-        This->Flags &= ~VBFLAG_LOAD;
-
+    if(device->stateBlock->vertexShader && ((IWineD3DVertexShaderImpl *) device->stateBlock->vertexShader)->baseShader.function) {
+        /* Assume no conversion */
+        memset(&strided, 0, sizeof(strided));
     } else {
-        /* Case 3: FVF */
-        if(!(This->Flags & VBFLAG_STREAM) ) {
-            TRACE("No vertex decl used and buffer is not bound to a stream\n");
-            /* No reload needed */
-            return FALSE;
-        } else {
-            This->Flags |= VBFLAG_LOAD;
-            primitiveConvertFVFtoOffset(device->stateBlock->fvf,
-                                        device->stateBlock->streamStride[This->stream],
-                                        NULL,
-                                        &strided,
-                                        This->vbo);
-            This->Flags &= ~VBFLAG_LOAD;
-            /* Data can only come from this buffer */
-        }
+        /* we need a copy because we modify some params */
+        memcpy(&strided, &device->strided_streams, sizeof(strided));
+
+        /* Filter out data that does not come from this VBO */
+        if(strided.u.s.position.VBO != This->vbo)    memset(&strided.u.s.position, 0, sizeof(strided.u.s.position));
+        if(strided.u.s.diffuse.VBO != This->vbo)     memset(&strided.u.s.diffuse, 0, sizeof(strided.u.s.diffuse));
+        if(strided.u.s.specular.VBO != This->vbo)    memset(&strided.u.s.specular, 0, sizeof(strided.u.s.specular));
+        if(strided.u.s.position2.VBO != This->vbo)   memset(&strided.u.s.position2, 0, sizeof(strided.u.s.position2));
     }
 
     /* Filter out data that does not come from this VBO */
@@ -297,6 +276,14 @@ static void     WINAPI IWineD3DVertexBuf
                 checkGLcall("glDeleteBuffersARB");
                 LEAVE_GL();
                 This->vbo = 0;
+
+                /* 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
+                 */
+                IWineD3DDeviceImpl_MarkStateDirty(This->resource.wineD3DDevice, STATE_STREAMSRC);
+
                 return;
             }
             /* Otherwise do not bother to release the VBO. If we're doing direct locking now,




More information about the wine-cvs mailing list