Nvidia if-clause driver bug

I’m getting dancing pixels near polygon borders with mipmapping on the following terrain fragment shader:


uniform sampler2D texture0;   // color texture
uniform sampler2D texture1;   // mixmap texture
uniform sampler2D texture2;   // detail texture 1
uniform sampler2D texture3;   // detail texture 2
uniform sampler2D texture4;   // detail texture 3
uniform sampler2D texture5;   // detail texture 4

varying vec2 uv0;
varying vec2 uv1;
varying vec2 uv2;

void main()
{
 vec4 color;
 vec4 mixmap;
 vec4 detail;
 
 vec4 dc;       // detail texture color
 float da;      // detail mixing alpha
 
 // get color
 color = texture2D(texture0, uv0);
 
 // get mixmap
 mixmap = texture2D(texture1, uv2);
 
 // detail 1
 if (mixmap.r > 0.0) {
  detail.rgb = texture2D(texture2, uv1);
 }
 
 // detail 2
 if (mixmap.g > 0.0) {
  dc = texture2D(texture3, uv1);
  da = clamp( (mixmap.g - (dc.a*0.75)) * 4 ,0.0,1.0);
  detail.rgb = mix(detail.rgb,dc.rgb,da);
 }
 
 // detail 3
 if (mixmap.b) { // !!comment out to fix!!
  dc = texture2D(texture4, uv1);
  da = clamp( (mixmap.b - (dc.a*0.75)) * 4 ,0.0,1.0);
  detail.rgb = mix(detail.rgb,dc.rgb,da);
 } // !!comment out to fix!!
 
 // detail 4
 if (mixmap.a > 0.0) { // !!comment out to fix!!
  dc = texture2D(texture5, uv1);
  da = clamp( (mixmap.a - (dc.a*0.75)) * 4 ,0.0,1.0);
  detail.rgb = mix(detail.rgb,dc.rgb,da);
 } // !!comment out to fix!!
 
 // mix color with detail
 color.rgb = (color.rgb) + (detail.rgb - 0.5);
 
 // apply fog
 float fog;
 fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale;
 fog = clamp(fog, 0.0, 1.0);
 color.rgb = mix(gl_Fog.color.rgb, color.rgb, fog);
 
 gl_FragColor = color;
}

Result (animated GIF):

Pixels jitter, even when the viewpoint is not moving, it is not texture aliasing.

WinXP SP2
H/W: 8800GT
Driver: 169.21 / 174.74 Beta

Changing bi/tri-linear/anisotropic filter, FSAA, various driver optimizations has no effect.

Commenting out the if-clauses fixes the problem, but wastes an unneeded texture fetch in most situations. Note that the first if-clause (detail 1 and detail 2) don’t cause any problems.

This isn’t the first time I have reported a bug with if-clauses. I guess if-clauses are a bit to advanced for the nVidia GLSL compiler?

Any workarounds?

This looks like the issue from the first pipeline:

http://www.opengl.org/pipeline/article/vol001_5/

That sounds plausible, but I don’t understand why the second detail layer does not suffer from this. Presumably because the values are different? And this only occurs on the polygon edges, I would expect it to occur all over the surface.

I had a similiar issue a few weeks ago writing an parallax occlusion mapping shader. You could solve this by computing the derivatives yourself and pass them to texture2DGrad. Unfortunately this will make your shader slower than always reading out all Textures. To make it faster I computed the mipmap level in the shader an accessed the textures with texture2DLod. Unfortunately this is currently only supported with the GL_EXT_gpu_shader4 extension which would limit it to g8 and g9 hardware.

My guess why it only appears on the edges: the hw computes the derivatives on the edges with other formulars than in the triangles.

I must admit I haven’t checked the specs out lately, but your “vec4 detail” is never explicitly initialized. If OpenGL doesn’t initialize it for you, that’ll leave it with an undefined value if the “mixmap.r > 0” test fails.

If variables are initialized for you, feel free to ignore me :slight_smile:

I’m now more confident that it is indeed the issue pointed out by sqrt[-1], or at least closely related.

My guess why it only appears on the edges: the hw computes the derivatives on the edges with other formulas than in the triangles.

I came to the same conclusion yes. The question is, is this expected behavior or a bug?

I must admit I haven’t checked the specs out lately, but your “vec4 detail” is never explicitly initialized. If OpenGL doesn’t initialize it for you, that’ll leave it with an undefined value if the “mixmap.r > 0” test fails.

The mixmap texture is normalized, i.e. one of the four cases is always true so variable initialization is not an issue (and to be sure I have verified this by initializing the variables explicitly).

I should add that the identical shader worked flawlessly on older hardware (GF 6200 series if I recall correctly), so I’m inclined to think it is a bug (or I may have been lucky in the past).

This is may caused by the fact that the gf8 uses dynamic braching to skip the instructions and the gf6200 does not.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.