无法在三星设备上分配变量 [OpenGL ES]

Tar*_*ras 3 android opengl-es fragment-shader

在三星设备上编译模糊着色器失败并出现错误:无法分配变量

着色器代码如下:

#ifdef GL_ES
precision mediump float;
#endif

varying vec2 v_texCoord;
varying vec2 v_blurTexCoords[14];
varying vec2 pixel_size;

uniform vec2 v_resolution;
uniform sampler2D u_texture;
uniform mat4 u_projTrans;

void main()
{
     ...
}
Run Code Online (Sandbox Code Playgroud)

在其他设备上运行良好,三星设备可能有什么问题?

Ret*_*adi 5

看来您只是超出了实现所支持的变量数量。可以通过以下方式查询变化向量的最大数量:

GLint maxVarying == 0;
glGetIntegerv(GL_MAX_VARYING_VECTORS, &maxVarying);
Run Code Online (Sandbox Code Playgroud)

合规实现所需的最小限制是 8。这意味着至少vec4支持 8 种类型变化。

您的案例很有趣,因为您总共使用了 16 种不同的 type vec2。您可能认为这适合 8 个vec4值的空间,因此应该适用于所有设备。但事情比这更复杂。

关于这个主题的详细细节可以在 GLES 1.00 规范第 111 页开始的附录 A.7 中找到,标题为“Counting of Varyings and Uniforms”。这是大约 2.5 页的非常技术性的描述,我无法在这里重复。但本质上,它描述了一种可能的打包算法,实现可以在兼容的情况下使用该算法。他们可以使用更有效包装的东西,但他们不必这样做。

此打包算法中适用于您的情况的一个关键部分如下:

向量总是占据单行寄存器。数组的元素必须位于不同的行中。例如 vec4 将始终占据一行;float[8] 将占据一列。由于不允许拆分变量,例如大数组。对于变量,float[16] 总是会因该算法而失败。

这意味着,对于仅支持 8 个不同向量且使用此兼容算法的实现,您无法容纳14 个值的数组vec2。它可以容纳 16 个类型的单个值vec2。或者例如,如果我正确理解规范,则为 8 个vec2值和 8 个类型的单值的数组vec2。但没有一个数组的大小大于 8。

为了让你的着色器安全编译,你需要一个至少返回 14 的实现GL_MAX_VARYING_VECTORS