Module: wine Branch: master Commit: 1b23dd1ba1e4bc557e842d77ce21432e5eda5dae URL: http://source.winehq.org/git/wine.git/?a=commit;h=1b23dd1ba1e4bc557e842d77ce...
Author: Stefan Dösinger stefan@codeweavers.com Date: Tue Nov 6 12:34:22 2007 +0100
wined3d: Implement the varying map.
---
dlls/wined3d/baseshader.c | 20 ++++++++++++++++++-- dlls/wined3d/glsl_shader.c | 3 +++ dlls/wined3d/pixelshader.c | 35 +++++++++++++++++++++++++++++++++-- dlls/wined3d/wined3d_private.h | 1 + 4 files changed, 55 insertions(+), 4 deletions(-)
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c index 2d1c5d9..df0ac0c 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 3dfca51..4083d56 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 daeae42..138e419 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 1fab9aa..56ba569 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;