bool GLProgram::link() { CCASSERT(_program != 0, "Cannot link invalid program"); #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) if(!_hasShaderCompiler) { // precompiled shader program is already linked //bindPredefinedVertexAttribs(); parseVertexAttribs(); parseUniforms(); return true; } #endif GLint status = GL_TRUE; bindPredefinedVertexAttribs(); glLinkProgram(_program); parseVertexAttribs(); parseUniforms(); if (_vertShader) { glDeleteShader(_vertShader); } if (_fragShader) { glDeleteShader(_fragShader); } _vertShader = _fragShader = 0; #if DEBUG || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) glGetProgramiv(_program, GL_LINK_STATUS, &status); if (status == GL_FALSE) { CCLOG("cocos2d: ERROR: Failed to link program: %i", _program); GL::deleteProgram(_program); _program = 0; } #endif #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || defined(WP8_SHADER_COMPILER) if (status == GL_TRUE) { CCPrecompiledShaders::getInstance()->addProgram(_program, _shaderId); } #endif return (status == GL_TRUE); }
void App::compileShader(const char *shader_src, bool recompile) { // clean up error log if (compile_error_log) { delete [] compile_error_log; compile_error_log = nullptr; } bool is_compiled, is_linked; // compile newly loaded shader is_compiled = shader.compileAndAttach(GL_FRAGMENT_SHADER, shader_src); if (!is_compiled) { compile_error_log = shader.getShaderCompileErrorLog(GL_FRAGMENT_SHADER); goto shader_compilation_failed; } is_linked = shader.link(); if (!is_linked) { compile_error_log = shader.getLinkErrorLog(); goto shader_compilation_failed; } if (recompile) { // try to migrate uniform data ShaderUniform *old_uniforms = uniforms; uniforms = nullptr; u8 *old_uniform_data = uniform_data; uniform_data = nullptr; int old_uniform_count = uniform_count; parseUniforms(); if (old_uniform_count) { transferUniformData(old_uniforms, old_uniform_count); assert(old_uniforms); delete [] old_uniforms; assert(old_uniform_data); delete [] old_uniform_data; } } else { parseUniforms(); // load uniform values from disk readUniformData(); } return; // success shader_compilation_failed: assert(compile_error_log); // logically eq. to shader did not compile // use error shader shader.compileAndAttach(GL_FRAGMENT_SHADER, error_frag_src); shader.link(); shader.use(); glUniform1f(shader.getUniformLocation("u_error_time"), u_time); }
void GLProgram::linkProgram() { glLinkProgram(m_programObject); GLint linked = 0; glGetProgramiv(m_programObject, GL_LINK_STATUS, &linked); if (linked) { parseUniforms(); return; } CHECK_GL_ERROR; GLint length = 0; glGetProgramiv(m_programObject, GL_INFO_LOG_LENGTH, &length); if (length > 1) { GLchar* message = new GLchar(sizeof(GLchar) * length); glGetProgramInfoLog(m_programObject, length, NULL, message); LOGE("Shader linking error output: %s", message); delete message; } }
bool GLProgram::link() { CCASSERT(_program != 0, "Cannot link invalid program"); GLint status = GL_TRUE; bindPredefinedVertexAttribs(); glLinkProgram(_program); // Calling glGetProgramiv(...GL_LINK_STATUS...) will force linking of the program at this moment. // Otherwise, they might be linked when they are used for the first time. (I guess this depends on the driver implementation) // So it might slow down the "booting" process on certain devices. But, on the other hand it is important to know if the shader // linked successfully. Some shaders might be downloaded in runtime so, release version should have this check. // For more info, see Github issue #16231 glGetProgramiv(_program, GL_LINK_STATUS, &status); if (status == GL_FALSE) { CCLOG("cocos2d: ERROR: Failed to link program: %i", _program); GL::deleteProgram(_program); _program = 0; } else { parseVertexAttribs(); parseUniforms(); clearShader(); } return (status == GL_TRUE); }
bool GLProgram::link() { CCASSERT(_program != 0, "Cannot link invalid program"); GLint status = GL_TRUE; bindPredefinedVertexAttribs(); glLinkProgram(_program); parseVertexAttribs(); parseUniforms(); clearShader(); #if DEBUG || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) glGetProgramiv(_program, GL_LINK_STATUS, &status); if (status == GL_FALSE) { CCLOG("cocos2d: ERROR: Failed to link program: %i", _program); GL::deleteProgram(_program); _program = 0; } #endif return (status == GL_TRUE); }
void App::loadShader(const char *frag_file_path, bool initial) { // clean up if (compile_error_log) { delete [] compile_error_log; compile_error_log = nullptr; } // compile newly loaded shader bool is_compiled = shader.readCompileAndAttach(GL_FRAGMENT_SHADER, frag_file_path); if (!is_compiled) { compile_error_log = shader.getShaderCompileErrorLog(GL_FRAGMENT_SHADER); assert(compile_error_log); // should be logically eq. to !is_compiled // use error shader shader.compileAndAttach(GL_FRAGMENT_SHADER, error_frag_src); shader.link(); shader.use(); glUniform1f(shader.getUniformLocation("u_error_time"), u_time); return; // keep old uniforms } shader.link(); if (initial) { parseUniforms(); // load uniform values from disk readUniformData(); } else { ShaderUniform *old_uniforms = uniforms; uniforms = nullptr; u8 *old_uniform_data = uniform_data; uniform_data = nullptr; int old_uniform_count = uniform_count; parseUniforms(); if (old_uniform_count) { transferUniformData(old_uniforms, old_uniform_count); assert(old_uniforms); delete [] old_uniforms; assert(old_uniform_data); delete [] old_uniform_data; } } }