WebGL 上的错误“Tex 图像 TEXTURE_2D 级别 0 导致延迟初始化”

cak*_*aka 10 javascript webgl

我收到错误消息:Error: WebGL warning: drawElements: Tex image TEXTURE_2D level 0 is incurring lazy initialization.在 WebGL 上,我想知道实际上是什么意思。

无论如何,延迟初始化如何在单线程应用程序中成为问题?我理解为当你在 getter 中初始化一个变量时?

我试着寻找我的错误信息并没有真正找到任何关于它的好信息。

这是我处理纹理的代码:

            const images = await Promise.all(model.maps.map(map => new Promise((resolve, reject) => {
                const image = new Image();

                image.src = map;
                image.onload = event => {
                    const texture = gl.createTexture();

                    gl.bindTexture(gl.TEXTURE_2D, texture);
                    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, image.width, image.height, 0, gl.RGBA, gl.FLOAT, null);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
                    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);

                    gl.bindTexture(gl.TEXTURE_2D, null);

                    resolve(texture);
                };

                image.onerror = error => {
                    console.log(error);
                    resolve(null);
                };
            })));
Run Code Online (Sandbox Code Playgroud)

我的绘图功能的相关部分基本上是:

gl.bindTexture(gl.TEXTURE_2D, textures[material.textureIndex]);
gl.activeTexture(gl.TEXTURE0);
gl.drawElements(gl.TRIANGLES, material.faceCount * 3, gl.UNSIGNED_SHORT, drawnCount);
Run Code Online (Sandbox Code Playgroud)

话虽如此,如果我使用 6 参数语法:gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.FLOAT, image);那么此错误消息不再显示,我设法正确呈现。

gma*_*man 14

这不是错误。这是一个警告。

错误:WebGL警告...

它在前面说“错误”非常令人困惑,但即使它只说“警告”我已经争论了很长时间它是一个不好的警告。

警告是 WebGL 需要做一些重要的工作。

当你制作一个纹理并且你没有向它传递任何数据时,你null作为最后一个参数传递给texImage2D,这意味着在某个时候 WebGL 必须清除纹理。假设纹理是 2048x2048 RGBA/UNSIGNED_BYTE。实际上,WebGL 必须分配 16meg 的 ram (2048x2048x4),将 16meg 的 ram 清除为 0,并gl.texSubImage2D在实际使用纹理之前调用在纹理中置零。如果他们不这样做,纹理中将包含随机数据,可能是机密、密码、以前的图形内存(如照片)或其他任何数据。

因此,警告告诉您发生了一些重要的工作。

此警告的问题是停止警告的解决方法比警告本身更糟糕。解决方法是让您自己清除纹理。为此,您需要在 JavaScript 中分配 16meg,就像在new Uint8Array(2048 * 2048 * 4). 这意味着 JavaScript 正在分配 16 兆字节,它还清除了 16 兆字节。它还分配一个Uint8Array对象来跟踪该 16meg。该Uint8Array对象是一个复杂的 JavaScript 对象,可能是多个组合在一起的对象的集合,例如,ArrayBuffer还分配了一个对象。这些对象都有原型链,并且能够添加属性和方法以及 getter 和 setter。那Uint8ArrayArrayBuffer还必须进行跟踪,以便以后可以对它们进行垃圾回收,这意味着它们甚至存在开销。更糟糕的是,如果浏览器是 Chrome 的多进程,我相信 Firefox 正在努力,那么在 JavaScript 中分配的 16meg 必须复制到 GPU 进程,这意味着首先 GPU 进程也需要分配 16meg 的 ram,数据必须从运行网页的进程复制到 GPU 进程,以便它可以传递给图形驱动程序。甚至更多的工作。

因此,换句话说,让 Firefox 关闭其警告实际上会使您的代码变慢并使用更多内存,如果 Firefox 只是默默地自行清除纹理。因此,为什么我说警告不应该存在

Firefox 的开发人员有一个观点,即任何时候 WebGL 做一些重要的事情他们都想给你一个警告。鉴于治愈使您的代码更重,我不同意他们的 POV。Chrome 不会发出此警告。这也让开发人员感到困惑,因为他们认为他们做错了什么。他们没有做错任何事。

https://bugzilla.mozilla.org/show_bug.cgi?id=1478216

至于没有渲染的东西,在你发布的代码中,你没有在纹理中放置任何东西,所以纹理当然是 0,0,0,0。

  • 这是[另一个可以说是糟糕的警告](https://bugzilla.mozilla.org/show_bug.cgi?id=1279855),因为它让开发人员认为他们做错了什么,而实际上他们没有做错,并且解决方法会更糟糕,更重。如果他们想保留这些警告,我认为它们应该只显示在特殊的“检查性能”模式中,但即使这样,警告也是假的,因为停止警告的解决方法会使性能变慢并使用更多内存。 (2认同)