[WINED3D 2/9] Rework dcl processing

Ivan Gyurdiev ivg231 at gmail.com
Mon Jun 12 01:53:32 CDT 2006


The new function is called in pass 2 (getister counting/maps), and it's 
now in baseshader. It operates on all INPUT and OUTPUT registers, which, 
in addition to the old vertex shader input declarations covers Shader 
Model 3.0 vshader output and pshader input declarations. The result is 
stored into the reg_map structure.

Changes to the function include storing the full register token for each 
semantic, not just the number. I will need this information in the 
future (write mask). Also, clean up and correct all bitmasks.

-------------- next part --------------
---

 dlls/wined3d/baseshader.c      |  157 +++++++++++++++++++++++++++++++++++-----
 dlls/wined3d/drawprim.c        |   24 ++++--
 dlls/wined3d/glsl_shader.c     |   21 ++++-
 dlls/wined3d/pixelshader.c     |   20 ++++-
 dlls/wined3d/vertexshader.c    |  145 +++++++------------------------------
 dlls/wined3d/wined3d_private.h |   15 +++-
 6 files changed, 224 insertions(+), 158 deletions(-)

358296416cf6d5caaa2f0b47a7b2318cce67a809
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index f62b71c..21ec944 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -172,10 +172,128 @@ 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. */
 
-static void shader_get_registers_used(
+void shader_get_registers_used(
     IWineD3DBaseShader *iface,
     shader_reg_maps* reg_maps,
     CONST DWORD* pToken) {
@@ -216,10 +334,21 @@ static void shader_get_registers_used(
                ++pToken;
            continue;
 
-        /* Skip declarations (for now) */
+        /* Handle declarations */
         } else if (D3DSIO_DCL == curOpcode->opcode) {
-            pToken += curOpcode->num_params;
-            continue;
+
+            DWORD usage = *pToken++;
+            DWORD param = *pToken++;
+            DWORD regtype = shader_get_regtype(param);
+
+            if (D3DSPR_INPUT == regtype) {
+                shader_parse_decl_usage(reg_maps->semantics_in, usage, param);
+
+            } else if (D3DSPR_OUTPUT == regtype) {
+                shader_parse_decl_usage(reg_maps->semantics_out, usage, param);
+            }
+
+            /* Handle samplers here */
 
         /* Skip definitions (for now) */
         } else if (D3DSIO_DEF == curOpcode->opcode) {
@@ -617,9 +746,10 @@ void generate_glsl_declarations(
     that are specific to pixel or vertex functions
     NOTE: A description of how to parse tokens can be found at:
           http://msdn.microsoft.com/library/default.asp?url=/library/en-us/graphics/hh/graphics/usermodedisplaydriver_shader_cc8e4e05-f5c3-4ec0-8853-8ce07c1551b2.xml.asp */
-void generate_base_shader(
+void shader_generate_main(
     IWineD3DBaseShader *iface,
     SHADER_BUFFER* buffer,
+    shader_reg_maps* reg_maps,
     CONST DWORD* pFunction) {
 
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
@@ -628,30 +758,19 @@ void generate_base_shader(
     SHADER_HANDLER hw_fct = NULL;
     DWORD opcode_token;
     DWORD i;
-    shader_reg_maps reg_maps;
     SHADER_OPCODE_ARG hw_arg;
 
-    memset(&reg_maps, 0, sizeof(shader_reg_maps));
-
     /* Initialize current parsing state */
     hw_arg.shader = iface;
     hw_arg.buffer = buffer;
-    hw_arg.reg_maps = &reg_maps;
+    hw_arg.reg_maps = reg_maps;
     This->baseShader.parse_state.current_row = 0;
 
-    /* First pass: figure out which temporary and texture registers are used */
-    shader_get_registers_used(iface, &reg_maps, pToken);
-
-    /* TODO: check register usage against GL/Directx limits, and fail if they're exceeded
-        nUseAddressRegister < = GL_MAX_PROGRAM_ADDRESS_REGISTERS_AR
-        nUseTempRegister    <=  GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB
-    */
-
     /* Pre-declare registers */
     if (wined3d_settings.shader_mode == SHADER_GLSL) {
-        generate_glsl_declarations(iface, &reg_maps, buffer);
+        generate_glsl_declarations(iface, reg_maps, buffer);
     } else {
-        generate_arb_declarations(iface, &reg_maps, buffer);
+        generate_arb_declarations(iface, reg_maps, buffer);
     }
 
     /* Second pass, process opcodes */
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 6c6e526..acd708c 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -833,33 +833,39 @@ static void draw_vertex(IWineD3DDevice *
 }
 #endif /* TODO: Software shaders */
 
-void loadNumberedArrays(IWineD3DDevice *iface, WineDirect3DVertexStridedData *sd, INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
+void loadNumberedArrays(
+    IWineD3DDevice *iface, 
+    WineDirect3DVertexStridedData *sd, 
+    DWORD arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE]) {
+
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
 
 #define LOAD_NUMBERED_ARRAY(_arrayName, _lookupName) \
-    if (sd->u.s._arrayName.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])) { \
-       TRACE_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], #_arrayName); \
-       GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName], \
+    if (sd->u.s._arrayName.lpData != NULL && 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); \
+        GL_EXTCALL(glVertexAttribPointerARB(idx, \
                         WINED3D_ATR_SIZE(_arrayName), \
                         WINED3D_ATR_GLTYPE(_arrayName), \
                         WINED3D_ATR_NORMALIZED(_arrayName), \
                         sd->u.s._arrayName.dwStride, \
                         sd->u.s._arrayName.lpData)); \
-        GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_##_lookupName])); \
+        GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \
     }
 
 
 #define LOAD_NUMBERED_POSITION_ARRAY(_lookupNumber) \
-    if (sd->u.s.position2.lpData != NULL && ((arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber] & 0x7FFF) == arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])) { \
-       FIXME_(d3d_shader)("Loading array %u with data from %s\n", arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], "position2"); \
-       GL_EXTCALL(glVertexAttribPointerARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber], \
+    if (sd->u.s.position2.lpData != NULL && 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"); \
+        GL_EXTCALL(glVertexAttribPointerARB(idx, \
                         WINED3D_ATR_SIZE(position2), \
                         WINED3D_ATR_GLTYPE(position2), \
                         WINED3D_ATR_NORMALIZED(position2), \
                         sd->u.s.position2.dwStride, \
                         ((char *)sd->u.s.position2.lpData) + \
                         WINED3D_ATR_SIZE(position2) * WINED3D_ATR_TYPESIZE(position2) * _lookupNumber)); \
-        GL_EXTCALL(glEnableVertexAttribArrayARB(arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + _lookupNumber])); \
+        GL_EXTCALL(glEnableVertexAttribArrayARB(idx)); \
     }
 
 /* Generate some lookup tables */
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 92f6851..59a0b05 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -168,7 +168,9 @@ static void shader_glsl_get_register_nam
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) arg->shader;
     BOOL pshader = shader_is_pshader_version(This->baseShader.hex_version);
     char tmpStr[50];
-    
+
+    *is_color = FALSE;   
+ 
     switch (regtype) {
     case D3DSPR_TEMP:
         sprintf(tmpStr, "R%lu", reg);
@@ -182,10 +184,19 @@ static void shader_glsl_get_register_nam
             }
         } else {
             IWineD3DVertexShaderImpl *vshader = (IWineD3DVertexShaderImpl*) arg->shader;
-            if (reg == vshader->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
-                || reg == vshader->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
-                (*is_color) = TRUE;
-            }
+
+            if (vshader->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] &&
+                reg == (vshader->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] & D3DSP_REGNUM_MASK))
+                *is_color = TRUE;
+
+            if (vshader->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] &&
+                reg == (vshader->arrayUsageMap[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, arrayUsageMap is not initialized
+              * in that case - how can we know if an input contains color data or not? */
+
             sprintf(tmpStr, "attrib%lu", reg);
         } 
         break;
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index aaee6b1..455124a 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -1305,6 +1305,17 @@ inline static VOID IWineD3DPixelShaderIm
     IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
     SHADER_BUFFER buffer;
 
+    /* First pass: figure out which registers are used, what the semantics are, etc.. */
+    shader_reg_maps reg_maps;
+    DWORD semantics_in[WINED3DSHADERDECLUSAGE_MAX_USAGE];
+
+    memset(&reg_maps, 0, sizeof(shader_reg_maps));
+    memset(semantics_in, 0, WINED3DSHADERDECLUSAGE_MAX_USAGE * sizeof(DWORD));
+    reg_maps.semantics_in = semantics_in;
+    reg_maps.semantics_out = NULL;
+    shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps, pFunction);
+    /* FIXME: validate against OpenGL */
+
 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
@@ -1325,8 +1336,8 @@ #endif
         /* Create the hw GLSL shader object and assign it as the baseShader.prgId */
         GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
 
-        /* Generate the bulk of the shader code */
-        generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
+        /* Base Shader Body */
+        shader_generate_main( (IWineD3DBaseShader*) This, &buffer, &reg_maps, pFunction);
 
         /* Pixel shaders < 2.0 place the resulting color in R0 implicitly */
         if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
@@ -1354,9 +1365,8 @@ #endif
         shader_addline(&buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
         shader_addline(&buffer, "PARAM one = { 1.0, 1.0, 1.0, 1.0 };\n");
 
-        /** Call the base shader generation routine to generate most 
-            of the pixel shader string for us */
-        generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
+        /* Base Shader Body */
+        shader_generate_main( (IWineD3DBaseShader*) This, &buffer, &reg_maps, pFunction);
 
         if (This->baseShader.hex_version < D3DPS_VERSION(2,0))
             shader_addline(&buffer, "MOV result.color, R0;\n");
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index dd066c3..17f364b 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -649,10 +649,19 @@ inline static void vshader_program_add_p
     strcat(hwLine, tmpReg);
     break;
   case D3DSPR_INPUT:
-    if (reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]
-        || reg == This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR]) {
+
+    if (This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] &&
+        reg == (This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE] & D3DSP_REGNUM_MASK))
         is_color = TRUE;
-    }
+
+    if (This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] &&
+        reg == (This->arrayUsageMap[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, arrayUsageMap is 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;
@@ -700,109 +709,6 @@ inline static void vshader_program_add_p
   }
 }
 
-static void vshader_parse_input_decl_usage(IWineD3DVertexShaderImpl *This, INT usage, INT arrayNo)
-{
-    switch(usage & 0xFFFF) {
-        case D3DDECLUSAGE_POSITION:
-            if((usage & 0xF0000) >> 16 == 0) { /* tween data */
-                TRACE("Setting position to %d\n", arrayNo);
-                This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION]     = arrayNo;
-            } else {
-                /* TODO: position indexes go from 0-8!!*/
-                TRACE("Setting position 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
-                /* robots uses positions up to 8, the position arrays are just packed.*/
-                if ((usage & 0xF0000) >> 16 > 1) {
-                    TRACE("Loaded for position %d (greater than 2)\n", (usage & 0xF0000) >> 16);
-                }
-                This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITION2 + ((usage & 0xF0000) >> 16) -1] = arrayNo;
-            }
-        break;
-        case D3DDECLUSAGE_BLENDINDICES:
-            /* not supported by openGL */
-            TRACE("Setting BLENDINDICES to %d\n", arrayNo);
-            This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDINDICES] = arrayNo;
-            if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended BLENDINDICES\n");
-        break;
-        case D3DDECLUSAGE_BLENDWEIGHT:
-            TRACE("Setting BLENDWEIGHT to %d\n", arrayNo);
-            This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BLENDWEIGHT]  = arrayNo;
-            if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended blend weights\n");
-        break;
-        case D3DDECLUSAGE_NORMAL:
-            if((usage & 0xF0000) >> 16 == 0) { /* tween data */
-                TRACE("Setting normal to %d\n", arrayNo);
-                This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL]   = arrayNo;
-            } else {
-                TRACE("Setting normal 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
-                This->arrayUsageMap[WINED3DSHADERDECLUSAGE_NORMAL2]   = arrayNo;
-            }
-        break;
-        case D3DDECLUSAGE_PSIZE:
-            TRACE("Setting PSIZE to %d\n", arrayNo);
-            This->arrayUsageMap[WINED3DSHADERDECLUSAGE_PSIZE]        = arrayNo;
-            if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended PSIZE\n");
-        break;
-        case D3DDECLUSAGE_COLOR:
-            if((usage & 0xF0000) >> 16 == 0)  {
-                TRACE("Setting DIFFUSE to %d\n", arrayNo);
-                This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DIFFUSE]  = arrayNo;
-            } else {
-                TRACE("Setting SPECULAR to %d\n", arrayNo);
-                This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SPECULAR] = arrayNo;
-            }
-        break;
-        case D3DDECLUSAGE_TEXCOORD:
-            /* only 7 texture coords have been designed for, so run a quick sanity check */
-            if ((usage & 0xF0000) >> 16 > 7) {
-                FIXME("(%p) : Program uses texture coordinate %d but only 0-7 have been implemented\n", This, (usage & 0xF0000) >> 16);
-            } else {
-                TRACE("Setting TEXCOORD %d  to %d\n", ((usage & 0xF0000) >> 16), arrayNo);
-                This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TEXCOORD0 + ((usage & 0xF0000) >> 16)] = arrayNo;
-            }
-        break;
-        /* The following aren't supported by openGL,
-            if we get them then everything needs to be mapped to numbered attributes instead of named ones.
-            this should be caught in the first pass */
-        case D3DDECLUSAGE_TANGENT:
-            TRACE("Setting TANGENT to %d\n", arrayNo);
-            This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TANGENT]      = arrayNo;
-        break;
-        case D3DDECLUSAGE_BINORMAL:
-            TRACE("Setting BINORMAL to %d\n", arrayNo);
-            This->arrayUsageMap[WINED3DSHADERDECLUSAGE_BINORMAL]     = arrayNo;
-        break;
-        case D3DDECLUSAGE_TESSFACTOR:
-            TRACE("Setting TESSFACTOR to %d\n", arrayNo);
-            This->arrayUsageMap[WINED3DSHADERDECLUSAGE_TESSFACTOR]   = arrayNo;
-        break;
-        case D3DDECLUSAGE_POSITIONT:
-            if((usage & 0xF0000) >> 16 == 0) { /* tween data */
-                FIXME("Setting positiont to %d\n", arrayNo);
-                This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT] = arrayNo;
-            } else {
-                FIXME("Setting positiont 2 to %d because usage = %d\n", arrayNo, (usage & 0xF0000) >> 16);
-                This->arrayUsageMap[WINED3DSHADERDECLUSAGE_POSITIONT2] = arrayNo;
-            if ((usage & 0xF0000) >> 16 != 0) FIXME("Extended positiont\n");
-            }
-        break;
-        case D3DDECLUSAGE_FOG:
-            /* supported by OpenGL */
-            TRACE("Setting FOG to %d\n", arrayNo);
-            This->arrayUsageMap[WINED3DSHADERDECLUSAGE_FOG]          = arrayNo;
-        break;
-        case D3DDECLUSAGE_DEPTH:
-            TRACE("Setting DEPTH to %d\n", arrayNo);
-            This->arrayUsageMap[WINED3DSHADERDECLUSAGE_DEPTH]        = arrayNo;
-        break;
-        case D3DDECLUSAGE_SAMPLE:
-            TRACE("Setting SAMPLE to %d\n", arrayNo);
-            This->arrayUsageMap[WINED3DSHADERDECLUSAGE_SAMPLE]       = arrayNo;
-        break;
-        default:
-        FIXME("Unrecognised dcl %08x", usage & 0xFFFF);
-    }
-}
-
 static void vshader_set_version(
       IWineD3DVertexShaderImpl *This,
       DWORD version) {
@@ -931,6 +837,17 @@ inline static VOID IWineD3DVertexShaderI
     IWineD3DVertexShaderImpl *This = (IWineD3DVertexShaderImpl *)iface;
     SHADER_BUFFER buffer;
 
+    /* First pass: figure out which registers are used, what the semantics are, etc.. */
+    shader_reg_maps reg_maps;
+    DWORD semantics_out[WINED3DSHADERDECLUSAGE_MAX_USAGE];
+
+    memset(&reg_maps, 0, sizeof(shader_reg_maps));
+    memset(semantics_out, 0, WINED3DSHADERDECLUSAGE_MAX_USAGE * sizeof(DWORD));
+    reg_maps.semantics_in = This->arrayUsageMap;
+    reg_maps.semantics_out = semantics_out;
+    shader_get_registers_used((IWineD3DBaseShader*) This, &reg_maps, pFunction);
+    /* FIXME: validate against OpenGL */
+
 #if 0 /* FIXME: Use the buffer that is held by the device, this is ok since fixups will be skipped for software shaders
         it also requires entering a critical section but cuts down the runtime footprint of wined3d and any memory fragmentation that may occur... */
     if (This->device->fixupVertexBufferSize < SHADER_PGMSIZE) {
@@ -951,8 +868,8 @@ #endif
         /* Create the hw GLSL shader program and assign it as the baseShader.prgId */
         GLhandleARB shader_obj = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
 
-        /* Generate the bulk of the shader code */
-        generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
+        /* Base Shader Body */
+        shader_generate_main( (IWineD3DBaseShader*) This, &buffer, &reg_maps, pFunction);
 
         shader_addline(&buffer, "}\n\0");
 
@@ -974,9 +891,8 @@ #endif
             This->baseShader.limits.constant_float = 
                 min(95, This->baseShader.limits.constant_float);
 
-        /** Call the base shader generation routine to generate most 
-            of the vertex shader string for us */
-        generate_base_shader( (IWineD3DBaseShader*) This, &buffer, pFunction);
+        /* Base Shader Body */
+        shader_generate_main( (IWineD3DBaseShader*) This, &buffer, &reg_maps, pFunction);
 
         shader_addline(&buffer, "END\n\0"); 
 
@@ -1408,10 +1324,6 @@ static HRESULT WINAPI IWineD3DVertexShad
     DWORD i;
     TRACE("(%p) : Parsing programme\n", This);
 
-    /* Initialise vertex input arrays */
-    for (i = 0; i < WINED3DSHADERDECLUSAGE_MAX_USAGE; i++)
-        This->arrayUsageMap[i] = -1;
-
     if (NULL != pToken) {
         while (D3DVS_END() != *pToken) {
             if (shader_is_vshader_version(*pToken)) { /** version */
@@ -1446,10 +1358,7 @@ static HRESULT WINAPI IWineD3DVertexShad
 
                     DWORD usage = *pToken;
                     DWORD param = *(pToken + 1);
-                    DWORD regtype = shader_get_regtype(param);
 
-                    if (regtype == D3DSPR_INPUT)
-                        vshader_parse_input_decl_usage(This, usage, param & D3DSP_REGNUM_MASK);
                     shader_program_dump_decl_usage(usage, param);
                     shader_dump_ins_modifiers(param);
                     TRACE(" ");
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f449d7e..69438f4 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1252,9 +1252,14 @@ typedef struct shader_reg_maps {
     DWORD texcoord;
     DWORD temporary;
     DWORD address;
+
     /* Constants */
     CHAR constantsF[256];  /* TODO: Make this dynamic */
     /* TODO: Integer and bool constants */
+
+    DWORD* semantics_in;
+    DWORD* semantics_out;
+
 } shader_reg_maps;
 
 #define SHADER_PGMSIZE 65535
@@ -1368,9 +1373,15 @@ extern void shader_program_dump_decl_usa
     DWORD dcl,
     DWORD param);
 
-extern void generate_base_shader(
+extern void shader_get_registers_used(
+    IWineD3DBaseShader *iface,
+    shader_reg_maps* reg_maps,
+    CONST DWORD* pToken);
+
+extern void shader_generate_main(
     IWineD3DBaseShader *iface,
     SHADER_BUFFER* buffer,
+    shader_reg_maps* reg_maps,
     CONST DWORD* pFunction);
 
 extern void shader_dump_ins_modifiers(
@@ -1433,7 +1444,7 @@ typedef struct IWineD3DVertexShaderImpl 
     DWORD usage;
 
     /* vertex declaration array mapping */
-    INT arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE];
+    DWORD arrayUsageMap[WINED3DSHADERDECLUSAGE_MAX_USAGE];
  
     /* run time datas...  */
     VSHADERDATA                *data;
-- 
1.3.3



More information about the wine-patches mailing list