diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 2d1c5d99118..df0ac0c8871 100644 --- a/dlls/wined3d/baseshader.c +++ b/dlls/wined3d/baseshader.c @@ -422,8 +422,24 @@ HRESULT shader_get_registers_used( else if (WINED3DSPR_TEMP == regtype) reg_maps->temporary[reg] = 1; - else if (WINED3DSPR_INPUT == regtype && !pshader) - reg_maps->attributes[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; diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 3dfca51a581..4083d56207e 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -2670,6 +2670,9 @@ static void handle_ps3_input(SHADER_BUFFER *buffer, semantic *semantics_in, sema if(map[i] >= (GL_LIMITS(glsl_varyings) / 4)) { FIXME("More input varyings declared than supported, expect issues\n"); continue; + } else if(map[i] == -1) { + /* Declared, but not read register */ + continue; } register_token = semantics_in[i].reg; diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c index daeae42b000..138e4190cec 100644 --- a/dlls/wined3d/pixelshader.c +++ b/dlls/wined3d/pixelshader.c @@ -543,7 +543,7 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) > 1) { shader_reg_maps *reg_maps = &This->baseShader.reg_maps; HRESULT hr; - unsigned int i; + unsigned int i, j, highest_reg_used = 0, num_regs_used = 0; /* Second pass: figure out which registers are used, what the semantics are, etc.. */ memset(reg_maps, 0, sizeof(shader_reg_maps)); @@ -553,7 +553,38 @@ static HRESULT WINAPI IWineD3DPixelShaderImpl_SetFunction(IWineD3DPixelShader *i /* FIXME: validate reg_maps against OpenGL */ for(i = 0; i < MAX_REG_INPUT; i++) { - This->input_reg_map[i] = i; + if(This->input_reg_used[i]) { + num_regs_used++; + highest_reg_used = i; + } + } + + /* Don't do any register mapping magic if it is not needed, or if we can't + * achive anything anyway + */ + if(highest_reg_used < (GL_LIMITS(glsl_varyings) / 4) || + num_regs_used >= (GL_LIMITS(glsl_varyings) / 4) ) { + if(num_regs_used >= (GL_LIMITS(glsl_varyings) / 4)) { + /* This happens with relative addressing. The input mapper function + * warns about this if the higher registers are declared too, so + * don't write a FIXME here + */ + WARN("More varying registers used than supported\n"); + } + + for(i = 0; i < MAX_REG_INPUT; i++) { + This->input_reg_map[i] = i; + } + } else { + j = 0; + for(i = 0; i < MAX_REG_INPUT; i++) { + if(This->input_reg_used[i]) { + This->input_reg_map[i] = j; + j++; + } else { + This->input_reg_map[i] = -1; + } + } } } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 1fab9aabf78..56ba5693309 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -2084,6 +2084,7 @@ typedef struct IWineD3DPixelShaderImpl { /* Pixel shader input semantics */ semantic semantics_in [MAX_REG_INPUT]; DWORD input_reg_map[MAX_REG_INPUT]; + BOOL input_reg_used[MAX_REG_INPUT]; /* run time data */ PSHADERDATA *data;