wined3d: Simplify handling of swizzled attributes.

Henri Verbeet hverbeet at codeweavers.com
Thu Jan 8 03:19:17 CST 2009


This should also be a little bit faster.
---
 dlls/wined3d/arb_program_shader.c |    3 +-
 dlls/wined3d/drawprim.c           |    3 +
 dlls/wined3d/glsl_shader.c        |    3 +-
 dlls/wined3d/vertexdeclaration.c  |   36 +-------
 dlls/wined3d/vertexshader.c       |  166 +-----------------------------------
 dlls/wined3d/wined3d_private.h    |   17 +----
 include/wine/wined3d.idl          |    2 +
 7 files changed, 18 insertions(+), 212 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index efb3cb8..cd6ba29 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -510,8 +510,7 @@ static void vshader_program_add_param(const SHADER_OPCODE_ARG *arg, const DWORD
     break;
   case WINED3DSPR_INPUT:
 
-    if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
-        is_color = TRUE;
+    if (This->swizzle_map & (1 << reg)) is_color = TRUE;
 
     sprintf(tmpReg, "vertex.attrib[%u]", reg);
     strcat(hwLine, tmpReg);
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 7d87ca1..70ba80b 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -158,6 +158,7 @@ void primitiveDeclarationConvertToStridedData(
     }
 
     /* Translate the declaration into strided data */
+    strided->swizzle_map = 0;
     for (i = 0 ; i < vertexDeclaration->declarationWNumElements - 1; ++i) {
         GLint streamVBO = 0;
         BOOL stride_used;
@@ -234,6 +235,8 @@ void primitiveDeclarationConvertToStridedData(
                 strided->u.input[idx].dwStride = stride;
                 strided->u.input[idx].VBO = streamVBO;
                 strided->u.input[idx].streamNo = element->Stream;
+                if (element->Type == WINED3DDECLTYPE_D3DCOLOR) strided->swizzle_map |= 1 << idx;
+                strided->use_map |= 1 << idx;
             }
         }
     }
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index eb169e0..0acdcad 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -1030,8 +1030,7 @@ static void shader_glsl_get_register_name(const DWORD param, const DWORD addr_to
                     strcpy(tmpStr, "gl_SecondaryColor");
             }
         } else {
-            if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
-               *is_color = TRUE;
+            if (((IWineD3DVertexShaderImpl *)This)->swizzle_map & (1 << reg)) *is_color = TRUE;
             sprintf(tmpStr, "attrib%u", reg);
         } 
         break;
diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c
index 7fc711b..f63e2e7 100644
--- a/dlls/wined3d/vertexdeclaration.c
+++ b/dlls/wined3d/vertexdeclaration.c
@@ -207,7 +207,7 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVerte
         const WINED3DVERTEXELEMENT *elements, UINT element_count) {
     IWineD3DVertexDeclarationImpl *This = (IWineD3DVertexDeclarationImpl *)iface;
     HRESULT hr = WINED3D_OK;
-    int i, j;
+    int i;
     char isPreLoaded[MAX_STREAMS];
 
     TRACE("(%p) : d3d version %d\n", This, ((IWineD3DImpl *)This->wineD3DDevice->wineD3D)->dxVersion);
@@ -263,39 +263,13 @@ static HRESULT WINAPI IWineD3DVertexDeclarationImpl_SetDeclaration(IWineD3DVerte
             isPreLoaded[This->pDeclarationWine[i].Stream] = 1;
         }
 
-        /* Create a sorted array containing the attribute declarations that are of type
-         * D3DCOLOR. D3DCOLOR requires swizzling of the r and b component, and if the
-         * declaration of one attribute changes the vertex shader needs recompilation.
-         * Having a sorted array of the attributes allows efficient comparison of the
-         * declaration against a shader
-         */
-        if(This->pDeclarationWine[i].Type == WINED3DDECLTYPE_D3DCOLOR) {
-            for(j = 0; j < This->num_swizzled_attribs; j++) {
-                if(This->swizzled_attribs[j].usage >  This->pDeclarationWine[i].Usage ||
-                  (This->swizzled_attribs[j].usage == This->pDeclarationWine[i].Usage &&
-                   This->swizzled_attribs[j].idx   >   This->pDeclarationWine[i].UsageIndex)) {
-                    memmove(&This->swizzled_attribs[j + 1], &This->swizzled_attribs[j],
-                             sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j + 1)));
-                    break;
-                }
-            }
-
-            This->swizzled_attribs[j].usage = This->pDeclarationWine[i].Usage;
-            This->swizzled_attribs[j].idx = This->pDeclarationWine[i].UsageIndex;
-            This->num_swizzled_attribs++;
-        } else if(This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_2 ||
-                  This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_4) {
-            if(!GL_SUPPORT(NV_HALF_FLOAT)) {
-                This->half_float_conv_needed = TRUE;
-            }
+        if (This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_2
+                || This->pDeclarationWine[i].Type == WINED3DDECLTYPE_FLOAT16_4)
+        {
+            if (!GL_SUPPORT(NV_HALF_FLOAT)) This->half_float_conv_needed = TRUE;
         }
     }
 
-    TRACE("Swizzled attributes found:\n");
-    for(i = 0; i < This->num_swizzled_attribs; i++) {
-        TRACE("%u: %s%d\n", i,
-              debug_d3ddeclusage(This->swizzled_attribs[i].usage), This->swizzled_attribs[i].idx);
-    }
     TRACE("Returning\n");
     return hr;
 }
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 9091c8a..339d955 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -218,113 +218,15 @@ BOOL vshader_get_input(
     return FALSE;
 }
 
-BOOL vshader_input_is_color(
-    IWineD3DVertexShader* iface,
-    unsigned int regnum) {
-
-    IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
-
-    DWORD usage_token = This->semantics_in[regnum].usage;
-    DWORD usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
-    DWORD usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
-
-    int i;
-
-    for(i = 0; i < This->num_swizzled_attribs; i++) {
-        if(This->swizzled_attribs[i].usage == usage &&
-           This->swizzled_attribs[i].idx == usage_idx) {
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-
-static inline void find_swizzled_attribs(IWineD3DVertexDeclaration *declaration, IWineD3DVertexShaderImpl *This) {
-    UINT num = 0, i, j;
-    UINT numoldswizzles = This->num_swizzled_attribs;
-    IWineD3DVertexDeclarationImpl *decl = (IWineD3DVertexDeclarationImpl *) declaration;
-
-    DWORD usage_token, usage, usage_idx;
-    BOOL found;
-
-    attrib_declaration oldswizzles[sizeof(This->swizzled_attribs) / sizeof(This->swizzled_attribs[0])];
-
-    /* Back up the old swizzles to keep attributes that are undefined in the current declaration */
-    memcpy(oldswizzles, This->swizzled_attribs, sizeof(oldswizzles));
-
-    memset(This->swizzled_attribs, 0, sizeof(This->swizzled_attribs[0]) * MAX_ATTRIBS);
-
-    for(i = 0; i < decl->num_swizzled_attribs; i++) {
-        for(j = 0; j < MAX_ATTRIBS; j++) {
-
-            if(!This->baseShader.reg_maps.attributes[j]) continue;
-
-            usage_token = This->semantics_in[j].usage;
-            usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
-            usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
-
-            if(decl->swizzled_attribs[i].usage == usage &&
-               decl->swizzled_attribs[i].idx == usage_idx) {
-                This->swizzled_attribs[num].usage = usage;
-                This->swizzled_attribs[num].idx = usage_idx;
-                num++;
-            }
-        }
-    }
-
-    /* Add previously converted attributes back in if they are not defined in the current declaration */
-    for(i = 0; i < numoldswizzles; i++) {
-
-        found = FALSE;
-        for(j = 0; j < decl->declarationWNumElements; j++) {
-            if(oldswizzles[i].usage == decl->pDeclarationWine[j].Usage &&
-               oldswizzles[i].idx == decl->pDeclarationWine[j].UsageIndex) {
-                found = TRUE;
-            }
-        }
-        if(found) {
-            /* This previously converted attribute is declared in the current declaration. Either it is
-             * already in the new array, or it should not be there. Skip it
-             */
-            continue;
-        }
-        /* We have a previously swizzled attribute that is not defined by the current vertex declaration.
-         * Insert it into the new conversion array to keep it in the old defined state. Otherwise we end up
-         * recompiling if the old decl is used again because undefined attributes are reset to no swizzling.
-         * In the reverse way(attribute was not swizzled and is not declared in new declaration) the attrib
-         * stays unswizzled as well because it isn't found in the oldswizzles array
-         */
-        for(j = 0; j < num; j++) {
-            if(oldswizzles[i].usage > This->swizzled_attribs[j].usage || (
-               oldswizzles[i].usage == This->swizzled_attribs[j].usage &&
-               oldswizzles[i].idx > This->swizzled_attribs[j].idx)) {
-                memmove(&This->swizzled_attribs[j + 1], &This->swizzled_attribs[j],
-                         sizeof(This->swizzled_attribs) - (sizeof(This->swizzled_attribs[0]) * (j + 1)));
-                break;
-            }
-        }
-        This->swizzled_attribs[j].usage = oldswizzles[i].usage;
-        This->swizzled_attribs[j].idx = oldswizzles[i].idx;
-        num++;
-    }
-
-    TRACE("New swizzled attributes array\n");
-    for(i = 0; i < num; i++) {
-        TRACE("%d: %s(%d), %d\n", i, debug_d3ddeclusage(This->swizzled_attribs[i].usage),
-              This->swizzled_attribs[i].usage, This->swizzled_attribs[i].idx);
-    }
-    This->num_swizzled_attribs = num;
-}
 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
     or GLSL and send it to the card */
 static void IWineD3DVertexShaderImpl_GenerateShader(IWineD3DVertexShader *iface,
         const struct shader_reg_maps* reg_maps, const DWORD *pFunction)
 {
     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
-    IWineD3DVertexDeclaration *decl = ((IWineD3DDeviceImpl *) This->baseShader.device)->stateBlock->vertexDecl;
     SHADER_BUFFER buffer;
 
-    find_swizzled_attribs(decl, This);
+    This->swizzle_map = ((IWineD3DDeviceImpl *)This->baseShader.device)->strided_streams.swizzle_map;
 
     shader_buffer_init(&buffer);
     ((IWineD3DDeviceImpl *)This->baseShader.device)->shader_backend->shader_generate_vshader(iface, &buffer);
@@ -516,56 +418,8 @@ static HRESULT WINAPI IWIneD3DVertexShaderImpl_SetLocalConstantsF(IWineD3DVertex
     return WINED3D_OK;
 }
 
-static inline BOOL swizzled_attribs_differ(IWineD3DVertexShaderImpl *This, IWineD3DVertexDeclarationImpl *vdecl) {
-    UINT i, j, k;
-    BOOL found;
-
-    DWORD usage_token;
-    DWORD usage;
-    DWORD usage_idx;
-
-    for(i = 0; i < vdecl->declarationWNumElements; i++) {
-        /* Ignore tesselated streams and the termination entry(position0, stream 255, unused) */
-        if(vdecl->pDeclarationWine[i].Stream >= MAX_STREAMS ||
-           vdecl->pDeclarationWine[i].Type == WINED3DDECLTYPE_UNUSED) continue;
-
-        for(j = 0; j < MAX_ATTRIBS; j++) {
-            if(!This->baseShader.reg_maps.attributes[j]) continue;
-
-            usage_token = This->semantics_in[j].usage;
-            usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
-            usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
-
-            if(vdecl->pDeclarationWine[i].Usage != usage ||
-               vdecl->pDeclarationWine[i].UsageIndex != usage_idx) {
-                continue;
-            }
-
-            found = FALSE;
-            for(k = 0; k < This->num_swizzled_attribs; k++) {
-                if(This->swizzled_attribs[k].usage == usage &&
-                    This->swizzled_attribs[k].idx == usage_idx) {
-                    found = TRUE;
-                }
-            }
-            if(!found && vdecl->pDeclarationWine[i].Type == WINED3DDECLTYPE_D3DCOLOR) {
-                TRACE("Attribute %s%d is D3DCOLOR now but wasn't before\n",
-                      debug_d3ddeclusage(usage), usage_idx);
-                return TRUE;
-            }
-            if( found && vdecl->pDeclarationWine[i].Type != WINED3DDECLTYPE_D3DCOLOR) {
-                TRACE("Attribute %s%d was D3DCOLOR before but is not any more\n",
-                      debug_d3ddeclusage(usage), usage_idx);
-                return TRUE;
-            }
-        }
-    }
-    return FALSE;
-}
-
 HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
-    IWineD3DVertexDeclarationImpl *vdecl;
     CONST DWORD *function = This->baseShader.function;
     IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *) This->baseShader.device;
 
@@ -573,20 +427,10 @@ HRESULT IWineD3DVertexShaderImpl_CompileShader(IWineD3DVertexShader *iface) {
 
     /* We're already compiled. */
     if (This->baseShader.is_compiled) {
-        vdecl = (IWineD3DVertexDeclarationImpl *) deviceImpl->stateBlock->vertexDecl;
-
-        if(This->num_swizzled_attribs != vdecl->num_swizzled_attribs ||
-           memcmp(This->swizzled_attribs, vdecl->swizzled_attribs, sizeof(vdecl->swizzled_attribs[0]) * This->num_swizzled_attribs) != 0) {
-
-            /* The swizzled attributes differ between shader and declaration. This doesn't necessarily mean
-             * we have to recompile, but we have to take a deeper look at see if the attribs that differ
-             * are declared in the decl and used in the shader
-             */
-            if(swizzled_attribs_differ(This, vdecl)) {
-                WARN("Recompiling vertex shader %p due to D3DCOLOR input changes\n", This);
-                goto recompile;
-            }
-            WARN("Swizzled attribute validation required an expensive comparison\n");
+        if ((This->swizzle_map & deviceImpl->strided_streams.use_map) != deviceImpl->strided_streams.swizzle_map)
+        {
+            WARN("Recompiling vertex shader %p due to D3DCOLOR input changes\n", This);
+            goto recompile;
         }
 
         return WINED3D_OK;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index cab2b20..89c5d77 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1711,11 +1711,6 @@ BOOL palette9_changed(IWineD3DSurfaceImpl *This);
 /*****************************************************************************
  * IWineD3DVertexDeclaration implementation structure
  */
-typedef struct attrib_declaration {
-    DWORD usage;
-    DWORD idx;
-} attrib_declaration;
-
 #define MAX_ATTRIBS 16
 
 typedef struct IWineD3DVertexDeclarationImpl {
@@ -1734,10 +1729,6 @@ typedef struct IWineD3DVertexDeclarationImpl {
     UINT                    num_streams;
     BOOL                    position_transformed;
     BOOL                    half_float_conv_needed;
-
-    /* Ordered array of declaration types that need swizzling in a vshader */
-    attrib_declaration      swizzled_attribs[MAX_ATTRIBS];
-    UINT                    num_swizzled_attribs;
 } IWineD3DVertexDeclarationImpl;
 
 extern const IWineD3DVertexDeclarationVtbl IWineD3DVertexDeclaration_Vtbl;
@@ -2182,10 +2173,6 @@ extern BOOL vshader_get_input(
     BYTE usage_req, BYTE usage_idx_req,
     unsigned int* regnum);
 
-extern BOOL vshader_input_is_color(
-    IWineD3DVertexShader* iface,
-    unsigned int regnum);
-
 extern HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object);
 
 /* GLSL helper functions */
@@ -2337,9 +2324,7 @@ typedef struct IWineD3DVertexShaderImpl {
     semantic semantics_in [MAX_ATTRIBS];
     semantic semantics_out [MAX_REG_OUTPUT];
 
-    /* Ordered array of attributes that are swizzled */
-    attrib_declaration          swizzled_attribs [MAX_ATTRIBS];
-    UINT                        num_swizzled_attribs;
+    WORD swizzle_map;   /* MAX_ATTRIBS, 16 */
 
     UINT                       min_rel_offset, max_rel_offset;
     UINT                       rel_offset;
diff --git a/include/wine/wined3d.idl b/include/wine/wined3d.idl
index 0ee7b1f..b43a8e7 100644
--- a/include/wine/wined3d.idl
+++ b/include/wine/wined3d.idl
@@ -1884,6 +1884,8 @@ typedef struct WineDirect3DVertexStridedData
     } u;
 
     BOOL position_transformed;
+    WORD swizzle_map;       /* MAX_ATTRIBS, 16 */
+    WORD use_map;           /* MAX_ATTRIBS, 16 */
 } WineDirect3DVertexStridedData;
 
 typedef struct _WINED3DVSHADERCAPS2_0
-- 
1.6.0.6



--------------010907010308010002010804--



More information about the wine-patches mailing list