PDA

View Full Version : Possible shader corruption



DarkRaven
09-26-2011, 12:21 PM
I'm working with shaders just now and I'm observing some very strange behavior. I've loaded this vertex shader:

#version 150

uniform float r;
uniform float g;
uniform float b;
varying float retVal;
attribute float dummyAttrib;

void main(){
retVal = dummyAttrib+r+g+b; //deleting dummyAttrib = corruption
gl_Position = gl_ModelViewProjectionMatrix*vec4(100,100,0,1);
}

First of all I render with glDrawArrays(GL_POINTS,0,1000) with this shader without nothing special, just using shader program. If you run this shader and set point size to something visible, you should see white square in middle of screen (I'm using glOrtho2d(0,200,0,200)). DummyAttrib is just some attrib - my shaders won't run if there's none. Also I need to actually use that attribute so normally I do something like float c = dummyAttrib.That is also first question I would like to ask why it is that way.

However this would be fine but when you change the line with comment (retval=...) to retVal = r+g+b; and add that mentioned line to use attrib (float c = dummyAttrib), strange things happen. First of all you won't see that square anymore, so I had to set up transform feedback to watch what's happening.

I've set the dummyAttrib to 5 in each element of field and r=g=b=1. With current code the result of transform feedback is 8 - exactly what you'd expect. However changing it like above gives strange values like 250.128 and every time I modify the code somehow (just reorder calls), this value changes. As soon as I return that dummyAttrib to calculation of retVal everything is magically fixed.

This is why I think there's some sort of shader corruption. I'm using the same loading interface for shaders as I did in projects before and these were flawless, however they were using attributes in normal way, not just dummy for actually running shader.

These 2 problems can have connecion. To sum up - shader won't run without any attribute and shader is corrupted if that attribute isn't used for setting varying that is used either in fragment shader or for transform feedback.

PS: It came to my mind when I was writing this that it looks like every variable that isn't used for passing into next stage is opt out. This could opt out attribute as well and then this shader would be without attribute and wouldn't work properly. Could this be a driver fault? I have Radeon 3870HD with current catalyst version 2010.1105.19.41785.

BionicBytes
09-30-2011, 09:12 AM
It came to my mind when I was writing this that it looks like every variable that isn't used for passing into next stage is opt out. This could opt out attribute as well and then this shader would be without attribute
Yes, all GLSL and cg compilers have done this since day 1.
This is perfectly normal and valid.



and wouldn't work properly.

if you take your original GLSL program and remove unused attribs and uniforms, that leaves the following:

void main(){
gl_Position = gl_ModelViewProjectionMatrix*vec4(100,100,0,1);
}

What does not work with this? Looks perfectly reasonable (don't know what it's doing - but that's another issue).



Could this be a driver fault? I have Radeon 3870HD with current catalyst version 2010.1105.19.41785.
Nope.

malexander
09-30-2011, 04:41 PM
There are several issues with this shader that should be fixed:
You can't render without a vertex attribute bound, as detailed in this post (http://http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=292300#Post2923 00). It's likely not rendering anything, and you're probably seeing uninitialized memory in the transform feedback buffer. The shader is accessing gl_ModelViewProjectionMatrix, which does not exist in the core GLSL 1.50 language. If you want to use it, use #version 150 compatibility instead. 'varying' as been replaced by 'out' in a vertex shader, and 'attribute' has been replaced by 'in'.

Because of points 2 & 3, I'm a little surprised it even compiles.

DarkRaven
10-02-2011, 09:54 AM
I've messed long with those shaders and found out rule for making valid shader:

- there must be varying that is passed to other stage or queried with transform feedback
- there must be attribute that affects the value of one of those varyings. That means if you set varying with attribute and than with other value, attribute is opt out.

It's easily done by creating: "attribute int dummyAttrib", creating allocated but unitialized buffer and using GLbyte pointer connecting dummyAttrib with buffer. GLSL seems to initialize buffer to 0s, so dummyAttrib can be added to last calculation of variable and won't affect the value.

PS: I'm also surprised that compiler doesn't complain about things like that, but maybe it's switched to compatibility mode as soon as it finds keyword attribute or similiar.