使用glGetProgramiv时“检测到堆栈损坏”

时间:2013-04-19 12:43:25

标签: android opengl-es android-ndk opengl-es-2.0

我正在编写原生的Android OpenGLES 2代码。

加载着色器时(着色器加载代码非常类似于NDK示例“hello-gl2”),我的程序没有链接(着色器自身编译没有错误)。

此代码:

GLint linkStatus = GL_FALSE;
GLCALL(glGetProgramiv(programId, GL_LINK_STATUS, &linkStatus));
if (linkStatus != GL_TRUE) {

返回false,所以我继续调用

LOGE("Could not link program, gathering log...");
GLint bufLength = 0;
GLCALL(glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &bufLength));

永远不会返回并崩溃我的应用。 LogCat显示为红色:

04-19 15:24:55.369: A/<unknown>(29293): stack corruption detected: aborted
04-19 15:24:55.379: I/ActivityManager(101): Process x.x.x (pid 29293) has died.

我可以假设日志检索功能中出现了问题,因为我传递了一个普通的GLint引用,这与Google示例中的代码相同......

我已尝试跳过查询长度并直接查询日志,但它会生成相同的错误。

我可以在这里发布整个GLSL着色器代码,但让日志功能正常运行会更有价值,所以我可以自己调试......

完整着色器加载代码:

GLuint OpenGLESHelper::loadShader(GLenum shaderType, const char* pSource) {
    GLuint shader;
    GLCALL(shader = glCreateShader(shaderType));
    if (shader) {
        GLCALL(glShaderSource(shader, 1, &pSource, NULL));
        GLCALL(glCompileShader(shader));
        GLint compiled = 0;
        GLCALL(glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled));
        if (!compiled) {
            LOGE("Could not compile shader, retrieving log...");
            GLint infoLen = 0;
            GLCALL(glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen));

            // Workaround
            if (infoLen == 0)
                infoLen = 4096;

            if (infoLen) {
                char* buf = (char*) malloc(infoLen);
                if (buf) {
                    GLCALL(glGetShaderInfoLog(shader, infoLen, NULL, buf));
                    LOGE("Could not compile shader %d:\n%s\n", shaderType, buf);
                    free(buf);
                }
                GLCALL(glDeleteShader(shader));
                shader = 0;
            }
        }
    }
    return shader;
}

ShaderProgram* OpenGLESHelper::createProgram(const char* pVertexSource,
        const char* pFragmentSource) {
    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
    if (!vertexShader) {
        return 0;
    }

    GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
    if (!pixelShader) {
        return 0;
    }

    GLuint programId;
    GLCALL(programId = glCreateProgram());
    if (programId) {
        GLCALL(glAttachShader(programId, vertexShader));
        GLCALL(glAttachShader(programId, pixelShader));
        GLCALL(glLinkProgram(programId));
        GLint linkStatus = GL_FALSE;
        GLCALL(glGetProgramiv(programId, GL_LINK_STATUS, &linkStatus));
        if (linkStatus != GL_TRUE) {
            LOGE("Could not link program, gathering log...");
            GLint bufLength = 0;
            GLCALL(glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &bufLength));

            if (bufLength) {
                char* buf = (char*) malloc(bufLength);
                if (buf) {
                    GLCALL(glGetProgramInfoLog(programId, bufLength, NULL, buf));
                    LOGE("Could not link program:\n%s\n", buf);
                    free(buf);
                }
            }
            GLCALL(glDeleteProgram(programId));
            programId = 0;
        }
    }

    ShaderProgram* program = new ShaderProgram;
    program->mProgramHandle = programId;

    GLCALL(
            program->mPositionAttributeHandle = glGetAttribLocation(programId, "vPosition"));
    GLCALL(
            program->mTexCoordAttributeHandle = glGetAttribLocation(programId, "a_TexCoordinate"));
    GLCALL(
            program->mTextureUniformHandle = glGetUniformLocation(programId, "rubyTexture"));
    GLCALL(
            program->mTextureSizeUniformHandle = glGetUniformLocation(programId, "rubyTextureSize"));

    return program;
}

使用过的预处理器宏:

  #ifdef ANDROID_DEBUG_GL_CALLS
#define GLCALLLOG(x, before) \
    do { \
        if (before) \
            LOGD("calling '%s' (%s:%d)", x, __FILE__, __LINE__); \
        else \
            LOGD("returned from '%s' (%s:%d)", x, __FILE__, __LINE__); \
    } while (false)
#else
#define GLCALLLOG(x, before) do {  } while (false)
#endif

#define GLCALL(x) \
    do { \
        GLCALLLOG(#x, true); \
        (x); \
        GLCALLLOG(#x, false); \
        checkGlError(#x, __FILE__, __LINE__); \
    } while (false)

#define GLTHREADCHECK \
    do { \
        assert(pthread_self() == _main_thread); \
    } while (false)

#else
#define GLCALL(x) do { (x); } while (false)
#define GLTHREADCHECK do {  } while (false)
#endif

更新

有一个特殊的着色器对产生了这种奇怪的行为。

我找到了其他2个正确编译的着色器对,但是在链接时,生成一个只有“链接失败”的日志。 - 除此之外没有任何信息。

然后我在带有GPU仿真的Jelly Bean AVD上尝试了这两个着色器对(完全相同的APK),它们完美地连接在一起,我的游戏在那里工作。

非常非常非常不一致的东西...... 我的HTC Desire有问题吗? 什么是检查我的着色器是否良好的好参考设备?

0 个答案:

没有答案