[WINED3D 6] Reverse semantics maps for shaders

Ivan Gyurdiev ivg231 at gmail.com
Fri Jul 7 01:27:38 CDT 2006


The shader semantics arrays map a usage designation (semantic) to a 
register token, or 0 if not used. This isn't flexible enough, because 
the types and number of semantics are hardcoded to the ones used by the 
fixed function pipeline. The shader may use semantics not supported by 
the fixed function pipeline. I've seen at least one demo use TEXCOORD8. 
Also, this presentation:  
http://www.ati.com/developer/gdc/D3DTutorial1_Shaders.pdf, shows other 
semantics being used that aren't supported by the fixed pipeline.

So, instead of mapping X->Y, map Y->X.
This change makes the semantic arrays map a register number to a semantic.

- primitiveDeclarationConvertToStrided() was made the only supported 
path for shaders.
  We can do this, because d3d8 requires a declaration with the shader, 
and d3d9 automatically converts FVF -> DECL9. If the shader does not 
supply a declaration, we go through this path anyway, and zero the 
strided data. Note that the FVF path never actually worked at all when 
used with a shader.

- primitiveDeclarationConvertToStrided() was made to query the shader 
for the location in the strided data to write to (see 
vshader_get_input). The fixed pipeline uses fixed_get_input introduced 
in last patch.

- loadNumberedArrays() was re-written to use this new scheme.

- traceDataLocations() does not trace the vertex declaration path 
anymore, because it doesn't handle shaders properly, while we have other 
traces to show the data.

- All the shader changes have to do with the map reversal/reformatting - 
3.0 pack/unpack are affected.

- logic for whether something is a color input or not is now 
encapsulated in vshader_input_is_color().

-------------- next part --------------
>From 415ddc9eb69de79fa58098cd4329cc6ff048be18 Mon Sep 17 00:00:00 2001
From: root <root at shark.bluenet>
Date: Wed, 5 Jul 2006 22:00:45 -0600
Subject: [PATCH] Reverse semantic maps for shaders

The shader semantics arrays map a usage designation (semantic) to a register number, or 0 if not used. This isn't flexible enough, because the types and number of semantics are hardcoded to the ones used by the fixed function pipeline. The shader may use semantics not supported by the fixed function pipeline. I've seen at least one demo use TEXCOORD8. Also, this presentation shows other semantics being used that aren't supported by the fixed pipeline: http://www.ati.com/developer/gdc/D3DTutorial1_Shaders.pdf.

So, instead of mapping X->Y, map Y->X.
This change makes the semantic arrays map a register number to a semantic.

- primitiveDeclarationConvertToStrided() was made the only supported path for shaders.
  We can do this, because d3d8 requires a declaration with the shader, and d3d9 automatically converts FVF -> DECL9. If the shader does not supply a declaration, we go through this path anyway, and zero the strided data. Note that the FVF path never actually worked at all when used with a shader.

- primitiveDeclarationConvertToStrided() was made to query the shader for the location in the strided data to write to (see vshader_get_input). The fixed pipeline uses fixed_get_input introduced in last patch.

- loadNumberedArrays() was re-written to use this new scheme.

- traceDataLocations() does not trace the vertex declaration path anymore, because it doesn't handle shaders properly, while we have other traces to show the data.

- All the shader changes have to do with the map reversal/reformatting - 3.0 pack/unpack are affected.

- logic for whether something is a color input or not is now encapsulated in vshader_input_is_color().
---
 dlls/wined3d/arb_program_shader.c |   11 ---
 dlls/wined3d/baseshader.c         |  128 +----------------------------
 dlls/wined3d/drawprim.c           |  162 +++++++++++++------------------------
 dlls/wined3d/glsl_shader.c        |  130 +++++++++++++-----------------
 dlls/wined3d/vertexshader.c       |   31 +++++++
 dlls/wined3d/wined3d_private.h    |   29 +++++--
 6 files changed, 174 insertions(+), 317 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 47791bc..b9c8c3a 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -340,18 +340,9 @@ static void vshader_program_add_param(SH
     break;
   case D3DSPR_INPUT:
 
-    if (This->semantics_in[WINED3DSHADERDECLUSAGE_DIFFUSE] &&
-        reg == (This->semantics_in[WINED3DSHADERDECLUSAGE_DIFFUSE] & D3DSP_REGNUM_MASK))
+    if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
         is_color = TRUE;
 
-    if (This->semantics_in[WINED3DSHADERDECLUSAGE_SPECULAR] &&
-        reg == (This->semantics_in[WINED3DSHADERDECLUSAGE_SPECULAR] & D3DSP_REGNUM_MASK))
-        is_color = TRUE;
-
-    /* FIXME: Shaders in 8.1 appear to not require a dcl statement - use
-     * the reg value from the vertex declaration. However, semantics are not initialized
-     * in that case - how can we know if an input contains color data or not? */
-
     sprintf(tmpReg, "vertex.attrib[%lu]", reg);
     strcat(hwLine, tmpReg);
     break;
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 8ed85ef..b7aa45f 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -171,132 +171,14 @@ unsigned int shader_get_float_offset(con
      }
 }
 
-static void shader_parse_decl_usage(
-    DWORD *semantics_map,
-    DWORD usage_token, DWORD param) {
-
-    unsigned int usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
-    unsigned int usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
-    unsigned int regnum = param & D3DSP_REGNUM_MASK;
-
-    switch(usage) {
-        case D3DDECLUSAGE_POSITION:
-            if (usage_idx == 0) { /* tween data */
-                TRACE("Setting position to %d\n", regnum);
-                semantics_map[WINED3DSHADERDECLUSAGE_POSITION] = param;
-            } else {
-                /* TODO: position indexes go from 0-8!!*/
-                TRACE("Setting position 2 to %d because usage_idx = %d\n", regnum, usage_idx);
-                /* robots uses positions up to 8, the position arrays are just packed.*/
-                if (usage_idx > 1) {
-                    TRACE("Loaded for position %d (greater than 2)\n", usage_idx);
-                }
-                semantics_map[WINED3DSHADERDECLUSAGE_POSITION2 + usage_idx-1] = param;
-            }
-            break;
-
-        case D3DDECLUSAGE_BLENDINDICES:
-            TRACE("Setting BLENDINDICES to %d\n", regnum);
-            semantics_map[WINED3DSHADERDECLUSAGE_BLENDINDICES] = param;
-            if (usage_idx != 0) FIXME("Extended BLENDINDICES\n");
-            break;
-
-        case D3DDECLUSAGE_BLENDWEIGHT:
-            TRACE("Setting BLENDWEIGHT to %d\n", regnum);
-            semantics_map[WINED3DSHADERDECLUSAGE_BLENDWEIGHT] = param;
-            if (usage_idx != 0) FIXME("Extended blend weights\n");
-            break;
-
-        case D3DDECLUSAGE_NORMAL:
-            if (usage_idx == 0) { /* tween data */
-                TRACE("Setting normal to %d\n", regnum);
-                semantics_map[WINED3DSHADERDECLUSAGE_NORMAL] = param;
-            } else {
-                TRACE("Setting normal 2 to %d because usage = %d\n", regnum, usage_idx);
-                semantics_map[WINED3DSHADERDECLUSAGE_NORMAL2] = param;
-            }
-            break;
-
-        case D3DDECLUSAGE_PSIZE:
-            TRACE("Setting PSIZE to %d\n", regnum);
-            semantics_map[WINED3DSHADERDECLUSAGE_PSIZE] = param;
-            if (usage_idx != 0) FIXME("Extended PSIZE\n");
-            break;
-
-        case D3DDECLUSAGE_COLOR:
-            if (usage_idx == 0)  {
-                TRACE("Setting DIFFUSE to %d\n", regnum);
-                semantics_map[WINED3DSHADERDECLUSAGE_DIFFUSE] = param;
-            } else {
-                TRACE("Setting SPECULAR to %d\n", regnum);
-                semantics_map[WINED3DSHADERDECLUSAGE_SPECULAR] = param;
-            }
-            break;
-
-        case D3DDECLUSAGE_TEXCOORD:
-            if (usage_idx > 7) {
-                FIXME("Program uses texture coordinate %d but only 0-7 have been "
-                    "implemented\n", usage_idx);
-            } else {
-                TRACE("Setting TEXCOORD %d  to %d\n", usage_idx, regnum);
-                semantics_map[WINED3DSHADERDECLUSAGE_TEXCOORD0 + usage_idx] = param;
-            }
-            break;
-
-        case D3DDECLUSAGE_TANGENT:
-            TRACE("Setting TANGENT to %d\n", regnum);
-            semantics_map[WINED3DSHADERDECLUSAGE_TANGENT] = param;
-            break;
-
-        case D3DDECLUSAGE_BINORMAL:
-            TRACE("Setting BINORMAL to %d\n", regnum);
-            semantics_map[WINED3DSHADERDECLUSAGE_BINORMAL] = param;
-            break;
-
-        case D3DDECLUSAGE_TESSFACTOR:
-            TRACE("Setting TESSFACTOR to %d\n", regnum);
-            semantics_map[WINED3DSHADERDECLUSAGE_TESSFACTOR] = param;
-            break;
-
-        case D3DDECLUSAGE_POSITIONT:
-            if (usage_idx == 0) { /* tween data */
-                FIXME("Setting positiont to %d\n", regnum);
-                semantics_map[WINED3DSHADERDECLUSAGE_POSITIONT] = param;
-            } else {
-                FIXME("Setting positiont 2 to %d because usage = %d\n", regnum, usage_idx);
-                semantics_map[WINED3DSHADERDECLUSAGE_POSITIONT2] = param;
-                if (usage_idx != 0) FIXME("Extended positiont\n");
-            }
-            break;
-
-        case D3DDECLUSAGE_FOG:
-            TRACE("Setting FOG to %d\n", regnum);
-            semantics_map[WINED3DSHADERDECLUSAGE_FOG] = param;
-            break;
-
-        case D3DDECLUSAGE_DEPTH:
-            TRACE("Setting DEPTH to %d\n", regnum);
-            semantics_map[WINED3DSHADERDECLUSAGE_DEPTH] = param;
-            break;
-
-        case D3DDECLUSAGE_SAMPLE:
-            TRACE("Setting SAMPLE to %d\n", regnum);
-            semantics_map[WINED3DSHADERDECLUSAGE_SAMPLE] = param;
-            break;
-
-        default:
-            FIXME("Unrecognised dcl %#x", usage);
-    }
-}
-
 /* Note that this does not count the loop register
  * as an address register. */
 
 void shader_get_registers_used(
     IWineD3DBaseShader *iface,
     shader_reg_maps* reg_maps,
-    DWORD* semantics_in,
-    DWORD* semantics_out,
+    semantic* semantics_in,
+    semantic* semantics_out,
     CONST DWORD* pToken) {
 
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
@@ -350,12 +232,14 @@ void shader_get_registers_used(
                 else
                     reg_maps->packed_input[regnum] = 1;
 
-                shader_parse_decl_usage(semantics_in, usage, param);
+                semantics_in[regnum].usage = usage;
+                semantics_in[regnum].reg = param;
 
             /* Vshader: mark 3.0 output registers used, save token */
             } else if (D3DSPR_OUTPUT == regtype) {
                 reg_maps->packed_output[regnum] = 1;
-                shader_parse_decl_usage(semantics_out, usage, param);
+                semantics_out[regnum].usage = usage;
+                semantics_out[regnum].reg = param;
 
             /* Save sampler usage token */
             } else if (D3DSPR_SAMPLER == regtype)
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 662260e..7177864 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -464,7 +464,12 @@ void primitiveDeclarationConvertToStride
             checkGLcall("glEnableVertexAttribArrayARB");
         }
 
-        stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
+        if (useVertexShaderFunction)
+            stride_used = vshader_get_input(This->stateBlock->vertexShader,
+                element->Usage, element->UsageIndex, &idx);
+        else
+            stride_used = fixed_get_input(element->Usage, element->UsageIndex, &idx);
+
         if (stride_used) {
            TRACE("Loaded %s array %u [usage=%s, usage_idx=%u, "
                  "stream=%u, offset=%u, stride=%lu, VBO=%u]\n",
@@ -476,10 +481,12 @@ void primitiveDeclarationConvertToStride
            strided->u.input[idx].dwType = element->Type;
            strided->u.input[idx].dwStride = stride;
            strided->u.input[idx].VBO = streamVBO;
-           if (element->Usage == D3DDECLUSAGE_POSITION)
-               strided->u.s.position_transformed = FALSE;
-           else if (element->Usage == D3DDECLUSAGE_POSITIONT)
-               strided->u.s.position_transformed = TRUE;
+           if (!useVertexShaderFunction) {
+               if (element->Usage == D3DDECLUSAGE_POSITION)
+                   strided->u.s.position_transformed = FALSE;
+               else if (element->Usage == D3DDECLUSAGE_POSITIONT)
+                   strided->u.s.position_transformed = TRUE;
+           }
         }
     };
 }
@@ -663,105 +670,35 @@ #endif
     }
 }
 
-void loadNumberedArrays(
-    IWineD3DDevice *iface, 
-    WineDirect3DVertexStridedData *sd, 
-    DWORD arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
+static void loadNumberedArrays(
+    IWineD3DDevice *iface,
+    IWineD3DVertexShader *shader,
+    WineDirect3DVertexStridedData *strided) {
 
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
     GLint curVBO = -1;
+    int i;
 
-#define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
-    if ((sd->u.s._arrayName.lpData != NULL || sd->u.s._arrayName.VBO != 0) && arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName]) { \
-        unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & D3DSP_REGNUM_MASK; \
-        TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx,  #_arrayName); \
-        if(curVBO != sd->u.s._arrayName.VBO) { \
-            GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s._arrayName.VBO)); \
-            checkGLcall("glBindBufferARB"); \
-            curVBO = sd->u.s._arrayName.VBO; \
-        } \
-        GL_EXTCALL(glVertexAttribPointerARB(idx, \
-                        WINED3D_ATR_SIZE(sd->u.s._arrayName.dwType), \
-                        WINED3D_ATR_GLTYPE(sd->u.s._arrayName.dwType), \
-                        WINED3D_ATR_NORMALIZED(sd->u.s._arrayName.dwType), \
-                        sd->u.s._arrayName.dwStride, \
-                        sd->u.s._arrayName.lpData)); \
-        GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \
-    }
+    for (i = 0; i < MAX_ATTRIBS; i++) {
 
+        if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
+            continue;
 
-#define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
-    if ((sd->u.s.position2.lpData != NULL  || sd->u.s.position2.VBO != 0)&& arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber]) { \
-        unsigned int idx = arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & D3DSP_REGNUM_MASK; \
-        TRACE_(d3d_shader)("Loading array %u with data from %s\n", idx, "position2"); \
-        if(curVBO != sd->u.s.position2.VBO) { \
-            GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position2.VBO)); \
-            checkGLcall("glBindBufferARB"); \
-            curVBO = sd->u.s.position2.VBO; \
-        } \
-        GL_EXTCALL(glVertexAttribPointerARB(idx, \
-                        WINED3D_ATR_SIZE(sd->u.s.position2.dwType), \
-                        WINED3D_ATR_GLTYPE(sd->u.s.position2.dwType), \
-                        WINED3D_ATR_NORMALIZED(sd->u.s.position2.dwType), \
-                        sd->u.s.position2.dwStride, \
-                        ((char *)sd->u.s.position2.lpData) + \
-                           WINED3D_ATR_SIZE(sd->u.s.position2.dwType) * \
-                           WINED3D_ATR_TYPESIZE(sd->u.s.position2.dwType) * _lookupNumber)); \
-        GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \
-    }
+        TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
 
-/* Generate some lookup tables */
-    /* drop the RHW coord, there must be a nicer way of doing this. */
-    sd->u.s.position.dwType  = min(D3DDECLTYPE_FLOAT3, sd->u.s.position.dwType);
-    sd->u.s.position2.dwType = min(D3DDECLTYPE_FLOAT3, sd->u.s.position2.dwType);
-
-    LOAD_NUMBERED_ARRAY(blendWeights,BLENDWEIGHT);
-    LOAD_NUMBERED_ARRAY(blendMatrixIndices,BLENDINDICES);
-    LOAD_NUMBERED_ARRAY(position,POSITION);
-    LOAD_NUMBERED_ARRAY(normal,NORMAL);
-    LOAD_NUMBERED_ARRAY(pSize,PSIZE);
-    LOAD_NUMBERED_ARRAY(diffuse,DIFFUSE);
-    LOAD_NUMBERED_ARRAY(specular,SPECULAR);
-    LOAD_NUMBERED_ARRAY(texCoords[0],TEXCOORD0);
-    LOAD_NUMBERED_ARRAY(texCoords[1],TEXCOORD1);
-    LOAD_NUMBERED_ARRAY(texCoords[2],TEXCOORD2);
-    LOAD_NUMBERED_ARRAY(texCoords[3],TEXCOORD3);
-    LOAD_NUMBERED_ARRAY(texCoords[4],TEXCOORD4);
-    LOAD_NUMBERED_ARRAY(texCoords[5],TEXCOORD5);
-    LOAD_NUMBERED_ARRAY(texCoords[6],TEXCOORD6);
-    LOAD_NUMBERED_ARRAY(texCoords[7],TEXCOORD7);
-#if 0   /* TODO: Samplers may allow for more texture coords */
-    LOAD_NUMBERED_ARRAY(texCoords[8],TEXCOORD8);
-    LOAD_NUMBERED_ARRAY(texCoords[9],TEXCOORD9);
-    LOAD_NUMBERED_ARRAY(texCoords[10],TEXCOORD10);
-    LOAD_NUMBERED_ARRAY(texCoords[11],TEXCOORD11);
-    LOAD_NUMBERED_ARRAY(texCoords[12],TEXCOORD12);
-    LOAD_NUMBERED_ARRAY(texCoords[13],TEXCOORD13);
-    LOAD_NUMBERED_ARRAY(texCoords[14],TEXCOORD14);
-    LOAD_NUMBERED_ARRAY(texCoords[15],TEXCOORD15);
-#endif
-    LOAD_NUMBERED_ARRAY(position,POSITIONT);
-    /* d3d9 types */
-    LOAD_NUMBERED_ARRAY(tangent,TANGENT);
-    LOAD_NUMBERED_ARRAY(binormal,BINORMAL);
-    LOAD_NUMBERED_ARRAY(tessFactor,TESSFACTOR);
-    LOAD_NUMBERED_ARRAY(position2,POSITION2);
-    /* there can be lots of position arrays */
-    LOAD_NUMBERED_POSITION_ARRAY(0);
-    LOAD_NUMBERED_POSITION_ARRAY(1);
-    LOAD_NUMBERED_POSITION_ARRAY(2);
-    LOAD_NUMBERED_POSITION_ARRAY(3);
-    LOAD_NUMBERED_POSITION_ARRAY(4);
-    LOAD_NUMBERED_POSITION_ARRAY(5);
-    LOAD_NUMBERED_POSITION_ARRAY(6);
-    LOAD_NUMBERED_POSITION_ARRAY(7);
-    LOAD_NUMBERED_ARRAY(position2,POSITIONT2);
-    LOAD_NUMBERED_ARRAY(normal2,NORMAL2);
-    LOAD_NUMBERED_ARRAY(fog,FOG);
-    LOAD_NUMBERED_ARRAY(depth,DEPTH);
-    LOAD_NUMBERED_ARRAY(sample,SAMPLE);
-
-#undef LOAD_NUMBERED_ARRAY
+        if(curVBO != strided->u.input[i].VBO) {
+            GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
+            checkGLcall("glBindBufferARB");
+            curVBO = strided->u.input[i].VBO;
+        }
+        GL_EXTCALL(glVertexAttribPointerARB(i,
+                        WINED3D_ATR_SIZE(strided->u.input[i].dwType),
+                        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));
+        GL_EXTCALL(glEnableVertexAttribArrayARB(i));
+   }
 }
 
 static void loadVertexData(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd) {
@@ -1526,8 +1463,7 @@ #undef BUFFER_OR_DATA
     /* Hardware Shader pipeline - load attribute arrays */
     } else if(useVertexShaderFunction && wined3d_settings.vs_selected_mode != SHADER_SW) {
 
-        loadNumberedArrays(iface, dataLocations, 
-            ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->semantics_in);
+        loadNumberedArrays(iface, This->stateBlock->vertexShader, dataLocations);
         useDrawStridedSlow = FALSE;
 
     /* Draw vertex by vertex */
@@ -1871,11 +1807,21 @@ void drawPrimitive(IWineD3DDevice *iface
     ENTER_GL();
 
     if(DrawPrimStrideData) {
+
+        /* Note: this is a ddraw fixed-function code path */
+
         TRACE("================ Strided Input ===================\n");
         dataLocations = DrawPrimStrideData;
+        drawPrimitiveTraceDataLocations(dataLocations);
         fixup = FALSE;
     }
-    else if (This->stateBlock->vertexDecl != NULL || (useVertexShaderFunction  && NULL != ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration)) {
+
+    else if (This->stateBlock->vertexDecl != NULL || useVertexShaderFunction) {
+
+        /* Note: This is a fixed function or shader codepath.
+         * This means it must handle both types of strided data.
+         * Shaders must go through here to zero the strided data, even if they
+         * don't set any declaration at all */
 
         TRACE("================ Vertex Declaration  ===================\n");
         dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
@@ -1883,9 +1829,19 @@ void drawPrimitive(IWineD3DDevice *iface
             ERR("Out of memory!\n");
             return;
         }
-        primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, dataLocations, StartVertexIndex, &fixup);
+
+        if (This->stateBlock->vertexDecl != NULL ||
+            ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration != NULL)            
+
+            primitiveDeclarationConvertToStridedData(iface, useVertexShaderFunction, 
+                dataLocations, StartVertexIndex, &fixup);
 
     } else {
+
+        /* Note: This codepath is not reachable from d3d9 (see fvf->decl9 conversion)
+         * It is reachable through d3d8, but only for fixed-function.
+         * It will not work properly for shaders. */
+
         TRACE("================ FVF ===================\n");
         dataLocations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dataLocations));
         if(!dataLocations) {
@@ -1893,11 +1849,9 @@ void drawPrimitive(IWineD3DDevice *iface
             return;
         }
         primitiveConvertToStridedData(iface, dataLocations, StartVertexIndex, &fixup);
+        drawPrimitiveTraceDataLocations(dataLocations);
     }
 
-    /* write out some debug information*/
-    drawPrimitiveTraceDataLocations(dataLocations);
-
     /* Setup transform matrices and sort out */
     primitiveInitState(iface, dataLocations, useVertexShaderFunction, &lighting_changed, &lighting_original);
 
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index d15874c..ae75ef0 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -501,20 +501,8 @@ static void shader_glsl_get_register_nam
                     strcpy(tmpStr, "gl_SecondaryColor");
             }
         } else {
-            IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl*) arg->shader;
-
-            if (This->semantics_in[WINED3DSHADERDECLUSAGE_DIFFUSE] &&
-                reg == (This->semantics_in[WINED3DSHADERDECLUSAGE_DIFFUSE] & D3DSP_REGNUM_MASK))
-                *is_color = TRUE;
-
-            if (This->semantics_in[WINED3DSHADERDECLUSAGE_SPECULAR] &&
-                reg == (This->semantics_in[WINED3DSHADERDECLUSAGE_SPECULAR] & D3DSP_REGNUM_MASK))
-                *is_color = TRUE;
-
-            /* FIXME: Shaders in 8.1 appear to not require a dcl statement - use
-             * the reg value from the vertex declaration. However, semantics are not initialized
-              * in that case - how can we know if an input contains color data or not? */
-
+            if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
+               *is_color = TRUE;
             sprintf(tmpStr, "attrib%lu", reg);
         } 
         break;
@@ -1390,53 +1378,50 @@ void pshader_glsl_dp2add(SHADER_OPCODE_A
 
 void pshader_glsl_input_pack(
    SHADER_BUFFER* buffer,
-   DWORD* semantics_in) {
+   semantic* semantics_in) {
 
    unsigned int i;
 
-   for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
+   for (i = 0; i < MAX_REG_INPUT; i++) {
 
-       DWORD reg = semantics_in[i];
-       unsigned int regnum = reg & D3DSP_REGNUM_MASK;
+       DWORD usage_token = semantics_in[i].usage;
+       DWORD register_token = semantics_in[i].reg;
+       DWORD usage, usage_idx;
        char reg_mask[6];
 
        /* Uninitialized */
-       if (!reg) continue;
-
-       shader_glsl_get_output_register_swizzle(reg, reg_mask);
-
-       switch(i) {
-
-           case WINED3DSHADERDECLUSAGE_DIFFUSE:
-               shader_addline(buffer, "IN%lu%s = vec4(gl_Color)%s;\n",
-                   regnum, reg_mask, reg_mask);
-               break;
-
-           case WINED3DSHADERDECLUSAGE_SPECULAR:
-               shader_addline(buffer, "IN%lu%s = vec4(gl_SecondaryColor)%s;\n",
-                   regnum, reg_mask, reg_mask);
+       if (!usage_token) continue;
+       usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
+       usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
+       shader_glsl_get_output_register_swizzle(register_token, reg_mask);
+
+       switch(usage) {
+
+           case D3DDECLUSAGE_COLOR:
+               if (usage_idx == 0)
+                   shader_addline(buffer, "IN%lu%s = vec4(gl_Color)%s;\n",
+                       i, reg_mask, reg_mask);
+               if (usage_idx == 1)
+                   shader_addline(buffer, "IN%lu%s = vec4(gl_SecondaryColor)%s;\n",
+                       i, reg_mask, reg_mask);
+               else
+                   shader_addline(buffer, "IN%lu%s = vec4(unsupported_color_input)%s;\n",
+                       i, reg_mask, reg_mask);
                break;
 
-           case WINED3DSHADERDECLUSAGE_TEXCOORD0:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD1:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD2:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD3:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD4:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD5:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD6:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD7:
+           case D3DDECLUSAGE_TEXCOORD:
                shader_addline(buffer, "IN%lu%s = vec4(gl_TexCoord[%lu])%s;\n",
-                   regnum, reg_mask, i - WINED3DSHADERDECLUSAGE_TEXCOORD0, reg_mask );
+                   i, reg_mask, usage_idx, reg_mask );
                break;
 
-           case WINED3DSHADERDECLUSAGE_FOG:
+           case D3DDECLUSAGE_FOG:
                shader_addline(buffer, "IN%lu%s = vec4(gl_FogFragCoord)%s;\n",
-                   regnum, reg_mask, reg_mask);
+                   i, reg_mask, reg_mask);
                break;
 
            default:
                shader_addline(buffer, "IN%lu%s = vec4(unsupported_input)%s;\n",
-                   regnum, reg_mask, reg_mask);
+                   i, reg_mask, reg_mask);
         }
     }
 }
@@ -1447,57 +1432,54 @@ void pshader_glsl_input_pack(
 
 void vshader_glsl_output_unpack(
    SHADER_BUFFER* buffer,
-   DWORD* semantics_out) {
+   semantic* semantics_out) {
 
    unsigned int i;
 
-   for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++) {
+   for (i = 0; i < MAX_REG_OUTPUT; i++) {
 
-       DWORD reg = semantics_out[i];
-       unsigned int regnum = reg & D3DSP_REGNUM_MASK;
+       DWORD usage_token = semantics_out[i].usage;
+       DWORD register_token = semantics_out[i].reg;
+       DWORD usage, usage_idx;
        char reg_mask[6];
 
        /* Uninitialized */
-       if (!reg) continue;
-
-       shader_glsl_get_output_register_swizzle(reg, reg_mask);
+       if (!usage_token) continue;
 
-       switch(i) {
+       usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
+       usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
+       shader_glsl_get_output_register_swizzle(register_token, reg_mask);
 
-           case WINED3DSHADERDECLUSAGE_DIFFUSE:
-               shader_addline(buffer, "gl_FrontColor%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask);
-               break;
+       switch(usage) {
 
-           case WINED3DSHADERDECLUSAGE_SPECULAR:
-               shader_addline(buffer, "gl_FrontSecondaryColor%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask);
+           case D3DDECLUSAGE_COLOR:
+               if (usage_idx == 0)
+                   shader_addline(buffer, "gl_FrontColor%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
+               else if (usage_idx == 1)
+                   shader_addline(buffer, "gl_FrontSecondaryColor%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
+               else
+                   shader_addline(buffer, "unsupported_color_output%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
                break;
 
-           case WINED3DSHADERDECLUSAGE_POSITION:
-               shader_addline(buffer, "gl_Position%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask);
+           case D3DDECLUSAGE_POSITION:
+               shader_addline(buffer, "gl_Position%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
                break;
-
-           case WINED3DSHADERDECLUSAGE_TEXCOORD0:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD1:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD2:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD3:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD4:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD5:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD6:
-           case WINED3DSHADERDECLUSAGE_TEXCOORD7:
+ 
+           case D3DDECLUSAGE_TEXCOORD:
                shader_addline(buffer, "gl_TexCoord[%lu]%s = OUT%lu%s;\n",
-                   i - WINED3DSHADERDECLUSAGE_TEXCOORD0, reg_mask, regnum, reg_mask);
+                   usage_idx, reg_mask, i, reg_mask);
                break;
 
            case WINED3DSHADERDECLUSAGE_PSIZE:
-               shader_addline(buffer, "gl_PointSize = OUT%lu.x;\n", regnum);
+               shader_addline(buffer, "gl_PointSize = OUT%lu.x;\n", i);
                break;
 
            case WINED3DSHADERDECLUSAGE_FOG:
-               shader_addline(buffer, "gl_FogFragCoord%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask);
+               shader_addline(buffer, "gl_FogFragCoord%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
                break;
 
            default:
-               shader_addline(buffer, "unsupported_output%s = OUT%lu%s;\n", reg_mask, regnum, reg_mask);
-      }
-   }
+               shader_addline(buffer, "unsupported_output%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
+       }
+    }
 }
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index df0fd99..7d452d2 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -609,6 +609,37 @@ static void vshader_set_limits(
       }
 }
 
+BOOL vshader_get_input(
+    IWineD3DVertexShader* iface,
+    BYTE usage_req, BYTE usage_idx_req,
+    unsigned int* regnum) {
+
+    IWineD3DVertexShaderImpl* This = (IWineD3DVertexShaderImpl*) iface;
+    int i;
+
+    for (i = 0; i < MAX_ATTRIBS; i++) {
+        DWORD usage_token = This->semantics_in[i].usage;
+        DWORD usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
+        DWORD usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
+
+        if (usage_token && (usage == usage_req && usage_idx == usage_idx_req)) {
+            *regnum = i;
+            return TRUE;
+        }
+    }
+    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 & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
+    return usage == D3DDECLUSAGE_COLOR;
+}
+
 /** Generate a vertex shader string using either GL_VERTEX_PROGRAM_ARB
     or GLSL and send it to the card */
 static VOID IWineD3DVertexShaderImpl_GenerateShader(
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f29c7a1..c1f2684 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1292,6 +1292,11 @@ typedef struct draw_context {
     BOOL is_transformed;
 } draw_context;
 
+typedef struct semantic {
+    DWORD usage;
+    DWORD reg;
+} semantic;
+
 typedef struct shader_reg_maps {
 
     char texcoord[MAX_REG_TEXCRD];          /* pixel < 3.0 */
@@ -1376,6 +1381,16 @@ extern const SHADER_OPCODE* shader_get_o
     IWineD3DBaseShader *iface, 
     const DWORD code);
 
+/* Vertex shader utility functions */
+extern BOOL vshader_get_input(
+    IWineD3DVertexShader* iface,
+    BYTE usage_req, BYTE usage_idx_req,
+    unsigned int* regnum);
+
+extern BOOL vshader_input_is_color(
+    IWineD3DVertexShader* iface,
+    unsigned int regnum);
+
 /* ARB_[vertex/fragment]_program helper functions */
 extern void shader_arb_load_constants(
     IWineD3DStateBlock* iface,
@@ -1446,12 +1461,12 @@ extern void pshader_glsl_texbem(SHADER_O
 extern void pshader_glsl_dp2add(SHADER_OPCODE_ARG* arg);
 extern void pshader_glsl_input_pack(
    SHADER_BUFFER* buffer,
-   DWORD* semantics_out);
+   semantic* semantics_out);
 
 /** GLSL Vertex Shader Prototypes */
 extern void vshader_glsl_output_unpack(
    SHADER_BUFFER* buffer,
-   DWORD* semantics_out);
+   semantic* semantics_out);
 
 /*****************************************************************************
  * IDirect3DBaseShader implementation structure
@@ -1483,8 +1498,8 @@ typedef struct IWineD3DBaseShaderImpl {
 extern void shader_get_registers_used(
     IWineD3DBaseShader *iface,
     shader_reg_maps* reg_maps,
-    DWORD* semantics_in,
-    DWORD* semantics_out,
+    semantic* semantics_in,
+    semantic* semantics_out,
     CONST DWORD* pToken);
 
 extern void shader_generate_glsl_declarations(
@@ -1567,8 +1582,8 @@ typedef struct IWineD3DVertexShaderImpl 
     DWORD usage;
 
     /* Vertex shader input and output semantics */
-    DWORD semantics_in [WINED3DSHADERDECLUSAGE_MAX_USAGE];
-    DWORD semantics_out [WINED3DSHADERDECLUSAGE_MAX_USAGE];
+    semantic semantics_in [MAX_ATTRIBS];
+    semantic semantics_out [MAX_REG_OUTPUT];
 
     /* run time datas...  */
     VSHADERDATA                *data;
@@ -1598,7 +1613,7 @@ typedef struct IWineD3DPixelShaderImpl {
     IWineD3DDeviceImpl         *wineD3DDevice;
 
     /* Pixel shader input semantics */
-    DWORD semantics_in [WINED3DSHADERDECLUSAGE_MAX_USAGE];
+    semantic semantics_in [MAX_REG_INPUT];
 
     /* run time data */
     PSHADERDATA                *data;
-- 
1.4.0



More information about the wine-patches mailing list