Webgl2的3D纹理最大尺寸是多少?

时间:2019-02-10 23:39:07

标签: webgl

我正在使用

在webgl中创建3D纹理

gl.bindTexture(gl.TEXTURE_3D,纹理){

const level = 0;
const internalFormat = gl.R32F;
const width = 512;
const height = 512;
const depth = 512; 

const border = 0;
const format = gl.RED;
const type = gl.FLOAT;
const data = imagesDataArray;

......命令

使用32F值时,看起来512 * 512 * 512的大小有点麻烦,因为chrome(在笔记本电脑8 gb ram上运行)浏览器在上载此大小的3D纹理时崩溃,但并非总是如此。使用说尺寸为512 * 512 * 256的纹理似乎总是可以在我的笔记本电脑上使用。 有什么方法可以提前告知GPU可以适应与webgl2相关的3D纹理的最大大小吗?

最诚挚的问候

1 个答案:

答案 0 :(得分:2)

不幸的是,没有办法无法告诉您有多少空间。

您可以查询GPU可以处理的最大尺寸,但无法查询GPU可用的内存量,就像无法查询JavaScript可用的内存量一样。

也就是说,512 * 512 * 512 * 1(R)* 4(32F)至少为0.5 Gig。您的笔记本电脑的GPU是否具有0.5Gig?实际上,您可能至少需要1gig的GPU内存才能使用.5gig作为纹理,因为操作系统需要为应用程序的窗口等留出空间...

浏览器还对可以使用的内存量设置了不同的限制。

一些要检查的东西。

  • 您有多少GPU内存。

    如果不超过0.5gig,则说明您不走运

  • 如果您的GPU的容量超过0.5gig,请尝试使用其他浏览器

    Firefox的限制可能与Chrome的限制不同

  • 可以完全创建纹理吗?

    使用gl.texStorage3D,然后调用gl.getError。它会出现内存不足错误还是在那里崩溃。

  • 如果gl.texStorage3D没有崩溃,您可以一次使用gl.texSubImage3D

    上传一点数据吗?

    我怀疑即使gl.texStorage3D也能正常工作,因为浏览器仍必须分配0.5gig来清除纹理。如果它确实起作用,则表明另一个问题是,上传纹理需要的内存至少是Chrome的3x-4x。

    1. JavaScript中有您的数据

      data = new Float32Array(size);
      
    2. 数据被发送到GPU进程

      gl.texSubImage3D (or any other texSub or texImage command)
      
    3. GPU进程将数据发送到驱动程序

      glTexSubImage3D(...) in C++
      

      驱动程序是否需要1或2份副本,我不知道。有可能保持 在ram中复制一份并将其上传到GPU。它保留副本,以便可以 如果需要交换数据以腾出空间以供其他使用,请重新上传数据。 是否发生这种情况取决于驾驶员。

还请注意,虽然我认为这不是问题,但允许驱动器将纹理扩展到需要2gig的RGBA32F。可能不是这样做的,但是我知道过去已经模拟了某些格式。

注意:texImage可能比texStorage占用更多的内存,因为texImage的语义意味着驱动程序直到绘制之前才能真正制作纹理,因为它不知道如果您以后要添加MIP级别。另一方面,texStorage会告诉驱动程序确切的mips大小和数目,因此不需要中间存储。

function main() {
  const gl = document.createElement('canvas').getContext('webgl2');
  if (!gl) {
    return alert('need webgl2');
  }
  
  const tex = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_3D, tex);
  gl.texStorage3D(gl.TEXTURE_3D, 1, gl.R32F, 512, 512, 512);
  log('texStorage2D:', glEnumToString(gl, gl.getError()));
  const data = new Float32Array(512*512*512);
  for (let depth = 0; depth < 512; ++depth) {
    gl.texSubImage3D(gl.TEXTURE_3D, 0, 0, 0, depth, 512, 512, 1, gl.RED, gl.FLOAT, data, 512 * 512 * depth);
  }
  log('texSubImage3D:', glEnumToString(gl, gl.getError()));
}

main();

function glEnumToString(gl, value) {
  return Object.keys(WebGL2RenderingContext.prototype)
    .filter(k => gl[k] === value)
    .join(' | ');
}

function log(...args) {
  const elem = document.createElement('pre');
  elem.textContent = [...args].join(' ');
  document.body.appendChild(elem);
}