The locations of a builtin vertex attribute

I am only using one attribute, and assigning it to slot3:

Two users get this, with a GEForce 5700 and a 7600 GS:

error: the locations of a builtin vertex attribute (gl_Colour) and a bound generic vertex attribute (BoneIndice) collided; assign the generic attribute to a different location via glBindAttribLocaitonARB

How can I avoid this error?

Don’t bind the attribute yourself, let the linker handle it for you?

You should be using glGetAttribLocationARB(program, “boneIndice”) to find out the location for the attribute, the GLSL decides on the locations itself (expect it to be different for different shaders), you need to ask it which locations it decided on, and use those.

Basically, you should never bind any attribute other than the one the spec forces you to bind (either the built-in gl_Position which is automatically bound, or attribute 0 when you aren’t using the built-in gl_Position).

Generally, the reason someone would want to forcibly bind an attribute to a location is if they want their rendering code to always use that attribute location. That is, you don’t have any direct connection between your mesh’s attributes and your program’s attributes; the only connection is via a convention (‘BoneIndice’ is alway attribute 3, etc).

This is not the best way to operate, but if you absolutely must, then you must not use any built-in vertex attributes.

By specification there should be no aliasing between conventional and generic attributes however there is one in Nvidia GLSL implementation (for some compatibility reasons). Basically it is the same as described in specification of ARB_vertex_program extension (table X.1) so if you need to combine fixed binding of generic attributes with conventional attributes, you should check that table.

however there is one in Nvidia GLSL implementation (for some compatibility reasons).

They’ve always had aliasing, ever since their initial assembly vertex program spec. Apparently, they think it’s OK to randomly violate the GL spec just because they don’t agree with a minor but significant API point.

I did some research. The problem is that:
[ul][li] The NV_vertex_program explicitly required the aliasing (value can be set and read by both generic and conventional attribute).[] The ARB_vertex_program allows it. It uses the same value of enumerants as NV_vertex_program and explicitly states that the[/li]state (e.g. including vertex attribute arrays and values) is identical and can be set by both the NV and ARB entry points (with undefined behavior for aliased attributes).[li] The ARB_vertex_shader disallows aliasing it yet still uses the same values of enumerants and entry points as the ARB_vertex_program.[] OGL 2.0 incorporated the ARB_vertex_shader with renamed entry points however values of enumerants remained the same.[/ul][/li]The Nvidia still wants to support NV_vertex_program because old programs use it however in that case there is conflict because the enumerants or even entire entry points (in case of the ARB variants from ARB_vertex_shader) should behave differently under different extensions.

For example if you set the glColor then the value of CURRENT VERTEX ATTRIB == CURRENT_VERTEX_ATTRIB_ARB == CURRENT_ATTRIB_NV for attribute 3 should be unchanged under ARB_vertex_shader extension yet it should be modified under the NV_vertex_program.

So basically you can not fully support both those extenions at the same time. The Nvidia decided to not break functionality of already existing old programs and instead documented this incorrect behavior so future programs have possibility to work around this limitation.

So basically you can not fully support both those extenions at the same time.

You can; it just requires effort. You have to have a flag in your shader that says, “This is a glslang shader, so turn off aliasing of attributes.” That way, when you go and use NV_vertex_program_* to do the low-level compiling, you simply have it look at the flag, see that aliasing should be turned off, and turn it off.

See? That’s simple.

As I understand it the problem exists even if you never run or compile any shader.

Lets have the following program utilizing ARB_vertex_program extension.

init_gl_context() ;
glVertexAttrib3fARB( 3, 0.5, 0.5, 0.5 ) ;
glColor3f( 1.0, 1.0, 1.0 ) ;

GLfloat result[ 4 ] ;
glGetVertexAttribfvARB( 3, GL_CURRENT_VERTEX_ATTRIB_ARB, result ) ; 

Question is what what will be value of result[ 0 ] in presence of various additional extensions.

[ul][] Without any additional extension present, the value is undefined.[] If only ARB_vertex_shader is present, the value will be 0.5. This extension modifies the ARB_vertex_program extension to remove the aliasing[] If only NV_vertex_program is present, the value will be 1.0. The ARB_vertex_program specifies that if both extensions are present, both ARB and NV functions will set the same state and aliasing operates as in the NV_vertex_program. The NV_vertex_program extension mentions several times that the state used for current values of generic vertex attributes is aliased with state used for current values of conventional vertex attributes.[] If both ARB_vertex_shader and NV_vertex_program are present, there is problem. The ARB_vertex_shader specification does not specify how to modify the section of ARB_vertex_program specification which talks about interraction with the NV_vertex_program. Because of this, the result is imho badly defined (the state should be shared yet one extension manipulating that state requires aliasing while other disallows it). Even if it were defined perfectly there might be older programs which relly on the aliasing behavior allowed by NV_vertex_program. Such programs would be brokend by simple addition of the ARB_vertex_shader extension even if they do not know nor care about that extension.[/ul]

If I just call glGetAttribLocationARB() without setting is -1 is always returned.

I see…if you set the location, you have to do so before linking, but if you retrieve the location you have to do so after linking.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.