glVertexArrayAttribFormat requires vao to be bound [FIXED]

Started by Joona, November 01, 2017, 11:35:52

Previous topic - Next topic

Joona

Not posting to bugs-section since I'm not sure if I'm just confused about the usage of glVertexArray* -functions.

TL;DR: the triangle I draw on the screen isn't displayed unless I explicitly bind the VAO before using glVertexArrayAttribFormat. GetError() returns the code 1282, GL_INVALID_OPERATION. getVersion returns 4.5.0 NVIDIA 385.41. Using other methods (glVertexAttribPointer, glVertexAttribFormat) to upload the vbo to the vao works.

To my understanding the whole point of the DSA-functions was to not have to explicitly bind the buffers.


I have simple data to represent a triangle in a vbo like so:
float size = 1.0f;
float[] triData = new float[]
		{
			 0,      size,
			-size, -size,
			 size,	 -size
		};
FloatBuffer triDataFB = BufferUtils.createFloatBuffer( triData.length );
triDataFB.put( triData );
triDataFB.flip();

int vbo = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
	GL15.glBufferData(GL15.GL_ARRAY_BUFFER, triDataFB, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);


If I use glVertexAttribPointer, or glVertexAttribFormat to upload the vbo, the triangle will be visible:
GL30.glBindVertexArray(vao);
{	
	GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
		GL20.glVertexAttribPointer(0, 2, GL11.GL_FLOAT, false, 0, 0);
	GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
	
	GL20.glEnableVertexAttribArray(0);
}
GL30.glBindVertexArray(0);


GL30.glBindVertexArray(vao);
{
	GL43.glVertexAttribFormat(0, 2, GL11.GL_FLOAT, false, 0);
	
	GL43.glVertexAttribBinding(0, 0);
	GL43.glBindVertexBuffer(0, vbo, 0, 2 * Float.BYTES);
	
	GL20.glEnableVertexAttribArray(0);	
}
GL30.glBindVertexArray(0);


However, using exactly the same method for uploading data, just with glVertexArray* -functions, the triangle is not shown anymore. The error code 1282, GL_INVALID_OPERATION is given.
GL45.glVertexArrayAttribFormat(vao, 0, 2, GL11.GL_FLOAT, false, 0);

GL45.glVertexArrayAttribBinding(vao, 0, 0);
GL45.glVertexArrayVertexBuffer(vao, 0, vbo, 0, 2 * Float.BYTES);

GL45.glEnableVertexArrayAttrib(vao, 0);


For some reason binding the vao momentarily sets the triangle visible again:
GL30.glBindVertexArray(vao);
	GL45.glVertexArrayAttribFormat(vao, 0, 2, GL11.GL_FLOAT, false, 0);
GL30.glBindVertexArray(0);

GL45.glVertexArrayAttribBinding(vao, 0, 0);
GL45.glVertexArrayVertexBuffer(vao, 0, vbo, 0, 2 * Float.BYTES);

GL45.glEnableVertexArrayAttrib(vao, 0);



main loop:
GL30.glBindVertexArray(vao);
program.bind();		
while (display.running())
{
	GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
	
	GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
	
	display.draw();
}


shaders:
#version 450 core

layout (location = 0) in vec4 pos;

void main()
{	
	gl_Position = pos;
}

#version 450 core

out vec4 oColor;

void main()
{	
	oColor = vec4(1);
}


Graphics card is GeForce GTX 560 Ti (supports ogl 4.5). Printing the version gives "4.5.0 NVIDIA 385.41".

Edit. using windows7 pro

spasi

If you're using a core profile context, then you need to have a VAO bound to render anything. It's required by the specification.

KaiHH

QuoteTo my understanding the whole point of the DSA-functions was to not have to explicitly bind the buffers.
That is true. However, if it actually was a DSA function raising the GL error, then please note that a VAO only becomes an actual VAO when you either:
- create it via glGenVertexArrays() AND glBindVertexArray() or
- create it via glCreateVertexArrays()

If you merely call glGenVertexArrays() you CANNOT immediately pass the VAO handle to a DSA function, as the VAO is not yet known to actually represent a VAO. That means, the following code will print 'false':
int vao = GL30.glGenVertexArrays();
System.out.println(GL30.glIsVertexArrayObject(vao));

The following will print 'true':
int vao = GL45.glCreateVertexArrays();
System.out.println(GL30.glIsVertexArrayObject(vao));

This behaviour is by specification.

Joona

Thanks! I got it to work now.

Quote from: spasi on November 01, 2017, 14:14:24
If you're using a core profile context, then you need to have a VAO bound to render anything. It's required by the specification.
Do you mean when I'm calling the actual glDrawArrays? In that case, it is bound. Or when I'm using functions like glVertexArray*? I just assumed it was bound under the hood.

I had no idea just calling glGenVertexArrays() doesn't actually make it a VAO automagically. I still have no clue as to why it would be like this, but at least I know it doesn't.