glBufferData 不断失败并出现 GL_INVALID_ENUM 即使它不应该

Posted

技术标签:

【中文标题】glBufferData 不断失败并出现 GL_INVALID_ENUM 即使它不应该【英文标题】:glBufferData keeps failing with GL_INVALID_ENUM even when it shouldn't 【发布时间】:2018-08-18 11:24:04 【问题描述】:

谁能看出这段代码有什么问题?

我对@9​​87654334@ 的调用一直失败,错误代码是GL_INVALID_ENUM。但是,我的值是正确的——我什至尝试直接硬编码这些值(以防万一)。根据docs,这应该可行。

编辑

我创建了一个最小的 - 或最小的 ANGLE + XAML + UWP 可以得到 - sample on GitHub。所有工作都发生在 5 个主要文件中:

MainPage.xaml.cs - 初始化 ANGLE 并启动渲染循环的主协调器 OpenGLES.cs - 初始化 ANGLE 上下文、显示和表面的逻辑 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);

我相信我的其余设置/绘图代码是正确的,因为这画得很好:

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);

【问题讨论】:

一个minimal reproducible example 会很好。 我的 GitHub github.com/mattleibow/ANGLE-Example 几乎是最少的 3 个缓冲区,而不是问题中的 1 个,但我会尝试获取单个文件版本。 GL 不是有史以来最短的代码。 @Rabbid76 是的,这很奇怪,这就是我开始这个问题的原因。我添加了一个最小的示例,它只是尝试渲染一个基本的三角形:github.com/mattleibow/ANGLE-Minimal 【参考方案1】:

如果您使用 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_DRAWGL_STREAM_READ...。

【讨论】:

你这个美丽的天才!我只是一个卑微的傻瓜。谢谢!就是这样,如此简单——只有白痴才会故意使用Int64 来表示C++ long。再次感谢!

以上是关于glBufferData 不断失败并出现 GL_INVALID_ENUM 即使它不应该的主要内容,如果未能解决你的问题,请参考以下文章

WiFiDirect discoverServices 不断失败并出现错误 3 (NO_SERVICE_REQUESTS)

为啥我的 .gitlab-ci.yml 在纱线测试中不断失败,并出现错误“/bin/sh: 1: react-scripts: not found”?

关于webgl中glBufferData的第二个参数的问题

比特币 RPC 连接不断失败

在启动中启用 CORS 失败并出现预检错误

为啥我的失败吐司在android kotlin中不断出现