cancel
Showing results for 
Search instead for 
Did you mean: 

Archives Discussions

trzy
Journeyman III

Unspecified link error on ATI X1250 in shader sampling texture multiple times

Hello,

I'm developing on a laptop with an integrated Radeon X1250 GPU. I'm writing a fragment shader to do bilinear interpolation manually (it's a long story, but absolutely necessary). This involves a fair amount of slow computations and four texture samples per fragment. The shader compiles, the log contains no errors, but the linker fails with this message:

Fragment shader(s) failed to link,  vertex shader(s) linked.


Below is the complete shader. If I remove a single fetch, it links. Likewise, if I use constant texel coordinates for one of the fetches, like so:

c[0] = FetchTexel(vec2(0.0,0.0),fsSubTexture.xy,fsSubTexture.zw,fsTexParams.zw);

It works as well. I've also tried manually inlining the FetchTexel() function to no avail. The program works fine on a desktop Nvidia machine. I'd like this code to run on lower spec hardware so I'm really hoping I'm not bumping into any sort of weird limitations here.

Thank you!

Code:

/*
 * fragment.glsl
 *
 * Fragment shader.
 */

#version 120

// Global uniforms
uniform sampler2D textureMap;  // complete texture map, 2048x2048 texels
uniform vec3  polygonState; // .x=not defined, .y=not defined, .z=alpha processing enable

// Inputs from vertex shader
varying vec4  fsSubTexture; // .x=texture X, .y=texture Y, .z=texture width, .w=texture height (all in texels)
varying vec4  fsTexParams; // .x=texture enable (if 1, else 0), .y=use transparency (if >=0), .z=U wrap mode (1=mirror, 0=repeat), .w=V wrap mode
varying float  fsTransLevel; // translucence level, 0.0 (transparent) to 1.0 (opaque). if less than 1.0, replace alpha value
varying float  fsLightIntensity; // lighting intensity

/*
 * FetchTexel():
 *
 * Samples a single Real3D texel from the selected texture, taking into
 * account wrapping behavior.
 *
 * Computing normalized OpenGL texture coordinates (0 to 1) within the
 * Real3D texture sheet:
 *
 * If the texture is not mirrored, we simply have to clamp the
 * coordinates to fit within the texture dimensions, add the texture
 * X, Y position to select the appropriate one, and normalize by 2048
 * (the dimensions of the Real3D texture sheet).
 *
 *  = [(u,v)%(w,h)+(x,y)]/(2048,2048)
 *
 * If mirroring is enabled, textures are mirrored every odd multiple of
 * the original texture. To detect whether we are in an odd multiple,
 * simply divide the coordinate by the texture dimension and check
 * whether the result is odd. Then, clamp the coordinates as before but
 * subtract from the dimension to mirror them:
 *
 *   = [M*((w,h)-(u,v)%(w,h)) + (1-M)*(u,v)%(w,h) + (x,y)]/(2048,2048)
 *  where M is 1.0 if the texture must be mirrored.
 */
vec4 FetchTexel(vec2 texCoord, vec2 texOffset, vec2 texSize, vec2 mirrorEnable)
{
 vec2 clampedCoord, mirror, glTexCoord;
 
 clampedCoord = mod(texCoord.st,texSize);      // clamp coordinates to within texture size
 mirror = mirrorEnable * mod(floor(texCoord.st/texSize),2.0); // whether this texel needs to be mirrored
 glTexCoord = ( mirror*(texSize-clampedCoord) +
     (vec2(1.0,1.0)-mirror)*clampedCoord +
     texOffset
     ) / 2048.0;
 
 return texture2D(textureMap, glTexCoord);
}

void main(void)

 vec4 c[4];
 vec2 uv[4], r;
 
 if (fsTexParams.x == 0.0)
  gl_FragColor = gl_Color; // if textures disabled, use color
 else
 {   
  /*
   * Bilinear Filtering
   */
  
  // Compute fractional blending factor, r, and lower left corner of texel 0
  uv[0] = gl_TexCoord[0].st-vec2(0.5,0.5);
  r = uv[0]-floor(uv[0]);
  uv[0] = floor(uv[0]);
  
  // Compute texel coordinates
  uv[0] = uv[0] + vec2(0.5,0.5); // offset to within center of pixel
  uv[1] = uv[0] + vec2(1.0,0.0);
  uv[2] = uv[0] + vec2(0.0,1.0);
  uv[3] = uv[0] + vec2(1.0,1.0);
  
  // Fetch texels
  c[0] = FetchTexel(uv[0],fsSubTexture.xy,fsSubTexture.zw,fsTexParams.zw);
  c[1] = FetchTexel(uv[1],fsSubTexture.xy,fsSubTexture.zw,fsTexParams.zw);
  c[2] = FetchTexel(uv[2],fsSubTexture.xy,fsSubTexture.zw,fsTexParams.zw);
  c[3] = FetchTexel(uv[3],fsSubTexture.xy,fsSubTexture.zw,fsTexParams.zw);

  gl_FragColor = c[0]*(1-r.s)*(1-r.t) + c[1]*r.s*(1-r.t) + c[2]*(1-r.s)*r.t + c[3]*r.s*r.t;
  
  /*
   * T1RGB5:
   *
   * The transparency bit determines whether to discard pixels (if set).
   * What is unknown is how this bit behaves when interpolated. OpenGL
   * processes it as an alpha value, so it might concievably be blended
   * with neighbors. Here, an arbitrary threshold is chosen.
   */
  if (fsTexParams.y >= 0.0)
  {
   if (gl_FragColor.a > 0.0)
    discard;
  }
 }
 
 // Apply translucency
 if (fsTransLevel < 1.0)
   gl_FragColor.a = fsTransLevel;
   
 // Apply ambient lighting
 gl_FragColor.rgb *= fsLightIntensity;
}

0 Likes
1 Reply
frali
Staff

We are sorry that we stop to update the driver for Radeon X1250.  I try your shader on a HD2900 card, it works.

0 Likes