It's a strange issue. . . one that didn't pop up on my Radeon 8500. My little OpenGL program's bump mapping implementation through fragment shaders does not work on my Radeon 9700. It was working perfectly until I upgraded. The strange part is that every other OpenGL demo that uses fragment shaders still works perfectly. My own program shows up as black, though.
Here's the fragment shader program:
Upon experimenting I found that the program is being executed properly. I can comment out a bunch and output the first couple instructions to register 0 and there is a result. However I cannot revert it back to normal and get the whole program to work.
Upon further experimentation I got to this point:
The fragment shader has to use register zero in the first phase, or else the thing won't work. It also has to be doing this early in the phase, so I can't simply output to register zero for the second light. That seemingly useless "mov r0, r0" is the only thing that is allowing this damn thing to work. As I said before, though: no other demo that uses ATI_fragment_shader that I've tested has this problem.
Any clue as to what's going on?
Update: This is strange. I put the "mov r0, r0" as the second instruction and the thing doesn't work.
There was another alternative I used where I had "mov r1, r0" instead, and output light 1 to r0 and then used r1 for light 2's normal map (the second phase modified accordingly) and it worked.
In another test I commented out everything except for light 1's first two instructions. I set it so instruction 2 would output to r0. The damn thing refused to work. If I set the first instruction to output to r0 and modified instruction two accordingly, the thing works.
There's no pattern. I'm almost about to say that the first instruction has to output to r0, but one of my alternate methods (mov r1, r0) proves that wrong.
Here's the fragment shader program:
Code:
glSampleMapATI (GL_REG_0_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STQ_ATI);
glSampleMapATI (GL_REG_2_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI);
glSampleMapATI (GL_REG_3_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI);
// LIGHT 1
// N.L
glColorFragmentOp2ATI (GL_DOT3_ATI,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_REG_0_ATI, GL_NONE, GL_BIAS_BIT_ATI|GL_2X_BIT_ATI,
GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI|GL_2X_BIT_ATI);
// add colour
glColorFragmentOp2ATI (GL_MUL_ATI,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_CON_1_ATI, GL_NONE, GL_NONE);
// LIGHT 2
// N.L
glColorFragmentOp2ATI (GL_DOT3_ATI,
GL_REG_3_ATI, GL_NONE, GL_NONE,
GL_REG_0_ATI, GL_NONE, GL_BIAS_BIT_ATI|GL_2X_BIT_ATI,
GL_REG_3_ATI, GL_NONE, GL_BIAS_BIT_ATI|GL_2X_BIT_ATI);
// add colour
glColorFragmentOp2ATI (GL_MUL_ATI,
GL_REG_3_ATI, GL_NONE, GL_NONE,
GL_CON_2_ATI, GL_NONE, GL_NONE,
GL_REG_3_ATI, GL_NONE, GL_NONE);
// reg1 = base map
// reg2 = light1 coloured N.L
// reg3 = light2 coloured N.L
// reg4 = light1 attenuation map
// reg5 = light2 attenuation map
glSampleMapATI (GL_REG_1_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STQ_ATI);
glPassTexCoordATI (GL_REG_2_ATI, GL_REG_2_ATI, GL_SWIZZLE_STR_ATI);
glPassTexCoordATI (GL_REG_3_ATI, GL_REG_3_ATI, GL_SWIZZLE_STR_ATI);
glPassTexCoordATI (GL_REG_4_ATI, GL_TEXTURE2_ARB, GL_SWIZZLE_STR_ATI);
glPassTexCoordATI (GL_REG_5_ATI, GL_TEXTURE4_ARB, GL_SWIZZLE_STR_ATI);
// LIGHT 1
// generate the light map via attenuation
glColorFragmentOp2ATI (GL_DOT3_ATI,
GL_REG_4_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_REG_4_ATI, GL_NONE, GL_NONE,
GL_REG_4_ATI, GL_NONE, GL_NONE);
// apply attenuation to N.L
glColorFragmentOp2ATI (GL_MUL_ATI,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_REG_4_ATI, GL_NONE, GL_COMP_BIT_ATI);
// LIGHT 2
// generate the light map via attenuation
glColorFragmentOp2ATI (GL_DOT3_ATI,
GL_REG_5_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_REG_5_ATI, GL_NONE, GL_NONE,
GL_REG_5_ATI, GL_NONE, GL_NONE);
// apply attenuation to N.L and add to light 1
glColorFragmentOp3ATI (GL_MAD_ATI,
GL_REG_2_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_REG_3_ATI, GL_NONE, GL_NONE,
GL_REG_5_ATI, GL_NONE, GL_COMP_BIT_ATI,
GL_REG_2_ATI, GL_NONE, GL_NONE);
// add ambient light
glColorFragmentOp2ATI (GL_ADD_ATI,
GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_CON_0_ATI, GL_NONE, GL_NONE,
GL_REG_2_ATI, GL_NONE, GL_NONE);
// modulate with the base texture
glColorFragmentOp2ATI (GL_MUL_ATI,
GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_REG_1_ATI, GL_NONE, GL_NONE,
GL_REG_0_ATI, GL_NONE, GL_NONE);
Upon experimenting I found that the program is being executed properly. I can comment out a bunch and output the first couple instructions to register 0 and there is a result. However I cannot revert it back to normal and get the whole program to work.
Upon further experimentation I got to this point:
Code:
glSampleMapATI (GL_REG_0_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STQ_ATI);
glSampleMapATI (GL_REG_2_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI);
glSampleMapATI (GL_REG_3_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI);
glColorFragmentOp1ATI (GL_MOV_ATI,
GL_REG_0_ATI, GL_NONE, GL_NONE,
GL_REG_0_ATI, GL_NONE, GL_NONE);
// LIGHT 1
// N.L
glColorFragmentOp2ATI (GL_DOT3_ATI,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_REG_0_ATI, GL_NONE, GL_BIAS_BIT_ATI|GL_2X_BIT_ATI,
GL_REG_2_ATI, GL_NONE, GL_BIAS_BIT_ATI|GL_2X_BIT_ATI);
// add colour
glColorFragmentOp2ATI (GL_MUL_ATI,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_CON_1_ATI, GL_NONE, GL_NONE);
// LIGHT 2
// N.L
glColorFragmentOp2ATI (GL_DOT3_ATI,
GL_REG_3_ATI, GL_NONE, GL_NONE,
GL_REG_0_ATI, GL_NONE, GL_BIAS_BIT_ATI|GL_2X_BIT_ATI,
GL_REG_3_ATI, GL_NONE, GL_BIAS_BIT_ATI|GL_2X_BIT_ATI);
// add colour
glColorFragmentOp2ATI (GL_MUL_ATI,
GL_REG_3_ATI, GL_NONE, GL_NONE,
GL_CON_2_ATI, GL_NONE, GL_NONE,
GL_REG_3_ATI, GL_NONE, GL_NONE);
// reg1 = base map
// reg2 = light1 coloured N.L
// reg3 = light2 coloured N.L
// reg4 = light1 attenuation map
// reg5 = light2 attenuation map
glSampleMapATI (GL_REG_1_ATI, GL_TEXTURE0_ARB, GL_SWIZZLE_STQ_ATI);
glPassTexCoordATI (GL_REG_2_ATI, GL_REG_2_ATI, GL_SWIZZLE_STR_ATI);
glPassTexCoordATI (GL_REG_3_ATI, GL_REG_3_ATI, GL_SWIZZLE_STR_ATI);
glPassTexCoordATI (GL_REG_4_ATI, GL_TEXTURE2_ARB, GL_SWIZZLE_STR_ATI);
glPassTexCoordATI (GL_REG_5_ATI, GL_TEXTURE4_ARB, GL_SWIZZLE_STR_ATI);
// LIGHT 1
// generate the light map via attenuation
glColorFragmentOp2ATI (GL_DOT3_ATI,
GL_REG_4_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_REG_4_ATI, GL_NONE, GL_NONE,
GL_REG_4_ATI, GL_NONE, GL_NONE);
// apply attenuation to N.L
glColorFragmentOp2ATI (GL_MUL_ATI,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_REG_2_ATI, GL_NONE, GL_NONE,
GL_REG_4_ATI, GL_NONE, GL_COMP_BIT_ATI);
// LIGHT 2
// generate the light map via attenuation
glColorFragmentOp2ATI (GL_DOT3_ATI,
GL_REG_5_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_REG_5_ATI, GL_NONE, GL_NONE,
GL_REG_5_ATI, GL_NONE, GL_NONE);
// apply attenuation to N.L and add to light 1
glColorFragmentOp3ATI (GL_MAD_ATI,
GL_REG_2_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_REG_3_ATI, GL_NONE, GL_NONE,
GL_REG_5_ATI, GL_NONE, GL_COMP_BIT_ATI,
GL_REG_2_ATI, GL_NONE, GL_NONE);
// add ambient light
glColorFragmentOp2ATI (GL_ADD_ATI,
GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_CON_0_ATI, GL_NONE, GL_NONE,
GL_REG_2_ATI, GL_NONE, GL_NONE);
// modulate with the base texture
glColorFragmentOp2ATI (GL_MUL_ATI,
GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
GL_REG_1_ATI, GL_NONE, GL_NONE,
GL_REG_0_ATI, GL_NONE, GL_NONE);
The fragment shader has to use register zero in the first phase, or else the thing won't work. It also has to be doing this early in the phase, so I can't simply output to register zero for the second light. That seemingly useless "mov r0, r0" is the only thing that is allowing this damn thing to work. As I said before, though: no other demo that uses ATI_fragment_shader that I've tested has this problem.
Any clue as to what's going on?
Update: This is strange. I put the "mov r0, r0" as the second instruction and the thing doesn't work.
There was another alternative I used where I had "mov r1, r0" instead, and output light 1 to r0 and then used r1 for light 2's normal map (the second phase modified accordingly) and it worked.
In another test I commented out everything except for light 1's first two instructions. I set it so instruction 2 would output to r0. The damn thing refused to work. If I set the first instruction to output to r0 and modified instruction two accordingly, the thing works.
There's no pattern. I'm almost about to say that the first instruction has to output to r0, but one of my alternate methods (mov r1, r0) proves that wrong.
Last edited: