Module: wine Branch: master Commit: 3f16f029405f7a243b4b42c81d617463b252b81e URL: http://source.winehq.org/git/wine.git/?a=commit;h=3f16f029405f7a243b4b42c81d...
Author: Stefan Dösinger stefan@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;