OpenGL ES 3实例渲染失败,但在桌面上可以工作。

4

我能够在桌面上使用GLSL 330核心的实例渲染,但是我无法在安卓上运行相同的C++代码(使用SDL2和NDK构建系统以及Android Studio)。

下面显示了logcat错误:

-18 15:49:57.264 20996-21026/package I/SDL/APP: shaders/mobile/sceneShader.frag.glsl compiled successfully
10-18 15:49:57.274 20996-21026/package I/SDL/APP: Program link failed: --From Vertex Shader:
10-18 15:49:57.274 20996-21026/packageI/SDL/APP: linker error: multiple attribute attempt to bind at same location 
10-18 15:49:57.274 20996-21026/packageI/SDL/APP: --From Fragment Shader:
10-18 15:49:57.274 20996-21026/package I/SDL/APP: linker error: multiple attribute attempt to bind at same location 

我的桌面和移动设备着色器代码除了文件顶部的 #version 行不同之外完全相同(分别指定 es 或桌面版)。

这是我的移动设备着色器代码:

#version 300 es

precision mediump float;

// attribute data
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec2 VertexTexCoord;
layout (location = 2) in vec3 VertexNormal;
layout (location = 3) in mat4 InstanceTransform; // used for translating the positions of instance renders

// varying data
layout (location = 0) out vec3 vPosition;
layout (location = 1) out vec2 vTexCoord0;
layout (location = 2) out vec2 vTexCoord1;
layout (location = 3) out vec3 vTexSkyboxCoord;
layout (location = 4) out vec3 vNormal;
layout (location = 5) out vec3 vClampColor;

// uniform data
layout (location = 0) uniform bool uInstanceRendering;

layout (location = 1) uniform mat4 uModelViewMatrix;
layout (location = 2) uniform mat4 uProjectionMatrix;
layout (location = 3) uniform mat3 uNormalMatrix;

layout (location = 4) uniform vec2 uTexOffset0;
layout (location = 5) uniform vec2 uTexOffset1;

void main(void)
{
    vec4 mvPosition;

    if (uInstanceRendering)
    {
        mvPosition = uModelViewMatrix * InstanceTransform * vec4(VertexPosition, 1.0);
    }
    else
    {
        mvPosition = uModelViewMatrix * vec4(VertexPosition, 1.0);
    }

    vTexSkyboxCoord = VertexPosition; // for skybox rendering

    const float atlasRows = 6.0f;
    vTexCoord0 = (VertexTexCoord / atlasRows) + uTexOffset0;
    vTexCoord1 = (VertexTexCoord / atlasRows) + uTexOffset1;

    vPosition = mvPosition.xyz;

    vNormal = normalize(uNormalMatrix * VertexNormal);

    vClampColor = clamp(VertexPosition, 0.0, 1.0);

    gl_Position = uProjectionMatrix * mvPosition;

#ifdef GL_ES
    gl_PointSize = 10.0f;
#endif
}

在C++和GLSL两方面繁琐地使用注释后,我找到了错误源头——代码中的这行:

mvPosition = uModelViewMatrix * InstanceTransform * vec4(VertexPosition, 1.0);

如果我将它注释掉,程序将能够编译,但是在没有大量与GPU相关的错误(如下所示从logcat中显示)的情况下无法执行glDraw*Instaced调用。
10-18 15:58:42.504 29196-29238/package W/Adreno-GSL: <gsl_ldd_control:408>: ioctl fd 49 code 0xc02c093d (IOCTL_KGSL_SUBMIT_COMMANDS) failed: errno 35 Resource deadlock would occur
10-18 15:58:42.504 29196-29238/package W/Adreno-GSL: <log_gpu_snapshot:323>: panel.gpuSnapshotPath is not set.not generating user snapshot
10-18 15:58:42.504 29196-29238/packageW/Adreno-GSL: <gsl_ldd_control:408>: ioctl fd 49 code 0xc02c093d (IOCTL_KGSL_SUBMIT_COMMANDS) failed: errno 35 Resource deadlock would occur
10-18 15:58:42.504 29196-29238/packageW/Adreno-GSL: <log_gpu_snapshot:323>: panel.gpuSnapshotPath is not set.not generating user snapshot
10-18 15:58:42.504 29196-29238/packageW/Adreno-GSL: <gsl_ldd_control:408>: ioctl fd 49 code 0xc02c093d (IOCTL_KGSL_SUBMIT_COMMANDS) failed: errno 35 Resource deadlock would occur
10-18 15:58:42.504 29196-29238/packageW/Adreno-GSL: <log_gpu_snapshot:323>: panel.gpuSnapshotPath is not set.not generating user snapshot
10-18 15:58:42.504 29196-29238/packageW/Adreno-GSL: <gsl_ldd_control:408>: ioctl fd 49 code 0xc02c093d (IOCTL_KGSL_SUBMIT_COMMANDS) failed: errno 35 Resource deadlock would occur
10-18 15:58:42.504 29196-29238/packageW/Adreno-GSL: <log_gpu_snapshot:323>: panel.gpuSnapshotPath is not set.not generating user snapshot
10-18 15:58:42.504 29196-29238/packageW/Adreno-GSL: <gsl_ldd_control:408>: ioctl fd 49 code 0xc02c093d (IOCTL_KGSL_SUBMIT_COMMANDS) failed: errno 35 Resource deadlock would occur
10-18 15:58:42.504 29196-29238/packageW/Adreno-GSL: <log_gpu_snapshot:323>: panel.gpuSnapshotPath is not set.not generating user snapshot
10-18 15:58:42.504 29196-29238/packageW/Adreno-ES20: <finish_current_fbo_rendering:315>: GL_OUT_OF_MEMORY

我制作了一个极简示例来测试实例渲染,使用OpenGL ES 3时也出现了同样的问题(仍然使用SDL)。

#version 300 es
precision mediump float;

// attribute data
layout (location = 0) in vec3 aVertexPosition;
layout (location = 1) in vec2 aVertexTexCoord;
layout (location = 2) in vec3 aVertexNormal;
layout (location = 3) in mat4 aInstanceTransform;

// varying data
out vec3 vPosition;
out vec2 vTexCoord;
out vec3 vNormal;

// uniform data
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform mat3 uNormalMatrix;

void main(void)
{
    vec4 mvTransform = uModelViewMatrix * aInstanceTransform * vec4(aVertexPosition, 1.0);

    vTexCoord = aVertexTexCoord;

    vPosition = mvTransform.xyz;

    vNormal = normalize(uNormalMatrix * aVertexNormal);

    gl_Position = uProjectionMatrix * mvTransform;
}

这里是我设置顶点数据的地方:

glBindBuffer(GL_ARRAY_BUFFER, mVBO_InstanceData);
glBufferData(GL_ARRAY_BUFFER, instanceData.size() * sizeof(glm::mat4), instanceData.data(), GL_STATIC_DRAW);

glEnableVertexAttribArray(3);
glVertexAttribPointer(3, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), reinterpret_cast<GLvoid*>(0));
glVertexAttribDivisor(3, 1); // increment instance data by 1 each iteration

glEnableVertexAttribArray(4);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), reinterpret_cast<GLvoid*>(sizeof(glm::vec4)));
glVertexAttribDivisor(4, 1);

glEnableVertexAttribArray(5);
glVertexAttribPointer(5, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), reinterpret_cast<GLvoid*>(2 * sizeof(glm::vec4)));
glVertexAttribDivisor(5, 1);

glEnableVertexAttribArray(6);
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), reinterpret_cast<GLvoid*>(3 * sizeof(glm::vec4)));
glVertexAttribDivisor(6, 1);
2个回答

4
您的某些“location”限定符与“300 es”着色器版本不兼容。您的顶点着色器包含以下定义:
layout (location = 0) out vec3 vPosition;
...

GLSL ES 3.00规范说明:

顶点着色器不能具有输出布局修饰符。

这个限制仅在版本3.10中解除,相应的措辞已更改为:

顶点和片段着色器允许在输出变量声明上使用位置布局修饰符。

对于uniform变量也几乎适用同样的规则,您可以使用:

layout (location = 0) uniform bool uInstanceRendering;
...

同样的,在这里,着色器版本3.00不允许在uniform上使用layout限定符:

布局限定符可以用于统一块,但不能用于非块统一声明。

同样地,此选项是在版本3.10中添加的。


啊,谢谢您检查我的代码并告诉我这个问题。我大多数情况下会在台式电脑上进行测试,然后再移植到移动设备上,所以我需要进行调整。不过,这并没有解决我的GPU实例化问题。我认为可能是我的硬件(我的手机)的问题,但我还不能确定。 - BlazePascal
如果您删除布局指令,您是否仍然会遇到链接错误?对于uniform变量,您当然必须使用glGetUniformLocation() - Reto Koradi
是的,在我添加布局限定符到 out 和 uniform 变量之前,这些错误就存在了。我只是添加它们是因为我认为这样可以解决移动端的绑定问题。 - BlazePascal
我创建了一个更小的项目,专注于执行实例渲染,但仍然存在同样的问题。我用我制作的最小示例更新了着色器代码。 - BlazePascal

1

我发现只需使用'glBindAttribLocation'而非在顶点着色器中使用layout限定符即可解决该问题。我甚至使用了与layout限定符相同的编号方案。我想知道是否可以使用4个vec4来设置实例数据?我猜测在我的移动设备上mat4会扰乱编号方案?


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