[WINED3D 2/5] Resend: Merge register counting pass

Ivan Gyurdiev ivg2 at cornell.edu
Tue May 9 17:03:09 CDT 2006


This is a resend. The patch was not modified from the original submission.

Changelog was:
============
This patch merges the vertex first pass and the pixel first pass.
The pixel shader code was used, the vertex shader code was removed.

A check for NULL opcode (unhandled) was borrowed from the vertex 
code,since this was bugzilla'd as causing crashes.
-------------- next part --------------
---

 dlls/wined3d/baseshader.c      |   81 +++++++++++++++++++++++++++
 dlls/wined3d/pixelshader.c     |   59 --------------------
 dlls/wined3d/vertexshader.c    |  118 +++++-----------------------------------
 dlls/wined3d/wined3d_private.h |    6 ++
 4 files changed, 104 insertions(+), 160 deletions(-)

20909871737f9a17d9a2e5b7ce4d786e5a163eaf
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 7f34bfd..1691151 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -27,6 +27,15 @@ #include "wined3d_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
 
+inline static BOOL shader_is_version_token(DWORD token) {
+    return 0xFFFF0000 == (token & 0xFFFF0000) || 
+           0xFFFE0000 == (token & 0xFFFF0000);
+}
+
+inline static BOOL shader_is_comment_token(DWORD token) {
+    return D3DSIO_COMMENT == (token & D3DSI_OPCODE_MASK);
+}
+
 int shader_addline(
     SHADER_BUFFER* buffer,  
     const char *format, ...) {
@@ -78,4 +87,76 @@ const SHADER_OPCODE* shader_get_opcode(
     return NULL;
 }
 
+/* Note: For vertex shaders,
+ * texUsed = addrUsed, and 
+ * D3DSPR_TEXTURE = D3DSPR_ADDR. 
+ *
+ * Also note that this does not count the loop register
+ * as an address register. */   
+
+void shader_get_registers_used(
+    IWineD3DBaseShader *iface,
+    CONST DWORD* pToken, 
+    DWORD* tempsUsed, 
+    DWORD* texUsed) {
+
+    if (pToken == NULL)
+        return;
+
+    *tempsUsed = 0;
+    *texUsed = 0;
+
+    while (D3DVS_END() != *pToken) {
+        CONST SHADER_OPCODE* curOpcode;
+
+        /* Skip version */
+        if (shader_is_version_token(*pToken)) {
+             ++pToken;
+             continue;
+
+        /* Skip comments */
+        } else if (shader_is_comment_token(*pToken)) {
+             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
+             ++pToken;
+             pToken += comment_len;
+             continue;
+        }
+
+        /* Fetch opcode */
+        curOpcode = shader_get_opcode(iface, *pToken);
+        ++pToken;
+
+        /* Unhandled opcode, and its parameters */
+        if (NULL == curOpcode) {
+           while (*pToken & 0x80000000)
+               ++pToken;
+           continue;
+
+        /* Skip declarations (for now) */
+        } else if (D3DSIO_DCL == curOpcode->opcode) {
+            pToken += curOpcode->num_params;
+            continue;
+
+        /* Skip definitions (for now) */
+        } else if (D3DSIO_DEF == curOpcode->opcode) {
+            pToken += curOpcode->num_params;
+            continue;
+
+        /* Set texture registers, and temporary registers */
+        } else {
+            int i;
+
+            for (i = 0; i < curOpcode->num_params; ++i) {
+                DWORD regtype = (((*pToken) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT);
+                DWORD reg = (*pToken) & D3DSP_REGNUM_MASK;
+                if (D3DSPR_TEXTURE == regtype)
+                    *texUsed |= (1 << reg);
+                if (D3DSPR_TEMP == regtype)
+                    *tempsUsed |= (1 << reg);
+                ++pToken;
+             }
+        }
+    }
+}
+
 /* TODO: Move other shared code here */
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index d097242..fe69949 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -899,63 +899,6 @@ inline static int gen_input_modifier_lin
     return insert_line;
 }
 
-inline static void pshader_program_get_registers_used(
-      IWineD3DPixelShaderImpl *This,
-      CONST DWORD* pToken, DWORD* tempsUsed, DWORD* texUsed) {
-  
-    if (pToken == NULL)
-        return;
-
-    *tempsUsed = 0;
-    *texUsed = 0;
-
-    while (D3DVS_END() != *pToken) {
-        CONST SHADER_OPCODE* curOpcode;
-
-        /* Skip version */
-        if (pshader_is_version_token(*pToken)) {
-             ++pToken;
-             continue;
-
-        /* Skip comments */
-        } else if (pshader_is_comment_token(*pToken)) {
-             DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
-             ++pToken;
-             pToken += comment_len;
-             continue;
-        }
-
-        /* Fetch opcode */       
-        curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
-        ++pToken;
-
-        /* Skip declarations (for now) */
-        if (D3DSIO_DCL == curOpcode->opcode) {
-            pToken += curOpcode->num_params;
-            continue;
-
-        /* Skip definitions (for now) */
-        } else if (D3DSIO_DEF == curOpcode->opcode) {
-            pToken += curOpcode->num_params;
-            continue;
-
-        /* Set texture registers, and temporary registers */
-        } else {
-            int i;
-                        
-            for (i = 0; i < curOpcode->num_params; ++i) {
-                DWORD regtype = shader_get_regtype(*pToken);
-                DWORD reg = (*pToken) & D3DSP_REGNUM_MASK;
-                if (D3DSPR_TEXTURE == regtype) 
-                    *texUsed |= (1 << reg);
-                if (D3DSPR_TEMP == regtype)
-                    *tempsUsed |= (1 << reg);
-                ++pToken;
-             }
-        }
-    }
-}
-
 void pshader_set_version(
       IWineD3DPixelShaderImpl *This, 
       DWORD version) {
@@ -1055,7 +998,7 @@ #endif
         This->constants[i] = 0;
 
     /* First pass: figure out which temporary and texture registers are used */
-    pshader_program_get_registers_used(This, pToken, &tempsUsed, &texUsed);
+    shader_get_registers_used((IWineD3DBaseShader*) This, pToken, &tempsUsed, &texUsed);
     TRACE("Texture registers used: %#lx, Temp registers used %#lx\n", texUsed, tempsUsed);
 
     /* TODO: check register usage against GL/Directx limits, and fail if they're exceeded */
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 10fd07a..bdad583 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -1150,14 +1150,7 @@ inline static VOID IWineD3DVertexShaderI
     DWORD i;
     SHADER_BUFFER buffer;
     char  tmpLine[255];
-    DWORD nUseAddressRegister = 0;
-    DWORD nUseTempRegister = 0;
-    DWORD regtype;
-    DWORD reg;
-    BOOL tmpsUsed[32];
-#if 0 /* TODO: loope register (just another address register ) */
-    BOOL hasLoops = FALSE;
-#endif
+    DWORD addressUsed, tempsUsed;
 
 #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... */
@@ -1173,87 +1166,11 @@ #endif
     buffer.bsize = 0;
     buffer.lineNo = 0;
 
-    /* set all the tmpsUsed to not used */
-    memset(tmpsUsed, FALSE , sizeof(tmpsUsed));
-
-    /* TODO: renumbering of attributes if the values are higher than the highest supported attribute but the total number of attributes is less than the highest supported attribute */
-    This->highestConstant = -1;
-
-  /**
-   * First pass to determine what we need to declare:
-   *  - Temporary variables
-   *  - Address variables
-   */ 
-    if (NULL != pToken) {
-        while (D3DVS_END() != *pToken) {
-            if (vshader_is_version_token(*pToken)) {
-            /** skip version */
-            ++pToken;
-            continue;
-            }
-            if (vshader_is_comment_token(*pToken)) { /** comment */
-                DWORD comment_len = (*pToken & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
-                ++pToken;
-                pToken += comment_len;
-                continue;
-            }
-            curOpcode = shader_get_opcode((IWineD3DBaseShader*) This, *pToken);
-            ++pToken;
-            /* TODO: dcl's */
-            /* TODO: Consts */
+    /* First pass: figure out which temporary and texture registers are used */
+    shader_get_registers_used((IWineD3DBaseShader*) This, pToken, &tempsUsed, &addressUsed);
+    TRACE("Address registers used: %#lx, Temp registers used %#lx\n", addressUsed, tempsUsed);
 
-            if (NULL == curOpcode) {
-                while (*pToken & 0x80000000) {
-                    FIXME("unrecognized opcode: %08lx\n", *pToken);
-                    /* skip unrecognized opcode */
-                    ++pToken;
-                }
-            } else {
-       
-                /* Skip declarations, handled earlier */
-                if (curOpcode->opcode == D3DSIO_DCL){
-                    pToken += 2;
-                
-                /* Skip definition of immediate constants, handled later */    
-                } else if(curOpcode->opcode == D3DSIO_DEF) {
-                    pToken += 5;
-
-                } else {
-                    /* Check to see if and tmp or addressing redisters are used */
-                    if (curOpcode->num_params > 0) {
-                        regtype = shader_get_regtype(*pToken);
-                        reg = ((*pToken)  & D3DSP_REGNUM_MASK);
-                        if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
-                        if (D3DSPR_TEMP == regtype){
-                            tmpsUsed[reg] = TRUE;
-                            if(nUseTempRegister    <= reg) nUseTempRegister    = reg + 1;
-                        }
-                        ++pToken;
-                        for (i = 1; i < curOpcode->num_params; ++i) {
-                            regtype = shader_get_regtype(*pToken);
-                            reg = ((*pToken)  & D3DSP_REGNUM_MASK);
-                            if (D3DSPR_ADDR == regtype && nUseAddressRegister <= reg) nUseAddressRegister = reg + 1;
-                            if (D3DSPR_TEMP == regtype){
-                                tmpsUsed[reg] = TRUE;
-                                if(nUseTempRegister    <= reg) nUseTempRegister    = reg + 1;
-                            }
-                            ++pToken;
-                        }
-                    }
-                }
-#if 1 /* TODO: if the shaders uses calls or loops then we need to convert the shader into glsl */
-                if (curOpcode->glname == GLNAME_REQUIRE_GLSL) {
-                    FIXME("This shader requires gl shader language support\n");
-#if 0
-                    This->shaderLanguage = GLSHADER_GLSL;
-#endif
-                }
-#endif
-            }
-        }
-    }
-
-    /* TODO: validate
+    /* 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
     */
@@ -1266,17 +1183,18 @@ #endif
     /* FIXME: if jumps are used, use GLSL, else use ARB_vertex_program */
     shader_addline(&buffer, "!!ARBvp1.0\n");
 
-    /* Declare necessary things.
-     * FIXME: replace with a bitmap
-     * FIXME: loop counts as an address register */
+    /* Pre-declare registers */
+    for (i = 0; i < This->baseShader.limits.temporary; i++) {
+        if (tempsUsed & (1 << i))
+            shader_addline(&buffer, "TEMP T%lu;\n", i);
+    }
 
-    for (i = 0; i < nUseTempRegister /* we should check numTemps here */ ; i++) {
-        if (tmpsUsed[i])
-            shader_addline(&buffer, "TEMP T%ld;\n", i);
+    for (i = 0; i < This->baseShader.limits.address; i++) {
+        if (addressUsed & (1 << i))
+            shader_addline(&buffer, "ADDRESS A%ld;\n", i);
     }
-    for (i = 0; i < nUseAddressRegister; i++) 
-        shader_addline(&buffer, "ADDRESS A%ld;\n", i);
 
+    /* Why do we need to alias those? */
     shader_addline(&buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
         This->baseShader.limits.constant_float, 
         This->baseShader.limits.constant_float - 1);            
@@ -1426,12 +1344,8 @@ #endif
         case D3DSIO_MOV:
             /* Address registers must be loaded with the ARL instruction */
             if (shader_get_regtype(*pToken) == D3DSPR_ADDR) {
-                if (((*pToken) & D3DSP_REGNUM_MASK) < nUseAddressRegister) {
-                    strcpy(tmpLine, "ARL");
-                    break;
-                } else
-                FIXME("(%p) Try to load A%ld an undeclared address register!\n", 
-                    This, ((*pToken) & D3DSP_REGNUM_MASK));
+                strcpy(tmpLine, "ARL");
+                break;
             }
             /* fall through */
         case D3DSIO_ADD:
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 0be6398..c5a1e80 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1216,6 +1216,12 @@ extern const SHADER_OPCODE* shader_get_o
     IWineD3DBaseShader *iface, 
     const DWORD code);
 
+extern void shader_get_registers_used(
+    IWineD3DBaseShader *iface,
+    CONST DWORD* pToken,
+    DWORD* tempsUsed,
+    DWORD* texUsed);
+
 inline static int shader_get_regtype(const DWORD param) {
     return (((param & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) |
             ((param & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2));
-- 
1.3.1



More information about the wine-patches mailing list