我的应用程序是使用 OpenGL API 用 C++ 编写的,我使用 Emscripten 为桌面操作系统以及 Web 构建它。不久前出现了一个奇怪的错误:在桌面上一切正常(进行任何优化,valgrind-clean),但在 WebGL 中崩溃并出现以下错误:
抛出异常:TypeError:参数 2 of WebGLRenderingContext.uniform4fv 无法转换为以下任何一个: Float32Array,无限制FloatSequence。
我用
-g4
构建了它(生成带有调试信息的可读 JS 代码),并发现有时 glUniform4fv
会变为零,因为它是 count
参数。 Emscripten 生成的 OpenGL 调用包装器如下:
function _glUniform4fv(location, count, value) {
var view;
if (4*count <= GL.MINI_TEMP_BUFFER_SIZE) {
// avoid allocation when uploading few enough uniforms
view = GL.miniTempBufferViews[4*count-1];
for (var i = 0; i < 4*count; i += 4) {
view[i] = HEAPF32[(((value)+(4*i))>>2)];
view[i+1] = HEAPF32[(((value)+(4*i+4))>>2)];
view[i+2] = HEAPF32[(((value)+(4*i+8))>>2)];
view[i+3] = HEAPF32[(((value)+(4*i+12))>>2)];
}
} else {
view = HEAPF32.subarray((value)>>2,(value+count*16)>>2);
}
GLctx.uniform4fv(GL.uniforms[location], view);
}
因此,当这个包装器变为零
count
并进入第一个分支时,它会执行view = GL.miniTempBufferViews[-1];
,即undefined
。该值变为 GLctx.uniform4fv
,产生上述错误。
好吧,让我们看一下OpenGL文档,ES 2.0版本,它是WebGL1的基础:
数
指定要添加的元素数量 被修改。如果目标为 统一变量不是数组,如果是数组则为 1 或更多 一个数组。
...
错误
...
如果计数小于 0,则会生成 GL_INVALID_VALUE。
所以我看不到当
count
为零时 OpenGL 应该做什么。我认为,当我们没有任何东西可以传递给着色器时,这是一个正确的值。至少,它不应该崩溃。
所以我有以下问题:
1) 从 GLES 2.0 规范来看,它是未定义的行为还是实现定义的行为?
2) Emscripten 的正确反应应该是什么?绝对不允许设置错误状态,因为规范中没有此类错误。但也许将零大小的
Float32Array
传递给 GLctx.uniform4fv
更正确,让浏览器的 Webgl 实现来处理它?我应该向 Emscripten 开发人员报告问题吗?
回到这个老问题,我相信这个问题已经在 emscripten 中修复了 https://github.com/emscripten-core/emscripten/pull/16837