Stefan Dösinger : wined3d: Nested loop support.

Alexandre Julliard julliard at winehq.org
Thu Oct 4 06:21:20 CDT 2007


Module: wine
Branch: master
Commit: 3f16f029405f7a243b4b42c81d617463b252b81e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3f16f029405f7a243b4b42c81d617463b252b81e

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Fri Sep 14 13:21:52 2007 +0200

wined3d: Nested loop support.

---

 dlls/wined3d/baseshader.c      |   12 ++++++++++--
 dlls/wined3d/glsl_shader.c     |   40 ++++++++++++++++++++++++++++++----------
 dlls/wined3d/wined3d_private.h |    5 +++--
 3 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 67888b2..cba756e 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -193,6 +193,7 @@ HRESULT shader_get_registers_used(
     IWineD3DStateBlockImpl *stateBlock) {
 
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
+    unsigned int cur_loop_depth = 0, max_loop_depth = 0;
 
     /* There are some minor differences between pixel and vertex shaders */
     char pshader = shader_is_pshader_version(This->baseShader.hex_version);
@@ -305,9 +306,15 @@ HRESULT shader_get_registers_used(
         /* If there's a loop in the shader */
         } else if (WINED3DSIO_LOOP == curOpcode->opcode ||
                    WINED3DSIO_REP == curOpcode->opcode) {
-            reg_maps->loop = 1;
+            cur_loop_depth++;
+            if(cur_loop_depth > max_loop_depth)
+                max_loop_depth = cur_loop_depth;
             pToken += curOpcode->num_params;
-   
+
+        } else if (WINED3DSIO_ENDLOOP == curOpcode->opcode ||
+                   WINED3DSIO_ENDREP == curOpcode->opcode) {
+            cur_loop_depth--;
+
         /* For subroutine prototypes */
         } else if (WINED3DSIO_LABEL == curOpcode->opcode) {
 
@@ -424,6 +431,7 @@ HRESULT shader_get_registers_used(
             }
         }
     }
+    reg_maps->loop_depth = max_loop_depth;
 
     return WINED3D_OK;
 }
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index f05cd72..8a0603b 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -640,12 +640,12 @@ void shader_generate_glsl_declarations(
             shader_addline(buffer, "attribute vec4 attrib%i;\n", i);
     }
 
-    /* Declare loop register aL */
-    if (reg_maps->loop) {
-        shader_addline(buffer, "int aL;\n");
-        shader_addline(buffer, "int tmpInt;\n");
+    /* Declare loop registers aLx */
+    for (i = 0; i < reg_maps->loop_depth; i++) {
+        shader_addline(buffer, "int aL%u;\n", i);
+        shader_addline(buffer, "int tmpInt%u;\n", i);
     }
-    
+
     /* Temporary variables for matrix operations */
     shader_addline(buffer, "vec4 tmp0;\n");
     shader_addline(buffer, "vec4 tmp1;\n");
@@ -829,7 +829,7 @@ static void shader_glsl_get_register_name(
         }
     break;
     case WINED3DSPR_LOOP:
-        sprintf(tmpStr, "aL");
+        sprintf(tmpStr, "aL%u", This->baseShader.cur_loop_regno - 1);
     break;
     case WINED3DSPR_SAMPLER:
         if (pshader)
@@ -1817,22 +1817,42 @@ void shader_glsl_sincos(SHADER_OPCODE_ARG* arg) {
 /* FIXME: I don't think nested loops will work correctly this way. */
 void shader_glsl_loop(SHADER_OPCODE_ARG* arg) {
     glsl_src_param_t src1_param;
+    IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
 
     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_ALL, &src1_param);
-  
-    shader_addline(arg->buffer, "for (tmpInt = 0, aL = %s.y; tmpInt < %s.x; tmpInt++, aL += %s.z) {\n",
-            src1_param.reg_name, src1_param.reg_name, src1_param.reg_name);
+
+    shader_addline(arg->buffer, "for (tmpInt%u = 0, aL%u = %s.y; tmpInt%u < %s.x; tmpInt%u++, aL%u += %s.z) {\n",
+                   shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_regno,
+                   src1_param.reg_name, shader->baseShader.cur_loop_depth, src1_param.reg_name,
+                   shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_regno, src1_param.reg_name);
+
+    shader->baseShader.cur_loop_depth++;
+    shader->baseShader.cur_loop_regno++;
 }
 
 void shader_glsl_end(SHADER_OPCODE_ARG* arg) {
+    IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
+
     shader_addline(arg->buffer, "}\n");
+
+    if(arg->opcode->opcode == WINED3DSIO_ENDLOOP) {
+        shader->baseShader.cur_loop_depth--;
+        shader->baseShader.cur_loop_regno--;
+    }
+    if(arg->opcode->opcode == WINED3DSIO_ENDREP) {
+        shader->baseShader.cur_loop_depth--;
+    }
 }
 
 void shader_glsl_rep(SHADER_OPCODE_ARG* arg) {
+    IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
     glsl_src_param_t src0_param;
 
     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
-    shader_addline(arg->buffer, "for (tmpInt = 0; tmpInt < %s; tmpInt++) {\n", src0_param.param_str);
+    shader_addline(arg->buffer, "for (tmpInt%d = 0; tmpInt%d < %s; tmpInt%d++) {\n",
+                   shader->baseShader.cur_loop_depth, shader->baseShader.cur_loop_depth,
+                   src0_param.param_str, shader->baseShader.cur_loop_depth);
+    shader->baseShader.cur_loop_depth++;
 }
 
 void shader_glsl_if(SHADER_OPCODE_ARG* arg) {
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index da4a90c..431160d 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1654,8 +1654,8 @@ typedef struct shader_reg_maps {
     char bumpmat, luminanceparams;
     char usesnrm, vpos;
 
-    /* Whether or not a loop is used in this shader */
-    char loop;
+    /* Whether or not loops are used in this shader, and nesting depth */
+    unsigned loop_depth;
 
     /* Whether or not this shader uses fog */
     char fog;
@@ -1885,6 +1885,7 @@ typedef struct IWineD3DBaseShaderClass
     UINT                            functionLength;
     GLuint                          prgId;
     BOOL                            is_compiled;
+    UINT                            cur_loop_depth, cur_loop_regno;
 
     /* Type of shader backend */
     int shader_mode;




More information about the wine-cvs mailing list