wined3d: Create a separate function to record register usage.

Henri Verbeet hverbeet at codeweavers.com
Tue Apr 28 02:53:28 CDT 2009


---
 dlls/wined3d/baseshader.c      |  146 ++++++++++++++++++++++-----------------
 dlls/wined3d/glsl_shader.c     |   20 +++--
 dlls/wined3d/wined3d_private.h |    3 +-
 3 files changed, 96 insertions(+), 73 deletions(-)

diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index e9cb760..21c99fc 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -468,6 +468,78 @@ static void shader_delete_constant_list(struct list* clist) {
     list_init(clist);
 }
 
+static void shader_record_register_usage(IWineD3DBaseShaderImpl *This, struct shader_reg_maps *reg_maps,
+        DWORD register_type, UINT register_idx, BOOL has_rel_addr, BOOL pshader)
+{
+    switch (register_type)
+    {
+        case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */
+            if (pshader) reg_maps->texcoord[register_idx] = 1;
+            else reg_maps->address[register_idx] = 1;
+            break;
+
+        case WINED3DSPR_TEMP:
+            reg_maps->temporary[register_idx] = 1;
+            break;
+
+        case WINED3DSPR_INPUT:
+            if (!pshader) reg_maps->attributes[register_idx] = 1;
+            else
+            {
+                if (has_rel_addr)
+                {
+                    /* If relative addressing is used, we must assume that all registers
+                     * are used. Even if it is a construct like v3[aL], we can't assume
+                     * that v0, v1 and v2 aren't read because aL can be negative */
+                    unsigned int i;
+                    for (i = 0; i < MAX_REG_INPUT; ++i)
+                    {
+                        ((IWineD3DPixelShaderImpl *)This)->input_reg_used[i] = TRUE;
+                    }
+                }
+                else
+                {
+                    ((IWineD3DPixelShaderImpl *)This)->input_reg_used[register_idx] = TRUE;
+                }
+            }
+            break;
+
+        case WINED3DSPR_RASTOUT:
+            if (register_idx == 1) reg_maps->fog = 1;
+            break;
+
+        case WINED3DSPR_MISCTYPE:
+            if (pshader && register_idx == 0) reg_maps->vpos = 1;
+            break;
+
+        case WINED3DSPR_CONST:
+            if (has_rel_addr)
+            {
+                if (!pshader)
+                {
+                    if (register_idx <= ((IWineD3DVertexShaderImpl *)This)->min_rel_offset)
+                        ((IWineD3DVertexShaderImpl *)This)->min_rel_offset = register_idx;
+                    else if (register_idx >= ((IWineD3DVertexShaderImpl *)This)->max_rel_offset)
+                        ((IWineD3DVertexShaderImpl *)This)->max_rel_offset = register_idx;
+                }
+                reg_maps->usesrelconstF = TRUE;
+            }
+            break;
+
+        case WINED3DSPR_CONSTINT:
+            reg_maps->integer_constants |= (1 << register_idx);
+            break;
+
+        case WINED3DSPR_CONSTBOOL:
+            reg_maps->boolean_constants |= (1 << register_idx);
+            break;
+
+        default:
+            TRACE("Not recording register of type %#x and idx %u\n", register_type, register_idx);
+            break;
+    }
+}
+
 /* Note that this does not count the loop register
  * as an address register. */
 
@@ -481,7 +553,6 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
     unsigned int cur_loop_depth = 0, max_loop_depth = 0;
     const DWORD* pToken = byte_code;
     char pshader;
-    unsigned int intconst = 0, boolconst = 0;
 
     /* There are some minor differences between pixel and vertex shaders */
 
@@ -625,7 +696,7 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
             pToken += param_size;
 
             /* Rep and Loop always use an integer constant for the control parameters */
-            intconst |= (1 << (reg & WINED3DSP_REGNUM_MASK));
+            reg_maps->integer_constants |= (1 << (reg & WINED3DSP_REGNUM_MASK));
         }
         else if (ins.handler_idx == WINED3DSIH_ENDLOOP
                 || ins.handler_idx == WINED3DSIH_ENDREP)
@@ -708,70 +779,19 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
                 regtype = shader_get_regtype(param);
                 reg = param & WINED3DSP_REGNUM_MASK;
 
-                if (WINED3DSPR_TEXTURE == regtype) { /* vs: WINED3DSPR_ADDR */
-
-                    if (pshader)
-                        reg_maps->texcoord[reg] = 1;
-                    else
-                        reg_maps->address[reg] = 1;
-                }
-
-                else if (WINED3DSPR_TEMP == regtype)
-                    reg_maps->temporary[reg] = 1;
-
-                else if (WINED3DSPR_INPUT == regtype) {
-                    if( !pshader)
-                        reg_maps->attributes[reg] = 1;
-                    else {
-                        if(param & WINED3DSHADER_ADDRMODE_RELATIVE) {
-                            /* If relative addressing is used, we must assume that all registers
-                             * are used. Even if it is a construct like v3[aL], we can't assume
-                             * that v0, v1 and v2 aren't read because aL can be negative
-                             */
-                            unsigned int i;
-                            for(i = 0; i < MAX_REG_INPUT; i++) {
-                                ((IWineD3DPixelShaderImpl *) This)->input_reg_used[i] = TRUE;
-                            }
-                        } else {
-                            ((IWineD3DPixelShaderImpl *) This)->input_reg_used[reg] = TRUE;
-                        }
-                    }
-                }
-
-                else if (WINED3DSPR_RASTOUT == regtype && reg == 1)
-                    reg_maps->fog = 1;
-
-                else if (WINED3DSPR_MISCTYPE == regtype && reg == 0 && pshader)
-                    reg_maps->vpos = 1;
-
-                else if(WINED3DSPR_CONST == regtype) {
-                    if(param & WINED3DSHADER_ADDRMODE_RELATIVE) {
-                        if(!pshader) {
-                            if(reg <= ((IWineD3DVertexShaderImpl *) This)->min_rel_offset) {
-                                ((IWineD3DVertexShaderImpl *) This)->min_rel_offset = reg;
-                            } else if(reg >= ((IWineD3DVertexShaderImpl *) This)->max_rel_offset) {
-                                ((IWineD3DVertexShaderImpl *) This)->max_rel_offset = reg;
-                            }
-                        }
-                        reg_maps->usesrelconstF = TRUE;
-                    }
-                }
-                else if(WINED3DSPR_CONSTINT == regtype) {
-                    intconst |= (1 << reg);
-                }
-                else if(WINED3DSPR_CONSTBOOL == regtype) {
-                    boolconst |= (1 << reg);
-                }
-
-                /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and is used
-                 * in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel shaders because TECRDOUT
-                 * isn't used in them, but future register types might cause issues
-                 */
-                else if (WINED3DSPR_TEXCRDOUT == regtype && i == 0 /* Only look at writes */
+                /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
+                 * is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
+                 * shaders because TECRDOUT isn't used in them, but future register types might cause issues */
+                if (regtype == WINED3DSPR_TEXCRDOUT && i == 0 /* Only look at writes */
                         && !pshader && WINED3DSHADER_VERSION_MAJOR(shader_version) < 3)
                 {
                     reg_maps->texcoord_mask[reg] |= shader_get_writemask(param);
                 }
+                else
+                {
+                    shader_record_register_usage(This, reg_maps, regtype, reg,
+                            param & WINED3DSHADER_ADDRMODE_RELATIVE, pshader);
+                }
             }
         }
     }
@@ -779,8 +799,6 @@ HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, struct shader_reg_m
     reg_maps->loop_depth = max_loop_depth;
 
     This->baseShader.functionLength = ((char *)pToken - (char *)byte_code);
-    This->baseShader.num_bool_consts = count_bits(boolconst);
-    This->baseShader.num_int_consts = count_bits(intconst);
 
     return WINED3D_OK;
 }
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 6aca4da..329ae94 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -558,13 +558,15 @@ static void shader_glsl_load_constants(
                 prog->vuniformF_locations, &priv->vconst_heap, priv->stack, constant_version);
 
         /* Load DirectX 9 integer constants/uniforms for vertex shader */
-        if(vshader->baseShader.num_int_consts) {
+        if (vshader->baseShader.reg_maps.integer_constants)
+        {
             shader_glsl_load_constantsI(vshader, gl_info, prog->vuniformI_locations,
                     stateBlock->vertexShaderConstantI, stateBlock->changed.vertexShaderConstantsI);
         }
 
         /* Load DirectX 9 boolean constants/uniforms for vertex shader */
-        if(vshader->baseShader.num_bool_consts) {
+        if (vshader->baseShader.reg_maps.boolean_constants)
+        {
             shader_glsl_load_constantsB(vshader, gl_info, programId,
                     stateBlock->vertexShaderConstantB, stateBlock->changed.vertexShaderConstantsB);
         }
@@ -583,13 +585,15 @@ static void shader_glsl_load_constants(
                 prog->puniformF_locations, &priv->pconst_heap, priv->stack, constant_version);
 
         /* Load DirectX 9 integer constants/uniforms for pixel shader */
-        if(pshader->baseShader.num_int_consts) {
+        if (pshader->baseShader.reg_maps.integer_constants)
+        {
             shader_glsl_load_constantsI(pshader, gl_info, prog->puniformI_locations,
                     stateBlock->pixelShaderConstantI, stateBlock->changed.pixelShaderConstantsI);
         }
 
         /* Load DirectX 9 boolean constants/uniforms for pixel shader */
-        if(pshader->baseShader.num_bool_consts) {
+        if (pshader->baseShader.reg_maps.boolean_constants)
+        {
             shader_glsl_load_constantsB(pshader, gl_info, programId,
                     stateBlock->pixelShaderConstantB, stateBlock->changed.pixelShaderConstantsB);
         }
@@ -748,12 +752,12 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
                  * (Unfortunately the Nvidia driver doesn't store 128 and -128 in one float
                  */
                 max_constantsF = GL_LIMITS(vshader_constantsF) - 3;
-                max_constantsF -= This->baseShader.num_int_consts;
+                max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants);
                 /* Strictly speaking a bool only uses one scalar, but the nvidia(Linux) compiler doesn't pack them properly,
                  * so each scalar requires a full vec4. We could work around this by packing the booleans ourselves, but
                  * for now take this into account when calculating the number of available constants
                  */
-                max_constantsF -= This->baseShader.num_bool_consts;
+                max_constantsF -= count_bits(This->baseShader.reg_maps.boolean_constants);
                 /* Set by driver quirks in directx.c */
                 max_constantsF -= GLINFO_LOCATION.reserved_glsl_constants;
             } else {
@@ -767,10 +771,10 @@ static void shader_generate_glsl_declarations(IWineD3DBaseShader *iface, const s
     /* Always declare the full set of constants, the compiler can remove the unused ones because d3d doesn't(yet)
      * support indirect int and bool constant addressing. This avoids problems if the app uses e.g. i0 and i9.
      */
-    if (This->baseShader.limits.constant_int > 0 && This->baseShader.num_int_consts)
+    if (This->baseShader.limits.constant_int > 0 && This->baseShader.reg_maps.integer_constants)
         shader_addline(buffer, "uniform ivec4 %cI[%u];\n", prefix, This->baseShader.limits.constant_int);
 
-    if (This->baseShader.limits.constant_bool > 0 && This->baseShader.num_bool_consts)
+    if (This->baseShader.limits.constant_bool > 0 && This->baseShader.reg_maps.boolean_constants)
         shader_addline(buffer, "uniform bool %cB[%u];\n", prefix, This->baseShader.limits.constant_bool);
 
     if(!pshader) {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 59b3b60..6a22c60 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -416,6 +416,8 @@ typedef struct shader_reg_maps
     char attributes[MAX_ATTRIBS];           /* vertex */
     char labels[MAX_LABELS];                /* pixel, vertex */
     DWORD texcoord_mask[MAX_REG_TEXCRD];    /* vertex < 3.0 */
+    WORD integer_constants;                 /* MAX_CONST_I, 16 */
+    WORD boolean_constants;                 /* MAX_CONST_B, 16 */
 
     /* Sampler usage tokens
      * Use 0 as default (bit 31 is always 1 on a valid token) */
@@ -2318,7 +2320,6 @@ typedef struct IWineD3DBaseShaderClass
     UINT                            functionLength;
     UINT                            cur_loop_depth, cur_loop_regno;
     BOOL                            load_local_constsF;
-    BOOL                            num_bool_consts, num_int_consts;
 
     /* Type of shader backend */
     int shader_mode;
-- 
1.6.0.6



--------------080902020105020905020707--



More information about the wine-patches mailing list