关于性能:webgl中的什么命令导致纹理内存被处理

What command in webgl cause texture memory to be processed

设置单个纹理WebGL程序时,什么命令实际上导致完成"工作"?

在我看来,textImage2D命令将html图像数据上传到GPU:

1
gl.texImage2D(target, level, internalformat, format, type, HTMLImageElement);

但是,一旦数据上传并绑定到纹理,该纹理仍需要"绑定"到采样器。

1
2
3
setActiveTexture(gl, 0, this['textureRef0']);
var samplerRef = gl.getUniformLocation(program, 'sampler0');
gl.uniform1i(samplerRef, 0);

是否需要分配任何内存以将纹理绑定到采样器?还是只是将指针指向纹理数据而更改的指针?

将纹理绑定到帧缓冲区又如何呢?

1
2
gl.bindFramebuffer(gl.FRAMEBUFFER, this.globalFB);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureRef0, 0);

单独行动是否会导致任何重大的性能问题?还是仅在调用程序并将数据渲染到该纹理时才完成"真正的"工作?


texImage2D分配内存,因为驱动程序需要在texImage2D返回时更改您传递的数据,从而复制传递给它的数据。

framebuffers不会分配太多内存,内存是附件。但是,帧缓冲区需要进行验证,因此最好使用所需附件的每种组合制作多个帧缓冲区,而不是更改单个帧缓冲区上的附件

换句话说,例如,如果您正在对纹理进行ping ponging处理后处理,例如

1
2
3
4
5
6
7
8
9
10
 // init time
 const fb = gl.createFramebuffer();

 // render time
 for each pass
    gl.framebufferTexture2D(...., dstTex);   // bad!
    ...
    gl.drawXXX
    const t = srcTex; srcTex = dstTex; dstTex = t;  // swap textures
 }

vs

1
2
3
4
5
6
7
8
9
10
11
12
13
 // init time
 let srcFB = gl.createFramebuffer();
 gl.framebufferTexture(...., srcTex);
 let dstFB = gl.createFramebuffer();
 gl.framebufferTexture(...., dstTex);

 // render time
 for each pass
    gl.bindFramebuffer(dstFB);   // good
    ...
    gl.drawXXX
    const t = srcFB; srcFB = dstFB; dstFB = t;  // swap framebuffers
 }

纹理还存在一个问题,由于API设计的原因,GL第一次进行纹理绘制时(以及任何时候更改其内容)都有大量工作要做。

考虑到这是WebGL中提供mips的正常顺序

1
2
3
4
5
texImage2D level 0, 16x16
texImage2D level 1, 8x8
texImage2D level 2, 4x4
texImage2D level 3, 2x2
texImage2D level 4, 1x1

但这也是完全有效的API调用

1
2
3
4
5
6
texImage2D level 0, 16x16
texImage2D level 1, 8x8
texImage2D level 2, 137x324    // nothing in the spec prevents this. It's fully valid
texImage2D level 3, 2x2
texImage2D level 4, 1x1
texImage2D level 2, 4x4        // fix level 2 before drawing

对级别2的调用具有某种奇怪的大小是有效的。不允许输入错误。当然,如果您在绘制之前不替换第2级,它将无法绘制,但根据API上传数据并没有错。这意味着直到实际使用纹理时,驱动程序才可以查看每个mip的数据,格式和大小,检查它们是否都正确,然后最终将数据排列在GPU上。

添加了

texStorage以解决该问题(在WebGL2 / OpenGL ES 3.0中可用)

调用activeTexture,将纹理与bindTexture绑定以及设置统一不会占用内存,也不会出现明显的性能问题。