wined3d: Implement the varying map.
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 @@
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 @@
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 @@
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 @@
/* 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 @@
/* 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;