A problem with Radeon 8500's pixel shaders

Ah well, i’ve got many problems with pixel shaders on my Radeon 8500. I’ve read the spec many, many times and i believed i mastered it, but my application doesn’t work. I did many tests, and found a simple (at least, i thought it was simple) shader, that doesn’t output the expected result. I have the latest beta drivers (but i get the same problem with the official drivers).

Here’s basically the problem.

I have a sky cube map bound in texture 0. The texture coordinates are a reflection vector into that cube map. This works fine (eg. i see the sky reflected onto my surface) when i’m not using a pixel shader.

Now i use that simple shader:

glPassTexCoordATI(GL_REG_1_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STR_ATI)

glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE, GL_CON_0_ATI, GL_NONE, GL_NONE)

glSampleMapATI(GL_REG_0_ATI, GL_REG_1_ATI, GL_SWIZZLE_STR_ATI)

I have the vector (0.5, 0.5, 0.5, 0) inside the constant 0.

I’m expecting that shader to replace the reflection vector by the constant vector, hence to have my surface of a uniform color (since the sampled texels will all have the same coordinates into the cube map). What really happens is like if the MOV instruction was completely ignored. I see normal reflections everywhere. But the pixel shader is well executed, since if i do other stupid operations, the surface appearance changes…

This simple shader is not doing anything interesting in itself, but i’d like to know why it doesn’t output the results i was expecting… what am i doing wrong ? Is there something i didn’t understand ?

Y.

[This message has been edited by Ysaneya (edited 06-16-2002).]

When you call glEndFragmentShaderATI(), try checking for an error with glGetError(), is the shader building properly?

Also, I think that each pass of the shader requires at least one fragment operation. So after your glSampleMapATI(***) and before your glEndFragmentShaderATI(), try calling
glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_PRIMARY_COLOR_ARB, GL_NONE, GL_NONE);

Dan

[This message has been edited by Dan82181 (edited 06-16-2002).]

Yes, there is no error returned after the end of the shader (glGetError returns GL_NO_ERROR). I tried to do an operation in the second pass, but i still don’t get the expected results (that is, with primary color modulation, i get a modulated reflection instead of a flat color). But thanks for your help… any other idea ?

Y.

OK, that is exceptionally wierd. You should probably submit it to ATI as a bug.

There’s something even more weird. If i add a glAlphaFragment operation (not doing anything, like mov reg0.a, reg0.a) after the color one, i get the expected result…:)) But you’re right, i’ll submit it to ATI and see what they have to say…

Y.

There are some issues with that shader.

Originally posted by Ysaneya:
glPassTexCoordATI(GL_REG_1_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STR_ATI)
This puts the tex coords in REG_1. Okay.

glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE, GL_CON_0_ATI, GL_NONE, GL_NONE)
You replace the texture coordinates in REG_1 with the constant, which is legal. But why?

*phase 2 begins here, because phases are seperated by PassTexCoord and SampleMap calls

glSampleMapATI(GL_REG_0_ATI, GL_REG_1_ATI, GL_SWIZZLE_STR_ATI)

You’re using a register identifier as ‘interp’. This indicates a dependant texture read, so it will only work in second phade (it is in second phase). But a dependant texture read wasn’t your intention, was it? You’re almost sampling the texture map on coordinates (0.5;0.5;0.5), regardless of ‘real’ tex coords. Almost, because you should have passed REG_1 from first phase to second.

From the spec:

  Note that in order to preserve the contents of a register from the first
  pass to the second, there must be a PassTexCoordATI instruction in the
  setup for the second pass that assigns that register to itself.  For 
  example, PassTexCoordATI(REG_1_ATI, REG_1_ATI, SWIZZLE_STR_ATI) will 
  preserve the first 3 components of REG_1_ATI for use in the second pass.

Taking a quick stab at this (gotta learn more myself), a shader for sampling a cube map and nothing else should look like this:

glBeginShaderATI();
    glSampleMapATI(GL_REG_0_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STR_ATI);
glEndShaderATI();

Don’t try to find an interest into that shader: it has none! I’m not trying to sample a cube map. As you pointed, it’s obvious to do it. But i would like to understand why this test shader doesn’t work, as it looks correct to me. As i said, it’s a dependant texture read, but from the same texel (since i replace the texture coordinates with a constant). So i’m expecting a uniform color everwhere. And what happens is that it’s as if it completely ignored the mov operation (so it works as if it was sampling the cube map normally).

I’m not really sure i agree with your interpretation of glPassTexCoord. What you basically mean is that, if you calculate a texture coordinate (say in REG1) in the first pass (“phase”), and want to do a dependant texture read, you need to do PassTexCoordATI on REG1, then SampleMapATI with REG1. In my interpretation, the PassTexCoordATI is not needed. But i’ll try it, we never know…

Thanks.

Y.

My theory regarding this:

The modification of REG_1 (MOV REG_1,CON_0) is discarded. The PassTexCoord(REG_1,TEXTURE0) is still in effect, that’s why you get ‘standard’ cube map sampling. If you want to keep the modifications into the second phase, you have to issue the PassTexCoord(REG_1,REG_1). It wasn’t my idea, it’s in the spec document, as quoted.

No, i think you are wrong in your understanding of the specification. PassTexCoord is used:

  • in the first pass, to get access to the texture coordinates (not sampled);

  • in the second pass, to get access to the register values computed into the first pass (still no sampling).

But where i think you’re wrong is this only applies to glColorFragment or glAlphaFragment operations, not glSampleMapATI. glSampleMapATI is a special instruction, like glTexCoordATI. There’s no need to call glPassTexCoordATI before doing a dependant texture read. To prove yourself, in the same specification, scroll down to the “bumped cubic environment mapping” example code (at the end), and see how they are doing their dependant texture reads. There’s no glPassTexCoordATI call at all.

Y.

An addition: i don’t seem to be able to get access to the alpha component of the primary color into the second phase of a pixel shader. RGB components work fine, but not the alpha. I just wanted to do a replication of the alpha channel of the primary color to a RGB vector, but it doesn’t work. It acts as if there was no replication at all. Hum…

Y.

Ysaneya,
I don’t have any problems using the alpha component of PRIMARY_COLOR_ARB in my programs? What exactly are you trying to do with them? As far as I know, if you want try and put the 4th scalar of a register into the first 3, you’d have to call

glColorFragmentOp1ATI(GL_MOV_ATI, <dstRegHere>, GL_NONE, GL_NONE, <srcRegHere>, GL_ALPHA, GL_NONE);

So just use PRIMARY_COLOR_ARB as your <srcRegHere> and that should work. I’ve never personally tried the MOV_ATI command, but I’ve used

glColorFragmentOp2ATI(GL_MUL_ATI, <dstRegHere>, GL_NONE, GL_NONE, <srcReg1Here>, GL_NONE, GL_NONE, <srcReg2Here>, GL_ALPHA, GL_NONE);

and it works, although <srcReg2Here> I don’t think has ever been PRIMARY_COLOR_ARB, and I know that glAlphaFragmentOp*ATI() with the MOV_ATI and the MUL_ATI using PRIMARY_COLOR_ARB works without any problems. If the MOV_ATI command doesn’t work, try using

glColorFragmentOp2ATI(GL_MUL_ATI, <dstRegHere>, GL_NONE, GL_NONE, GL_ONE, GL_NONE, GL_NONE, GL_PRIMARY_COLOR_ATI, GL_ALPHA, GL_NONE);

That should atleast work.

Hope it helps!!

Dan

[This message has been edited by Dan82181 (edited 06-18-2002).]

I tried everything, but it doesn’t work. I used that code:

glBeginFragmentShaderATI();
glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE, GL_ONE, GL_NONE, GL_NONE, GL_PRIMARY_COLOR_ARB, GL_ALPHA, GL_NONE);
glColorFragmentOp1ATI(GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
GL_REG_1_ATI, GL_NONE, GL_NONE);
glEndFragmentShaderATI();

(i also tried the simpler MOV version, but same result)

I specified a surface with vertex colors (0, 0.5, 1.0, 1.0), and what i get is a blue-ish uniform color, instead of a white color as if replication had worked.

I more and more believe the drivers are buggued, but i have the latest beta drivers, and i can’t believe i’m the first one to try such operations…

Y.

It works for me ( alpha replication ). I’m using the new Catalyst drivers but it worked before that too ( using beta drivers ). This definitely works ( just checked it ),

glBeginFragmentShaderATI();
glColorFragmentOp1ATI( GL_MOV_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE, GL_PRIMARY_COLOR_ARB, GL_ALPHA, GL_NONE );
glEndFragmentShaderATI();

Ysaneya,
I don’t want to sound rude or anything, but double check your values for your defines and make sure that they match the latest ones posted at ATi’s website, then try to download and install the latest drivers. I’m sure you’ve noticed that the spec has gone through several changes, so some of the enumerants might have gotten changed without you knowing it, or you might be using the new values with older drivers, or something along those lines. But something is definately fishy if it’s working fine for me and PH, but it’s giving you a headache.

Dan

Problem solved. I had an old OpenGL driver installed. I still can’t explain it, since i downloaded and installed the beta driver (from April) less than two weeks ago. Why it didn’t update my OpenGL driver, i have no idea. So i cleaned up everything properly, and now the alpha replication is working. I’m pretty confident that the other bugs i found will be fixed too.

Thank you all for your help!

Y.

Ysaneya,
Glad to see that it’s working now. Just don’t forget to let ATi know that you found and fixed the problem so that they don’t start chasing down a phantom bug!

Dan