Can anyone see what is wrong with this code?
My call to glBufferData
keeps failing and the error code is GL_INVALID_ENUM
. But, my values are correct - I even tried hardcoding the values in directly (just in case). According to the docs this should work.
EDIT
I created a minimal - or as minimal as ANGLE + XAML + UWP can get - sample on GitHub. There are 5 main files where all the work happens:
If you download and run the code, it should throw an exception after the glBufferData
on line 61
To toggle between a buffer-based array and the direct array, just change the line: SimpleRenderer.cs#L31
ORIGINAL
For the life of me it appears to match the C++ code - which runs fine. I am using ANGLE on Windows UWP. (I have the full code here if you need more context)
GLfloat[] vertexPositions = new[] {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
Gles.glGenBuffers(1, out GLuint mVertexPositionBuffer);
Gles.glBindBuffer(0x8892 /*Gles.GL_ARRAY_BUFFER*/, mVertexPositionBuffer);
var gcData = GCHandle.Alloc(vertexPositions, GCHandleType.Pinned);
try {
var size = vertexPositions.Length * Marshal.SizeOf<GLfloat>();
var data = gcData.AddrOfPinnedObject();
Gles.glBufferData(0x8892 /*Gles.GL_ARRAY_BUFFER*/, size, data, 0x88E4 /*Gles.GL_STATIC_DRAW*/);
// Gles.glGetError() == Gles.GL_INVALID_ENUM
} finally {
gcData.Free();
}
My p/invoke layer Gles
looks like this:
[DllImport(libGLESv2)]
public static extern void glGenBuffers(GLsizei n, out GLuint buffers);
[DllImport(libGLESv2)]
public static extern void glBindBuffer(GLenum target, GLuint buffer);
[DllImport(libGLESv2)]
public static extern void glBufferData(GLenum target, GLsizeiptr size, IntPtr data, GLenum usage);
This is what my C++ code looks like:
GLfloat vertexPositions[] = { ... };
glGenBuffers(1, &mVertexPositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
I believe the rest of my setup/drawing code is correct because this draws just fine:
GLfloat[] vertexPositions = new[] {
0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};
var gcData = GCHandle.Alloc(vertexPositions, GCHandleType.Pinned);
try {
Gles.glVertexAttribPointer((GLuint)mPositionAttribLocation, 3, Gles.GL_FLOAT, Gles.GL_FALSE, 0, gcData.AddrOfPinnedObject());
} finally {
gcData.Free();
}
Gles.glEnableVertexAttribArray((GLuint)mPositionAttribLocation);
Gles.glDrawArrays(Gles.GL_TRIANGLES, 0, 3);
If you use a 32 bit architecture e.g. x86, then GLsizeiptr
has to be a 32 bit datatype.
To solve the issue the type of the alias GLsizeiptr
has to be System.Int32
:
using GLsizeiptr = System.Int32;
If the type would be System.Int64
, then the last paramters of
public static extern void glBufferData(
GLenum target, GLsizeiptr size, IntPtr data, GLenum usage);
would be misaligned.
This causes the GL_INVALID_ENUM
error in glBufferData
, because the value of the last parameter (usage
) is not GL_STREAM_DRAW
, GL_STREAM_READ
... .