[Bug] glGetActiveAttribType returns incorrect values

Started by Cornix, January 06, 2014, 22:07:26

Previous topic - Next topic

Cornix

Hi there.

I wrote an application some time ago involving my own shaders. I used the method:
GL20.glGetActiveAttribType(progID, attrID)

to get the type of an attribute.

When testing this application on my desktop computer everything worked fine. When testing on a small asus eee netbook it didnt work however.
After much testing and lots of debug messages I finally found the cause:
GL20.glGetActiveAttrib(progID, attrID, bufLength, bufSize, bufType, bufName);
int actualType = bufType.get(0);
int fakeType = GL20.glGetActiveAttribType(progID, attrID);
System.out.println(fakeType+" != "+actualType+" == "+(fakeType != actualType)); // true

As you can see the methods return different values for the type of an attribute.

Since the function:
glGetActiveAttribType

is not defined on the OpenGL reference pages I would guess that it was added by the lwjgl team. As it seems, it does not quite return the correct value on all hardware.

Best regards.

spasi

I cannot reproduce this. Please check for OpenGL errors before and after calling these methods.

Cornix

I did check for OpenGL errors.
I tested this on numerous computers before writing this bug report. It worked (so there was no bug) on 6 different machines.
Only on one machine it did not work, that was an asus eee netbook.

spasi

Then it must be a driver issue on that particular machine. But let me know if you could run any more tests on the netbook, I'll need more info to make sure. What exactly are the values of "actualType" and "fakeType"? Does glGetActiveAttribSize work correctly?

Cornix

Here is the output I generated for testing purposes:

On the asus netbook:
QuoteGLSL Version 1.30
GL Version 2.1.8787


actualType (35666) ==  fakeType (18) ? => false
Type for gl_MultiTexCoord0 = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (1) ? => false
Type for gl_Vertex = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (18) ? => false
Type for gl_Color = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (1) ? => false
Type for gl_MultiTexCoord0 = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (1) ? => false
Type for gl_Vertex = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (18) ? => false
Type for gl_MultiTexCoord0 = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (1) ? => false
Type for gl_Vertex = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (10) ? => false
Type for gl_Color = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (1) ? => false
Type for gl_Vertex = 35666 == FLOAT_VEC4
The user of the asus netbook reported, that he had the latest driver installed.

This is what the same program outputted on my desktop pc (and on all other machines I tested it on):
QuoteGLSL Version 4.20
GL Version 4.2.12002 Compatibility Profile Context 9.12.0.0


actualType (35666) == fakeType (35666) ? => true
Type for gl_MultiTexCoord0 = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (35666) ? => true
Type for gl_Vertex = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (35666) ? => true
Type for gl_Color = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (35666) ? => true
Type for gl_MultiTexCoord0 = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (35666) ? => true
Type for gl_Vertex = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (35666) ? => true
Type for gl_MultiTexCoord0 = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (35666) ? => true
Type for gl_Vertex = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (35666) ? => true
Type for gl_Color = 35666 == FLOAT_VEC4

actualType (35666) == fakeType (35666) ? => true
Type for gl_Vertex = 35666 == FLOAT_VEC4

The program I used looks somewhat like this: (I removed all code that should not be important for this test case)
int attribute_count = GL20.glGetProgrami(get_program_id(), GL20.GL_ACTIVE_ATTRIBUTES);
		int attribute_length = GL20.glGetProgrami(get_program_id(), GL20.GL_ACTIVE_ATTRIBUTE_MAX_LENGTH);
		attributes = new Attribute[attribute_count];
		int index = 0;
		int offset = 0;
		for (int i = 0; i < attribute_count; i++) {
			IntBuffer bufSize = Buffer_Generator.make_int_buffer(1);
			IntBuffer bufType = Buffer_Generator.make_int_buffer(1);
			IntBuffer bufLength = Buffer_Generator.make_int_buffer(1);
			ByteBuffer bufName = Buffer_Generator.make_byte_buffer(attribute_length);
			
			GL20.glGetActiveAttrib(get_program_id(), i, bufLength, bufSize, bufType, bufName);
			bufType.clear();
			int type = bufType.get(0);
			
			int otherType = GL20.glGetActiveAttribType(get_program_id(), i);
			System.err.println("actualType ("+type+") == fakeType ("+otherType+") ? => "+(type == otherType));
			
			String name = GL20.glGetActiveAttrib(get_program_id(), i, attribute_length);
			int size = GL20.glGetActiveAttribSize(get_program_id(), i);
			int position = GL20.glGetAttribLocation(get_program_id(), name);
			Attribute attribute = new Attribute(this, Field_Type.get(type), get_use_by_name(name), name, position, offset, size);
			attributes[index++] = attribute;
			offset += attribute.get_element_count() * Buffer_Generator.FLOAT_BYTE_SIZE;
		}


The name, size and position were returned correctly on every computer.

I hope this is helpful to you.

spasi

The values 18, 18, 18, 10 (the first iteration for each shader program) seem to be equal to attribute_length (GL_ACTIVE_ATTRIBUTE_MAX_LENGTH). E.g. for the first shader "gl_MultiTexCoord0".length + 1 == 18 (the +1 is for the C string null terminator character). glGetActiveAttribType uses the same internal buffer as glGetProgrami, which suggests that glGetActiveAttribType causes an OpenGL error and nothing gets written to the buffer. The following 1's (for each program) are there because the internal buffer is also used in glGetActiveAttribSize, which works and writes 1 there.

I don't know why glGetActiveAttribType is failing. The code is exactly the same as glGetActiveAttribSize, except the pointer addresses for the size and type arguments are flipped.

Cornix

So? What should I do?
I can see that this is probably some kind of incompatibility with the drivers, but the method is not an OpenGL function (at least I can not find it in the reference pages) so I would assume its some kind of error on the lwjgl end. I mean, it is probably using the same code as glGetActiveAttrib somewhere because how else could it get the type of the attribute if there is no other way defined in openGL, right?

At least there should be some kind of warning that certain drivers do not work well together with glGetActiveAttribType; maybe in the documentation of the method.

spasi

Quote from: Cornix on January 07, 2014, 21:06:09So? What should I do?

Well, plain glGetActiveAttrib works fine, so you could use that. It's more efficient anyway, apparently you use all 3 pieces of information it returns. The Size/Type and string variants are only useful if you need 1 piece of info and don't want to bother with the other arguments.

If you'd like to help debug this further, it'd be useful to know exactly what OpenGL error is raised when glGetActiveAttribType is called.

Quote from: Cornix on January 07, 2014, 21:06:09I can see that this is probably some kind of incompatibility with the drivers, but the method is not an OpenGL function (at least I can not find it in the reference pages) so I would assume its some kind of error on the lwjgl end. I mean, it is probably using the same code as glGetActiveAttrib somewhere because how else could it get the type of the attribute if there is no other way defined in openGL, right?

This is the implementation:

public static int glGetActiveAttribType(int program, int index) {
	ContextCapabilities caps = GLContext.getCapabilities();
	long function_pointer = caps.glGetActiveAttrib;
	BufferChecks.checkFunctionAddress(function_pointer);
	IntBuffer type = APIUtil.getBufferInt(caps);
	nglGetActiveAttrib(program, index, 0, 0L, MemoryUtil.getAddress(type, 1), MemoryUtil.getAddress(type), APIUtil.getBufferByte0(caps), function_pointer);
	return type.get(0);
}


Indeed, it uses glGetActiveAttrib internally.