WebGL着色器:可变变量的最大数量

9

根据 OpenGL ES 规范 第 2.10.4 节(着色器变量:varying 变量):

可用于处理 varying 变量的插值器数量由实现相关的常量 MAX_VARYING_VECTORS 给出。

该值表示可以插值的 四元素浮点向量 的数量;声明为矩阵或数组的 varying 变量将消耗多个插值器。

在链接程序时,任何被顶点着色器写入或由片段着色器读取的 varying 变量都会占用此限制。

如果着色器访问超过 MAX_VARYING_VECTORS 值的 varying 变量,则该程序可能无法成功链接。

在我的机器上,Chrome 中运行 gl.getParameter(gl.MAX_VARYING_VECTORS) 返回 15,这意味着我可以在着色器中使用 15 个 vec4 varying。

我做了一些测试来验证它。15 个 vec4 varying 可以正常工作,但尝试使用 16 个时,程序无法链接,gl.getProgramInfoLog() 返回 "Varyings over maximum register limit"

但有多少个类型为 vec3vec2float 的 varying 可以使用呢?

OpenGL ES 规范似乎在暗示这一点,而没有明确说明:

任何 varying 变量...都将占用此限制。

如果着色器访问超过 MAX_VARYING_VECTORS 值的 varying 变量,则该程序可能无法成功链接。

我有两个猜测:

  1. 可变浮点数的最大数量为:
    MAX_VARYING_VECTORS * 4
    (每个vec4向量有4个float
  2. 例如,如果MAX_VARYING_VECTORS8,则以下每个选项都可以安全使用而不会导致任何链接错误:
    • 8个vec4可变数
    • 10个vec3可变数
    • 16个vec2可变数
    • 32个float可变数
    • 3个vec4、3个vec3、3个vec2和5个float可变数
    • 长度为8的1个vec4可变数组
    • 长度为10的1个vec3可变数组
    • 长度为16的1个vec2可变数组
    • 长度为32的1个float可变数组
    • 任何其他vec4/vec3/vec2/float变量或数组的组合,最多使用32个float

因此,对于我的MAX_VARYING_VECTORS值为15,我猜最多可以使用60个float。 我的测试似乎证实了这一点。 例如,在我的机器上,30个vec2可变数可以正常工作,但31个会导致"Varyings over maximum register limit"链接错误。

所以我的问题是:

  • 我的两个猜测正确吗?
  • 如果MAX_VARYING_VECTORS8,那么使用16个vec2可变数是否安全?这保证总是能够工作吗?
1个回答

10

从WebGL规范中得知

OpenGL ES Shading Language,版本1.00 [GLES20GLSL],附录A,第7节“计算Varying和Uniform变量”的定义了一种保守算法,用于计算着色器中所有uniform和varying变量所需的存储空间大小。GLSL ES规范要求,如果附录A中定义的打包算法成功,则着色器必须在目标平台上编译成功。WebGL API进一步要求,如果打包算法对着色器的uniform变量或程序的varying变量失败,则编译或链接必须失败。

因此,是的,如果你阅读算法,如果MAX_VARYING_VECTORS为8,则可以使用16个vec2。但是您不能使用10个vec3。您只能使用8个vec3

此外还有数组限制。例如,如果MAX_VARYING_VECTORS为8,则无法拥有大于8的float数组或大于8的vec2数组。


1
非常感谢。打包算法的描述非常有帮助,特别是:“目标架构由寄存器网格组成,每行 MAX_VARYING_VECTORS 列 4 个用于变量。每个寄存器可以包含一个 float 值。不允许拆分变量。向量始终占据单行寄存器。”这解释了为什么不允许使用 10 个 vec3。“数组的元素必须在不同的行中。”因此,一个数组不能超过 MAX_VARYING_VECTORS 个元素。 - TachyonVortex
1
这一点也很重要需要注意:“如果在片段着色器中引用(预处理后),则在计算varyings的存储要求时包括内置特殊变量(gl_FragCoordgl_FrontFacinggl_PointCoord)。 - TachyonVortex
@TachyonVortex 我知道这是一个有点老的帖子,但似乎数组限制并不总是适用。在我的Mac机器上的Firefox中,gl.getParameter(gl.MAX_VARYING_VECTORS)返回16,但我能够使用32个元素的vec2数组。然而,在Chrome上,我的MAX_VARYING_VECTORS为31,浏览器拒绝链接程序,说Varyings over maximum register limit。我需要一个大约50个元素的varying vec2数组,想知道如何实现。 - Daniel W
这看起来像是Firefox 36的一个错误。在我的Mac上,符合性测试失败了。检查FirfoxNightly (FF 39),它似乎已经被修复了。也许你应该尝试一下,看看你的程序是否会出现与Chrome相同的行为。至于需要50个vec2s,听起来你可能无法解决。如果MAX_VARYING_VECTORS是16,那么你最多只能有32个vec2s。 - gman
出乎意料的是,我的程序在Firefox和Nightly中使用50个vec2仍然可以正常运行。对我来说是好消息,但就符合性而言并不那么好。 - Daniel W
我知道这已经过时了,但是对于阅读此线程的人来说,如果您想在着色器中使用值的随机访问数组,您应该使用纹理,而不是一个统一的数组。 - gman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接