glBufferData 一直失败 GL_INVALID_ENUM 即使它不应该
glBufferData keeps failing with GL_INVALID_ENUM even when it shouldn't
谁能看出这段代码有什么问题?
我对 glBufferData
的调用一直失败,错误代码是 GL_INVALID_ENUM
。但是,我的值是正确的——我什至尝试直接对值进行硬编码(以防万一)。根据 docs 这应该有效。
编辑
我创建了一个最小的 - 或者最小的角度 + XAML + UWP 可以获得 - sample on GitHub。所有工作都在 5 个主要文件中进行:
- MainPage.xaml.cs
- 初始化 ANGLE 并启动渲染循环的主要协调器
- OpenGLES.cs - 初始化角度上下文、显示和表面的逻辑
- SimpleRenderer.cs - 三角形的主要效果图
- Egl.cs & Gles.cs - p/invoke 方法
如果您下载 运行 代码,它应该在 glBufferData
on line 61
之后抛出异常
要在基于缓冲区的数组和直接数组之间切换,只需更改以下行:SimpleRenderer.cs#L31
原版
就我的生活而言,它似乎与 C++ 代码匹配 - 运行没问题。我在 Windows UWP 上使用 ANGLE。 (如果您需要更多上下文,我有完整的代码 here)
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();
}
我的 p/invoke 层 Gles
看起来像这样:
[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);
这是我的 C++ 代码的样子:
GLfloat vertexPositions[] = { ... };
glGenBuffers(1, &mVertexPositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
我相信我的 setup/drawing 代码的其余部分是正确的,因为它绘制得很好:
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);
如果您使用 32 位架构,例如x86,那么 GLsizeiptr
必须是 32 位数据类型。
要解决此问题,别名 GLsizeiptr
的类型必须是 System.Int32
:
using GLsizeiptr = System.Int32;
如果类型为 System.Int64
,则
的最后一个参数
public static extern void glBufferData(
GLenum target, GLsizeiptr size, IntPtr data, GLenum usage);
会错位。
这会导致glBufferData
中的GL_INVALID_ENUM
错误,因为最后一个参数(usage
)的值不是GL_STREAM_DRAW
、GL_STREAM_READ
.. . .
谁能看出这段代码有什么问题?
我对 glBufferData
的调用一直失败,错误代码是 GL_INVALID_ENUM
。但是,我的值是正确的——我什至尝试直接对值进行硬编码(以防万一)。根据 docs 这应该有效。
编辑
我创建了一个最小的 - 或者最小的角度 + XAML + UWP 可以获得 - sample on GitHub。所有工作都在 5 个主要文件中进行:
- MainPage.xaml.cs - 初始化 ANGLE 并启动渲染循环的主要协调器
- OpenGLES.cs - 初始化角度上下文、显示和表面的逻辑
- SimpleRenderer.cs - 三角形的主要效果图
- Egl.cs & Gles.cs - p/invoke 方法
如果您下载 运行 代码,它应该在 glBufferData
on line 61
要在基于缓冲区的数组和直接数组之间切换,只需更改以下行:SimpleRenderer.cs#L31
原版
就我的生活而言,它似乎与 C++ 代码匹配 - 运行没问题。我在 Windows UWP 上使用 ANGLE。 (如果您需要更多上下文,我有完整的代码 here)
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();
}
我的 p/invoke 层 Gles
看起来像这样:
[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);
这是我的 C++ 代码的样子:
GLfloat vertexPositions[] = { ... };
glGenBuffers(1, &mVertexPositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
我相信我的 setup/drawing 代码的其余部分是正确的,因为它绘制得很好:
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);
如果您使用 32 位架构,例如x86,那么 GLsizeiptr
必须是 32 位数据类型。
要解决此问题,别名 GLsizeiptr
的类型必须是 System.Int32
:
using GLsizeiptr = System.Int32;
如果类型为 System.Int64
,则
public static extern void glBufferData(
GLenum target, GLsizeiptr size, IntPtr data, GLenum usage);
会错位。
这会导致glBufferData
中的GL_INVALID_ENUM
错误,因为最后一个参数(usage
)的值不是GL_STREAM_DRAW
、GL_STREAM_READ
.. . .