Skip to main content
GameDev.net gamedev.net
🔒 Locked

[SOLVED] [GLSL] Weird behavior with interface blocks.

Started by FreOzgur Feb 3, 2015 at 11:36 PM 4 replies 5.2k views
Original Post
FreOzgur
FreOzgur

Hello friends!

I have a strange behaviour with my glsl code..

I am trying to pass a simple 'uint' variable between stages (from vertex shader to fragment shader), but it seems like I'm doing something wrong.

I have an interface block like this:


// Vertex Shader
out InterfBlock {
	vec4 WorldPos;
	vec3 WorldNormal;
	vec2 TexCoord[2];
	vec3 CamDir;
 	uint DrawID;
} OUT;	

//Fragment Shader
in InterfBlock {
	vec4 WorldPos;
	vec3 WorldNormal;
	vec2 TexCoord[2];
	vec3 CamDir;
	uint DrawID; // This line is the problem, works if I remove.
} IN;

When I run my program, it simply generates no error.
(There is an error checker already that uses glGetShaderInfoLog() and works when I simply forget to put a semicolon, so I know it works,)

But also my GpuProgram class gives me the number of Uniforms in my shaders. But it says 0 (zero). (But there are a few uniforms)

The strange thing is, the shader works perfectly when I simply remove the "uint DrawID;" from FRAGMENT SHADER.. (Also shows the correct amount of Uniforms if I remove).

It doesn't matter if I keep it in Vertex Shader, it works. But when I add the line "uint DrawID;" in interface block of frag shader, It stops working.
Any ideas?

Edit:
NVIDIA Driver Version: 331.113
OS: Linux-x86_64

OpenGL version from glxinfo: 3.3.0 NVIDIA 331.113

SapphireG
SapphireG

Could you please define "it stops working" ? What is its behavior?

Just a speculation by my part...


layout (location = 8) in uint DrawIDs;
...
OUT.DrawID = DrawIDs;

How are you passing this attribute? Can you paste the code? If you're using glVertexAttribPointer() make sure you have normalized set to GL_FALSE, or try using glVertexAttribIPointer() instead.

FreOzgur
FreOzgur

Thanks for the reply!

My buffer class is just a wrapper around OpenGL.

I am filling the buffer like this:


unsigned int* buffer = (unsigned int*)drawids->MapRange(0, sizeof(unsigned int) * 6, BufferLock_Write);  // My own buffer class. Just a simple wrapper, tested, working.. 
    for(int i = 0; i < 6; ++i)
        buffer[i] = i;
drawids->Unmap();

And then simply enable the attribute and and set the pointer: (Already use glVertexAttribIPointer())


glBindBuffer(GL_ARRAY_BUFFER, drawids->GetHandlerGL());
glEnableVertexAttribArray(8);
glVertexAttribIPointer(8, 1, GL_UNSIGNED_INT, 0, BUFFER_OFFSET(0));
glVertexAttribDivisor(8, 1);

Actually my attribute already works, I know it. Because when I only use it on vertex shader to get every instances (there are only two for testing) matrices, they can succesfully get their matrices. But the problem is just I cannot pass it to fragment shader. If I don't try to pass it to fragment shader, It works as intended.

And by "it stops working", literally just stops working. No GLSL error is generated, the glsl compiling looks failed but no information generated by glGetShaderInfoLog(), It returns an empty text with size 1. I know it failed since glGetShaderiv() with GL_COMPILE_STATUS returns GL_FALSE.
Actual code for checking compile errors, if you interested:


static void TestCompileError(String file, GLuint handler) {
	GLint result = 0;
	glGetShaderiv(handler, GL_COMPILE_STATUS, &result);

	if (result == GL_FALSE) {
		GLint length;
		glGetShaderiv(handler, GL_INFO_LOG_LENGTH, &length);
		std::vector<char> buffer;
		buffer.resize(length);
		GLsizei final;
		glGetShaderInfoLog(handler, length, &final, &buffer[0]);
		std::string message(&buffer[0], length);
		std::cout << file.c_str() << ": " << length << ": " << message.c_str() << std::endl;
	}
}

I hope it is not a Driver Bug sad.png

FreOzgur
FreOzgur

Update!

Wow.. It seems like everything works perfectly if I simply use "float" instead of "uint" in interface block.

I just changed it to:


// Vertex Shader
out InterfBlock {
	vec4 WorldPos;
	vec3 WorldNormal;
	vec2 TexCoord[2];
	vec3 CamDir;
 	float DrawID; // Change here
} OUT;	

//Fragment Shader
in InterfBlock {
	vec4 WorldPos;
	vec3 WorldNormal;
	vec2 TexCoord[2];
	vec3 CamDir;
	float DrawID; // Change here
} IN;

and then simply cast my DrawIDs to float by:


// Vertex shader
OUT.DrawID = float(DrawIDs);

// Fragment shader
vec3 color = texture2DArray(colorTexture, vec3(IN.TexCoord[0], IN.DrawID)).xyz;

Now everything works perfectly..

But what is the problem with "uint" ??? Was that a bug?? C'mon drivers..

Xycaleth
Xycaleth
It does sound like a bug. You have to specify the flat qualifier for integral out variables, e.g.
flat uint DrawID;, so the compiler should have warned you about that.
FreOzgur
FreOzgur

It does sound like a bug. You have to specify the flat qualifier for integral out variables, e.g.
flat uint DrawID;, so the compiler should have warned you about that.

Woah, thanks for the information!

Yeah I guess, giving me no error about that was a bug..
I added the 'flat' qualifier to both shaders with 'uint', and worked as intended.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.