5

系统:安卓4.03,OpenGL ES 2.0

问题:在第一帧已经用另一个程序/着色器渲染后调用 glAttachShader 时,某些设备 (Galaxy S3) 崩溃并出现“GL_INVALID_VALUE”错误(错误堆栈中没有更多详细信息)。其他设备(华硕 eee TF101)完全可以。该错误并不总是发生,有时它也是“GL_INVALID_ENUM”。如果我在第一次调用 onDrawFrame 时强制编译所有着色器,它适用于所有(我的)设备。

问题: 是否存在 openGL(ES) 机器无法编译着色器的状态?绑定的缓冲区、纹理或启用的属性数组是否可能会干扰将着色器附加到程序?如果是这样,在附加着色器和链接程序之前必须确保的理想状态是什么?在其他对象已经用其他着色器渲染之后编译着色器是否有效?

背景:我正在开发一个 Android 库,它允许我以更加面向对象的方式使用 openGL 图形(使用“场景”、“材质”、“模型”等对象),最终轻松编写游戏。场景、模型等是在与 GL 上下文不同的线程中创建的。只有当 onDrawFrame 遇到这些对象之一时,它才会在正确的线程中进行缓冲区对象绑定、纹理绑定和着色器编译。我想避免在代码开头编译所有着色器。根据材质、模型和场景的要求组装着色器源(例如:材质:包括凹凸贴图,模型:包括矩阵调色板浏览,场景:包括雾)。当从场景中删除模型时,我将再次删除着色器 - 如果我添加另一个模型,

在这一点上,我试图在不发布代码的情况下尽可能简洁——你可以想象从这个库中提取相关部分是很困难的。

4

2 回答 2

2

在渲染期间编译是完全有效的,但不鼓励这样做,因为驱动程序需要为此占用资源(CPU)。当某些状态被注入着色器时,一些驱动程序状态会在驱动程序端触发着色器重新编译。将绘图调用重组为共享相同驱动程序状态的块是明智的(着色器程序更喜欢这是驱动程序完成的最昂贵的操作之一)。

提示:确保“使用”所有在着色器中声明的变量、统一和属性,否则,Mali 驱动程序会在编译期间将它们删除,当您尝试获取统一位置、属性位置等时,驱动程序会返回 GL_INVALID_VALUE。

希望有帮助。

于 2013-01-22T15:47:27.203 回答
0

如果你复制Android开发包自带的BasicGLSurfaceView示例代码来启动你的项目,那么第一次调用

checkGlError

在附加顶点着色器之后。但是,您可能更早使用了无效值或枚举,或者在代码中的其他位置使用了无效值或枚举。但这只会在 glAttachShader 之后被此调用接收。

在我的例子中,我删除了一个仍然作为帧缓冲区渲染目标链接的纹理。我运行较慢的旧 Android 设备在删除之前编译了着色器,我的新设备以某种方式设法调用

glFramebufferTexture2D

在编译着色器之前。整个事情以某种方式与queueEvent和我对线程安全的理解不足有关。

感谢您的努力,TraxNet 和 Prateek Nina。

于 2013-01-26T14:54:45.563 回答