Hello Guest

glVertexArrayAttribFormat requires vao to be bound [FIXED]

  • 3 Replies
  • 4401 Views
glVertexArrayAttribFormat requires vao to be bound [FIXED]
« on: November 01, 2017, 11:35:52 »
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:
Code: [Select]
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:
Code: [Select]
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);

Code: [Select]
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.
Code: [Select]
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:
Code: [Select]
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:
Code: [Select]
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:
Code: [Select]
#version 450 core

layout (location = 0) in vec4 pos;

void main()
{
gl_Position = pos;
}
Code: [Select]
#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
« Last Edit: November 02, 2017, 09:33:28 by Joona »

*

Offline spasi

  • *****
  • 2261
    • WebHotelier
Re: glVertexArrayAttribFormat requires vao to be bound
« Reply #1 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.

*

Offline KaiHH

  • ****
  • 334
Re: glVertexArrayAttribFormat requires vao to be bound
« Reply #2 on: November 01, 2017, 17:58:21 »
Quote
To 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':
Code: [Select]
int vao = GL30.glGenVertexArrays();
System.out.println(GL30.glIsVertexArrayObject(vao));
The following will print 'true':
Code: [Select]
int vao = GL45.glCreateVertexArrays();
System.out.println(GL30.glIsVertexArrayObject(vao));
This behaviour is by specification.
« Last Edit: November 01, 2017, 19:04:11 by KaiHH »

Re: glVertexArrayAttribFormat requires vao to be bound
« Reply #3 on: November 02, 2017, 09:30:56 »
Thanks! I got it to work now.

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.