glLinkProgram崩溃,即使glCompileShader没有返回任何错误

glLinkProgram crashes even though glCompileShader does not return any error

本文关键字:返回 任何 错误 glCompileShader 崩溃 即使 glLinkProgram      更新时间:2023-10-16

我正在尝试使本机代码 https://software.intel.com/sites/default/files/managed/79/e5/OpenGL%20ES%20Tessellation.zip 在我的三星Galaxy S5上运行。我在代码中禁用了曲面细分。

我还更改了代码以使用 OpenGLS ES 3.0。

程序

运行并成功编译附加的着色器,但是当程序使用编译的着色器调用glLinkProgram时,glLinkProgram崩溃。程序在编译着色器时调用 glError,当时没有错误。

有人可以帮我如何调试吗?

//--------------------------------------------------------------------------------------
// Copyright 2014 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works of this
// software for any purpose and without fee, provided, that the above copyright notice
// and this statement appear in all copies.  Intel makes no representations about the
// suitability of this software for any purpose.  THIS SOFTWARE IS PROVIDED "AS IS."
// INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, AND ALL LIABILITY,
// INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE,
// INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  Intel does not
// assume any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//--------------------------------------------------------------------------------------
// Generated by ShaderGenerator.exe version 0.13
//--------------------------------------------------------------------------------------
// Fog color in both shaders
// Skybox
const float TessellationHeight = 5500.0; // Height of a 1.0 in the height map (height map * TessellationHeight)
const int NumLights = 2;
const vec3 LightDirections[NumLights] = vec3[]( vec3(-1.0, -1.0,  -1.0),
                                                vec3(0.5, -1.0,  1.0) );
const vec3 LightColors[NumLights] = vec3[]( vec3(0.362, 0.526, 0.575),
                                            vec3(0.630, 0.914, 1.0));
// -------------------------------------
layout (std140, row_major) uniform cbPerModelValues
{
   mat4 World;
   mat4 NormalMatrix;
   mat4 WorldViewProjection;
   mat4 InverseWorld;
   mat4 LightWorldViewProjection;
   vec4 BoundingBoxCenterWorldSpace;
   vec4 BoundingBoxHalfWorldSpace;
   vec4 BoundingBoxCenterObjectSpace;
   vec4 BoundingBoxHalfObjectSpace;
};
// -------------------------------------
layout (std140, row_major) uniform cbPerFrameValues
{
   mat4  View;
   mat4  InverseView;
   mat4  Projection;
   mat4  ViewProjection;
   vec4  AmbientColor;
   vec4  LightColor;
   vec4  LightDirection;
   vec4  EyePosition;
   vec4  MaxTessellation;
};
// -------------------------------------
uniform sampler2D Texture0;
uniform sampler2D Texture1;
uniform sampler2D Texture2;
// -------------------------------------
#ifdef GLSL_VERTEX_SHADER
precision highp float;
#define POSITION  0
#define NORMAL    1
#define BINORMAL  2
#define TANGENT   3
#define COLOR   4
#define TEXCOORD0 5
// -------------------------------------
layout (location = POSITION)  in vec3 Position; // Projected position
layout (location = NORMAL)    in vec3 Normal;
layout (location = TANGENT)   in vec3 Tangent;
layout (location = BINORMAL)  in vec3 Binormal;
layout (location = TEXCOORD0) in vec2 UV0;
// -------------------------------------
out vec4 outPosition;
out vec3 outNormal;
out vec3 outTangent;
out vec3 outBinormal;
out vec2 outUV0;
out vec3 outWorldPosition; // Object space position 
#endif //GLSL_VERTEX_SHADER
#ifdef GLSL_FRAGMENT_SHADER
precision highp float;
// -------------------------------------
in vec4 outPosition;
in vec3 outNormal;
in vec3 outTangent;
in vec3 outBinormal;
in vec2 outUV0;
in vec3 outWorldPosition; // Object space position 
in vec3 outTriDistance;
// -------------------------------------
vec4 DIFFUSETMP( )
{
    return texture(Texture0,(((outUV0)) *(20.0)) );
}
// -------------------------------------
vec4 NORMAL( )
{
    return texture(Texture1,(((outUV0)) *(1.0)) ) * 2.0 - 1.0;
}
// -------------------------------------
vec4 AOMAP( )
{
    return texture(Texture2,(((outUV0)) *(1.0)) );
}
// -------------------------------------
vec4 DIFFUSE( )
{
    vec4 diffuse = DIFFUSETMP() * AOMAP();
#ifdef OPENGL_ES
    diffuse.rgb = pow(diffuse.rgb, vec3(2.2));
#endif
    return diffuse*vec4(2.0);
}
// -------------------------------------
vec4 AMBIENT( )
{
    return DIFFUSE();
}
// -------------------------------------
#endif //GLSL_FRAGMENT_SHADER
#ifdef GLSL_VERTEX_SHADER
// -------------------------------------
void main( )
{
    outPosition = vec4( Position, 1.0);
    outWorldPosition = (outPosition * World).xyz;
    outNormal   = Normal   * mat3(World);
    outTangent  = Tangent  * mat3(World);
    outBinormal = Binormal * mat3(World);
    outUV0 = UV0;
}
#endif //GLSL_VERTEX_SHADER
#ifdef  GLSL_TESS_CONTROL_SHADER
precision highp float;
#ifdef OPENGL_ES
#extension GL_INTEL_tessellation:require
#endif
layout(vertices = 3) out;
in vec4 outPosition[];
in vec3 outNormal[];
in vec3 outTangent[];
in vec3 outBinormal[];
in vec2 outUV0[];
in vec3 outWorldPosition[];
out  vec4  tcPosition[3];
out  vec3  tcNormal[3];
out  vec3  tcTangent[3];
out  vec3  tcBinormal[3];
out  vec2  tcUV0[3];
out  vec3  tcWorldPosition[3];
float level(float d)
{
    d = d/55000.0; // d = [0..1]
    float s = clamp(1.0*(d), 0.0, 1.0);
    return mix(MaxTessellation.x,1.0, s);
}
void main()
{
    tcPosition[gl_InvocationID] = outPosition[gl_InvocationID];
    tcWorldPosition[gl_InvocationID] = outWorldPosition[gl_InvocationID];
    tcNormal[gl_InvocationID] = outNormal[gl_InvocationID];
    tcBinormal[gl_InvocationID] = outBinormal[gl_InvocationID];
    tcTangent[gl_InvocationID] = outTangent[gl_InvocationID];
    tcUV0[gl_InvocationID] = outUV0[gl_InvocationID];
    if(gl_InvocationID == 0) {
        vec3 CamPos = EyePosition.xyz;
        float d0 = distance(CamPos, outWorldPosition[0]);
        float d1 = distance(CamPos, outWorldPosition[1]);
        float d2 = distance(CamPos, outWorldPosition[2]);
        gl_TessLevelOuter[2] = level(mix(d0,d1,0.5));
        gl_TessLevelOuter[0] = level(mix(d1,d2,0.5));
        gl_TessLevelOuter[1] = level(mix(d2,d0,0.5));
        float inner = max(max(gl_TessLevelOuter[0], gl_TessLevelOuter[1]),gl_TessLevelOuter[2]);
        gl_TessLevelInner[0] = inner;
    }
}
#endif  //GLSL_TESS_CONTROL_SHADER
#ifdef GLSL_TESS_EVALUATION_SHADER
precision highp float;
#ifdef OPENGL_ES
#extension GL_INTEL_tessellation:require
#endif // OPENGL_ES
layout(triangles,fractional_odd_spacing,ccw) in;
in  vec4  tcPosition[];
in  vec3  tcNormal[];
in  vec3  tcTangent[];
in  vec3  tcBinormal[];
in  vec2  tcUV0[];
in  vec3  tcWorldPosition[];
out vec4 outPosition;
out vec3 outNormal;
out vec3 outTangent;
out vec3 outBinormal;
out vec2 outUV0;
out vec3 outWorldPosition;
vec2 interpolate(vec2 a, vec2 b, vec2 c)
{
    vec2 p0 = vec2(gl_TessCoord.x) * a;
    vec2 p1 = vec2(gl_TessCoord.y) * b;
    vec2 p2 = vec2(gl_TessCoord.z) * c;
    return p0+p1+p2;
}
vec3 interpolate(vec3 a, vec3 b, vec3 c)
{
    vec3 p0 = vec3(gl_TessCoord.x) * a;
    vec3 p1 = vec3(gl_TessCoord.y) * b;
    vec3 p2 = vec3(gl_TessCoord.z) * c;
    return p0+p1+p2;
}
vec4 interpolate(vec4 a, vec4 b, vec4 c)
{
    vec4 p0 = vec4(gl_TessCoord.x) * a;
    vec4 p1 = vec4(gl_TessCoord.y) * b;
    vec4 p2 = vec4(gl_TessCoord.z) * c;
    return p0+p1+p2;
}
void main()
{
    outPosition = interpolate(tcPosition[0],tcPosition[1],tcPosition[2]);
    outUV0 = interpolate(tcUV0[0],tcUV0[1],tcUV0[2]);
    outWorldPosition = interpolate(tcWorldPosition[0],tcWorldPosition[1],tcWorldPosition[2]);
    outNormal = interpolate(tcNormal[0],tcNormal[1],tcNormal[2]);
    outTangent = interpolate(tcTangent[0],tcTangent[1],tcTangent[2]);
    outBinormal = interpolate(tcBinormal[0],tcBinormal[1],tcBinormal[2]);
    float y = texture(Texture1,(outUV0)).a * TessellationHeight;
    outPosition.y = y;
    outPosition   = outPosition * WorldViewProjection;
    gl_Position = outPosition;
}
#endif  //GLSL_TESS_EVALUATION_SHADER
#ifdef GLSL_FRAGMENT_SHADER
out vec4 fragColor;// -------------------------------------
void main( )
{
    vec4 result = vec4(0.0,0.0,0.0,1.0);
    vec3 normal   = outNormal;
    vec3 tangent  = outTangent;
    vec3 binormal = outBinormal;
    mat3 tangentToWorld = mat3(tangent, binormal, normal);
    normal = normalize( tangentToWorld * NORMAL().bgr );
    float  shadowAmount = 1.0;
    // Ambient-related computation
    vec3 ambient = AmbientColor.rgb * AMBIENT().rgb;
    result.xyz +=  ambient;
    vec3 lightDirection = -LightDirection.xyz;
    // Diffuse-related computation
    vec3 albedo = DIFFUSE().rgb;
    for(int ii=0; ii<NumLights; ++ii) {
        lightDirection = -LightDirections[ii];
        float  nDotL = max( 0.0,dot( normal, lightDirection ) );
        vec3 diffuse = LightColors[ii] * nDotL * shadowAmount  * albedo;
        result.xyz += diffuse * (1.0/float(NumLights));
    }
    fragColor =  result;
    const vec4 FogColor = vec4(0.211,0.223,0.226,1.0);
    const float MinFogDistance = 5000.0;
    const float MaxFogDistance = 75000.0;
    float dist = distance(outWorldPosition, EyePosition.xyz);
    float fog_factor = clamp((MaxFogDistance - dist)/(MaxFogDistance - MinFogDistance),0.0,1.0);
    fragColor =  mix(fragColor,FogColor,1.0-fog_factor);
    #ifdef OPENGL_ES
    fragColor.rgb = pow(fragColor.rgb, vec3(0.454545454545));
    #endif
}
#endif //GLSL_FRAGMENT_SHADER

问题可能来自片段着色器中数组的动态索引,并非所有实现都支持该索引。(见 https://www.khronos.org/files/opengles_shading_language.pdf 第103页。请注意,在顶点着色器中是可以的...

在您的代码中:

for(int ii=0; ii<NumLights; ++ii) {
    lightDirection = -LightDirections[ii];
    float  nDotL = max( 0.0,dot( normal, lightDirection ) );
    vec3 diffuse = LightColors[ii] * nDotL * shadowAmount  * albedo;
    result.xyz += diffuse * (1.0/float(NumLights));
}

尝试使用常量索引进行调试。将所有 xxx[ii] 替换为 xxx[0]。如果它以这种方式工作,那么您可能会面临这种动态索引限制。

绕过此问题的一种黑客方法:使用 float for loops 并在循环体中创建一个 int var:

float NumLights_f = float(NumLights);
for(float ii_f=0.; ii_f<NumLights_f; ++ii_f) {
    int ii = int(ii_f);
    lightDirection = -LightDirections[ii];
    float  nDotL = max( 0.0,dot( normal, lightDirection ) );
    vec3 diffuse = LightColors[ii] * nDotL * shadowAmount  * albedo;
    result.xyz += diffuse * (1.0/float(NumLights));
}

出于某种原因,它解决了我类似的错误。我不是glsl-es大师,我很好奇为什么会这样工作。而且它可能以性能损失为代价......是因为循环展开吗?int(ii_f) 就像展开后的常数?