[3/3] WineD3D: Implement per stream offsets

Mirek thunder.m at czela.net
Wed Jan 17 03:03:21 CST 2007


Hi, one or more nvidia sdk demos using instancing.

Mirek

Stefan Dösinger napsal(a):
> Stumbled uppon that while reading up instancing. This is a functionality 
> technically required for all d3d9 drivers. The new functionality is not 
> really tested because I have no app that really needs this, but it should not 
> cause issues with games not using stream offsets.
> 
> 
> ------------------------------------------------------------------------
> 
> From 6bd68813f3b05e525555ab2c28b331d838b50b92 Mon Sep 17 00:00:00 2001
> From: Stefan Doesinger <stefan at codeweavers.com>
> Date: Sat, 13 Jan 2007 15:09:16 +0100
> Subject: [PATCH] WineD3D: Implement per stream offsets
> 
> ---
>  dlls/wined3d/directx.c  |    2 +-
>  dlls/wined3d/drawprim.c |   47 +++++++++++++++++++++++++++++++++++++----------
>  dlls/wined3d/state.c    |   22 ++++++++++++----------
>  3 files changed, 50 insertions(+), 21 deletions(-)
> 
> diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
> index cbcbdc2..0e6f4bc 100644
> --- a/dlls/wined3d/directx.c
> +++ b/dlls/wined3d/directx.c
> @@ -2244,7 +2244,7 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter,
>         ------------------------------------------------ */
>      if (This->dxVersion > 8) {
>          /* d3d9.dll sets D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES here because StretchRects is implemented in d3d9 */
> -        *pCaps->DevCaps2                          = 0;
> +        *pCaps->DevCaps2                          = D3DDEVCAPS2_STREAMOFFSET;
>          /* TODO: VS3.0 needs at least D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET */
>          *pCaps->MaxNpatchTessellationLevel        = 0;
>          *pCaps->MasterAdapterOrdinal              = 0;
> diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
> index 400ffb5..fdc9843 100644
> --- a/dlls/wined3d/drawprim.c
> +++ b/dlls/wined3d/drawprim.c
> @@ -628,8 +628,12 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
>      DWORD diffuseColor = 0xFFFFFFFF;       /* Diffuse Color              */
>      DWORD specularColor = 0;               /* Specular Color             */
>      IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
> +    UINT *streamOffset = This->stateBlock->streamOffset;
>      LONG                       SkipnStrides = startVertex + This->stateBlock->loadBaseVertexIndex;
>  
> +    BYTE *texCoords[WINED3DDP_MAXTEXCOORD];
> +    BYTE *diffuse = NULL, *specular = NULL, *normal = NULL, *position = NULL;
> +
>      TRACE("Using slow vertex array code\n");
>  
>      /* Variable Initialization */
> @@ -638,6 +642,29 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
>          else pIdxBufL = (const long *) idxData;
>      }
>  
> +    /* Adding the stream offset once is cheaper than doing it every iteration. Do not modify the strided data, it is a pointer
> +     * to the strided Data in the device and might be needed intact on the next draw
> +     */
> +    for (textureNo = 0, texture_idx = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
> +        if(sd->u.s.texCoords[textureNo].lpData) {
> +            texCoords[textureNo] = sd->u.s.texCoords[textureNo].lpData + streamOffset[sd->u.s.texCoords[textureNo].streamNo];
> +        } else {
> +            texCoords[textureNo] = NULL;
> +        }
> +    }
> +    if(sd->u.s.diffuse.lpData) {
> +        diffuse = sd->u.s.diffuse.lpData + streamOffset[sd->u.s.diffuse.streamNo];
> +    }
> +    if(sd->u.s.specular.lpData) {
> +        specular = sd->u.s.specular.lpData + streamOffset[sd->u.s.specular.streamNo];
> +    }
> +    if(sd->u.s.normal.lpData) {
> +        normal = sd->u.s.normal.lpData + streamOffset[sd->u.s.normal.streamNo];
> +    }
> +    if(sd->u.s.position.lpData) {
> +        position = sd->u.s.position.lpData + streamOffset[sd->u.s.position.streamNo];
> +    }
> +
>      /* Start drawing in GL */
>      VTRACE(("glBegin(%x)\n", glPrimType));
>      glBegin(glPrimType);
> @@ -707,8 +734,8 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
>                      continue;
>                  }
>  
> -                ptrToCoords = (float *)(sd->u.s.texCoords[coordIdx].lpData + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
> -                if (sd->u.s.texCoords[coordIdx].lpData == NULL) {
> +                ptrToCoords = (float *)(texCoords[coordIdx] + (SkipnStrides * sd->u.s.texCoords[coordIdx].dwStride));
> +                if (texCoords[coordIdx] == NULL) {
>                      TRACE("tex: %d - Skipping tex coords, as no data supplied\n", textureNo);
>                      ++texture_idx;
>                      continue;
> @@ -796,8 +823,8 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
>          } /* End of textures */
>  
>          /* Diffuse -------------------------------- */
> -        if (sd->u.s.diffuse.lpData != NULL) {
> -            DWORD *ptrToCoords = (DWORD *)(sd->u.s.diffuse.lpData + (SkipnStrides * sd->u.s.diffuse.dwStride));
> +        if (diffuse) {
> +            DWORD *ptrToCoords = (DWORD *)(diffuse + (SkipnStrides * sd->u.s.diffuse.dwStride));
>              diffuseColor = ptrToCoords[0];
>              VTRACE(("diffuseColor=%lx\n", diffuseColor));
>  
> @@ -813,8 +840,8 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
>          }
>  
>          /* Specular ------------------------------- */
> -        if (sd->u.s.specular.lpData != NULL) {
> -            DWORD *ptrToCoords = (DWORD *)(sd->u.s.specular.lpData + (SkipnStrides * sd->u.s.specular.dwStride));
> +        if (specular) {
> +            DWORD *ptrToCoords = (DWORD *)(specular + (SkipnStrides * sd->u.s.specular.dwStride));
>              specularColor = ptrToCoords[0];
>              VTRACE(("specularColor=%lx\n", specularColor));
>  
> @@ -850,16 +877,16 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
>          }
>  
>          /* Normal -------------------------------- */
> -        if (sd->u.s.normal.lpData != NULL) {
> -            float *ptrToCoords = (float *)(sd->u.s.normal.lpData + (SkipnStrides * sd->u.s.normal.dwStride));
> +        if (normal != NULL) {
> +            float *ptrToCoords = (float *)(normal + (SkipnStrides * sd->u.s.normal.dwStride));
>  
>              VTRACE(("glNormal:nx,ny,nz=%f,%f,%f\n", ptrToCoords[0], ptrToCoords[1], ptrToCoords[2]));
>              glNormal3f(ptrToCoords[0], ptrToCoords[1], ptrToCoords[2]);
>          }
>  
>          /* Position -------------------------------- */
> -        if (sd->u.s.position.lpData != NULL) {
> -            float *ptrToCoords = (float *)(sd->u.s.position.lpData + (SkipnStrides * sd->u.s.position.dwStride));
> +        if (position) {
> +            float *ptrToCoords = (float *)(position + (SkipnStrides * sd->u.s.position.dwStride));
>              x = ptrToCoords[0];
>              y = ptrToCoords[1];
>              z = ptrToCoords[2];
> diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
> index bc2686f..8d74006 100644
> --- a/dlls/wined3d/state.c
> +++ b/dlls/wined3d/state.c
> @@ -2112,6 +2112,7 @@ static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
>  static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
>      GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
>      int i;
> +    UINT *offset = stateblock->streamOffset;
>  
>      for (i = 0; i < MAX_ATTRIBS; i++) {
>  
> @@ -2130,7 +2131,7 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi
>                          WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
>                          WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
>                          strided->u.input[i].dwStride,
> -                        strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride));
> +                        strided->u.input[i].lpData + stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride + offset[strided->u.input[i].streamNo]) );
>          GL_EXTCALL(glEnableVertexAttribArrayARB(i));
>     }
>  }
> @@ -2139,6 +2140,7 @@ static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDi
>  static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
>      unsigned int textureNo   = 0;
>      unsigned int texture_idx = 0;
> +    UINT *offset = stateblock->streamOffset;
>      GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
>  
>      TRACE("Using fast vertex array code\n");
> @@ -2155,7 +2157,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
>  #endif
>  
>              TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
> -                sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride);
> +                sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
>              /* FIXME("TODO\n");*/
>              /* Note dwType == float3 or float4 == 2 or 3 */
>  
> @@ -2170,7 +2172,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
>              VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
>                  WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
>                  sd->u.s.blendWeights.dwStride,
> -                sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride));
> +                sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
>  
>              if(curVBO != sd->u.s.blendWeights.VBO) {
>                  GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
> @@ -2182,7 +2184,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
>                  WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
>                  WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
>                  sd->u.s.blendWeights.dwStride,
> -                sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride);
> +                sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
>  
>              checkGLcall("glWeightPointerARB");
>  
> @@ -2320,12 +2322,12 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
>          if(sd->u.s.position.VBO == 0) {
>              glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
>                  WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
> -                sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride);
> +                sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
>          } else {
>              glVertexPointer(
>                  WINED3D_ATR_SIZE(sd->u.s.position.dwType),
>                  WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
> -                sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride);
> +                sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
>          }
>          checkGLcall("glVertexPointer(...)");
>          glEnableClientState(GL_VERTEX_ARRAY);
> @@ -2350,7 +2352,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
>          glNormalPointer(
>              WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
>              sd->u.s.normal.dwStride,
> -            sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride);
> +            sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
>          checkGLcall("glNormalPointer(...)");
>          glEnableClientState(GL_NORMAL_ARRAY);
>          checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
> @@ -2384,7 +2386,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
>          }
>          glColorPointer(4, GL_UNSIGNED_BYTE,
>                         sd->u.s.diffuse.dwStride,
> -                       sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride);
> +                       sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
>          checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
>          glEnableClientState(GL_COLOR_ARRAY);
>          checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
> @@ -2411,7 +2413,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
>              }
>              GL_EXTCALL(glSecondaryColorPointerEXT)(4, GL_UNSIGNED_BYTE,
>                                                     sd->u.s.specular.dwStride,
> -                                                   sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride);
> +                                                   sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
>              vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
>              glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
>              vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
> @@ -2476,7 +2478,7 @@ static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVerte
>                      WINED3D_ATR_SIZE(sd->u.s.texCoords[coordIdx].dwType),
>                      WINED3D_ATR_GLTYPE(sd->u.s.texCoords[coordIdx].dwType),
>                      sd->u.s.texCoords[coordIdx].dwStride,
> -                    sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride);
> +                    sd->u.s.texCoords[coordIdx].lpData + stateblock->loadBaseVertexIndex * sd->u.s.texCoords[coordIdx].dwStride + offset[sd->u.s.texCoords[coordIdx].streamNo]);
>                  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
>              }
>          } else if (!GL_SUPPORT(NV_REGISTER_COMBINERS)) {
> 
> 
> ------------------------------------------------------------------------
> 
> 



More information about the wine-devel mailing list