gl::LinkResult ProgramGL::load(const gl::Context *context, gl::InfoLog &infoLog, gl::BinaryInputStream *stream) { preLink(); // Read the binary format, size and blob GLenum binaryFormat = stream->readInt<GLenum>(); GLint binaryLength = stream->readInt<GLint>(); const uint8_t *binary = stream->data() + stream->offset(); stream->skip(binaryLength); // Load the binary mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength); // Verify that the program linked if (!checkLinkStatus(infoLog)) { return false; } postLink(); reapplyUBOBindingsIfNeeded(context); return true; }
/* Shader Program Helper This function will attempt to create a shader program that has the Vertex and Fragement shader code that you pass in. If successfully compiled and linked to the program, the unique program ID given by OpenGL will be returned. This ID will be >1 if successful, or 0 (an invalid ID) if any of the above fails. Most of the Code below is for checking if the shaders compiled and linked correctly. */ GLuint CreateShaderProgram(const std::string &vsSource, const std::string &fsSource) { GLuint programID = glCreateProgram(); GLuint vsID = glCreateShader(GL_VERTEX_SHADER); GLuint fsID = glCreateShader(GL_FRAGMENT_SHADER); if (programID == 0 || vsID == 0 || fsID == 0) { // Clean up others that were created glDeleteProgram(programID); glDeleteShader(vsID); glDeleteShader(fsID); std::cerr << "Cannot create Shaders or Program" << std::endl; return 0; // invalid ID } // glShaderSource() expects char**, so these are helper variables const char *vsSourceArray = vsSource.c_str(); const char *fsSourceArray = fsSource.c_str(); // https://www.opengl.org/sdk/docs/man4/xhtml/glShaderSource.xml glShaderSource(vsID, 1, &vsSourceArray, NULL); glShaderSource(fsID, 1, &fsSourceArray, NULL); // Compile the Shader Sources, check for errors glCompileShader(vsID); glCompileShader(fsID); if (!checkCompileStatus(vsID) || !checkCompileStatus(fsID)) { // Clean up others that were created glDeleteProgram(programID); glDeleteShader(vsID); glDeleteShader(fsID); std::cerr << "Cannot create Shaders or Program" << std::endl; return 0; // invalid ID } glAttachShader(programID, vsID); glAttachShader(programID, fsID); glLinkProgram(programID); if (!checkLinkStatus(programID)) { // Clean up others that were created glDeleteProgram(programID); glDeleteShader(vsID); glDeleteShader(fsID); std::cerr << "Cannot create Shaders or Program" << std::endl; return 0; // invalid ID } return programID; }
void Shader::createProgram() { m_Program = glCreateProgram(); glAttachShader(m_Program, m_VertexShader); glAttachShader(m_Program, m_FragmentShader); glLinkProgram(m_Program); checkLinkStatus(); }
GrGLProgram* GrGLProgramBuilder::finalize() { // verify we can get a program id GrGLuint programID; GL_CALL_RET(programID, CreateProgram()); if (0 == programID) { this->cleanupFragmentProcessors(); return nullptr; } // compile shaders and bind attributes / uniforms SkTDArray<GrGLuint> shadersToDelete; fVS.finalize(GrGLSLUniformHandler::kVertex_Visibility); if (!this->compileAndAttachShaders(fVS, programID, GR_GL_VERTEX_SHADER, &shadersToDelete)) { this->cleanupProgram(programID, shadersToDelete); return nullptr; } // NVPR actually requires a vertex shader to compile bool useNvpr = primitiveProcessor().isPathRendering(); if (!useNvpr) { const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); int vaCount = primProc.numAttribs(); for (int i = 0; i < vaCount; i++) { GL_CALL(BindAttribLocation(programID, i, primProc.getAttrib(i).fName)); } } fFS.finalize(GrGLSLUniformHandler::kFragment_Visibility); if (!this->compileAndAttachShaders(fFS, programID, GR_GL_FRAGMENT_SHADER, &shadersToDelete)) { this->cleanupProgram(programID, shadersToDelete); return nullptr; } this->bindProgramResourceLocations(programID); GL_CALL(LinkProgram(programID)); // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = kChromium_GrGLDriver != fGpu->ctxInfo().driver(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { checkLinkStatus(programID); } this->resolveProgramResourceLocations(programID); this->cleanupShaders(shadersToDelete); return this->createProgram(programID); }
GrGLProgram* GrGLProgramBuilder::finalize() { // verify we can get a program id GrGLuint programID; GL_CALL_RET(programID, CreateProgram()); if (0 == programID) { return NULL; } // compile shaders and bind attributes / uniforms SkTDArray<GrGLuint> shadersToDelete; if (!fVS.compileAndAttachShaders(programID, &shadersToDelete)) { this->cleanupProgram(programID, shadersToDelete); return NULL; } // NVPR actually requires a vertex shader to compile bool useNvpr = primitiveProcessor().isPathRendering(); if (!useNvpr) { fVS.bindVertexAttributes(programID); } if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) { this->cleanupProgram(programID, shadersToDelete); return NULL; } bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL; if (usingBindUniform) { this->bindUniformLocations(programID); } fFS.bindFragmentShaderLocations(programID); GL_CALL(LinkProgram(programID)); // Calling GetProgramiv is expensive in Chromium. Assume success in release builds. bool checkLinked = !fGpu->ctxInfo().isChromium(); #ifdef SK_DEBUG checkLinked = true; #endif if (checkLinked) { checkLinkStatus(programID); } if (!usingBindUniform) { this->resolveUniformLocations(programID); } this->cleanupShaders(shadersToDelete); return this->createProgram(programID); }
GLuint Shader::ComputeByGPU(const char* computeShaderName) { const char *computeShaderSource = loadComputeFile(computeShaderName); GLuint computeShaderID = glCreateShader(GL_COMPUTE_SHADER); glShaderSource(computeShaderID, 1, &computeShaderSource, NULL); glCompileShader(computeShaderID); checkCompileStatus(computeShaderID, computeShaderName); GLuint program = glCreateProgram(); glAttachShader(program, computeShaderID); glLinkProgram(program); checkLinkStatus(program, computeShaderName); return program; }
void StereoBlitProgram::initializeShaders() { glow::Shader* vertShader = glowutils::createShaderFromFile(GL_VERTEX_SHADER, "data/shader/blit/stereoblit.vert"); glow::Shader* fragShader = glowutils::createShaderFromFile(GL_FRAGMENT_SHADER, "data/shader/blit/stereoblit.frag"); bindAttributeLocation(ScreenQuad::VERTEX_ATTRIBUTE_LOCATION, "v_vertex"); attach(vertShader, fragShader); link(); assert(checkLinkStatus()); bindFragDataLocation(0, "fragColor"); getUniform<GLint>("texture")->set(BlitProgram::TEXTURE_LOCATION); }
void Program::link() const { m_linked = false; if (!binaryImplementation().updateProgramLinkSource(this)) return; glLinkProgram(id()); m_linked = checkLinkStatus(); m_dirty = false; updateUniforms(); updateUniformBlockBindings(); }
LinkResult ProgramGL::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) { preLink(); // Read the binary format, size and blob GLenum binaryFormat = stream->readInt<GLenum>(); GLint binaryLength = stream->readInt<GLint>(); const uint8_t *binary = stream->data() + stream->offset(); stream->skip(binaryLength); // Load the binary mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength); // Verify that the program linked if (!checkLinkStatus(infoLog)) { return LinkResult(false, gl::Error(GL_NO_ERROR)); } postLink(); return LinkResult(true, gl::Error(GL_NO_ERROR)); }
LinkResult ProgramGL::link(const gl::ContextState &data, gl::InfoLog &infoLog) { preLink(); // Set the transform feedback state std::vector<const GLchar *> transformFeedbackVaryings; for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames()) { transformFeedbackVaryings.push_back(tfVarying.c_str()); } if (transformFeedbackVaryings.empty()) { if (mFunctions->transformFeedbackVaryings) { mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr, mState.getTransformFeedbackBufferMode()); } } else { ASSERT(mFunctions->transformFeedbackVaryings); mFunctions->transformFeedbackVaryings( mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()), &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode()); } const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader()); const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader()); // Attach the shaders mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID()); mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID()); // Bind attribute locations to match the GL layer. for (const sh::Attribute &attribute : mState.getAttributes()) { if (!attribute.staticUse) { continue; } mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str()); } // Link and verify mFunctions->linkProgram(mProgramID); // Detach the shaders mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID()); mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID()); // Verify the link if (!checkLinkStatus(infoLog)) { return LinkResult(false, gl::Error(GL_NO_ERROR)); } if (mWorkarounds.alwaysCallUseProgramAfterLink) { mStateManager->forceUseProgram(mProgramID); } postLink(); return LinkResult(true, gl::Error(GL_NO_ERROR)); }
gl::LinkResult ProgramGL::link(const gl::Context *context, const gl::ProgramLinkedResources &resources, gl::InfoLog &infoLog) { preLink(); if (mState.getAttachedComputeShader()) { const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader()); mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID()); // Link and verify mFunctions->linkProgram(mProgramID); // Detach the shaders mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID()); } else { // Set the transform feedback state std::vector<std::string> transformFeedbackVaryingMappedNames; for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames()) { std::string tfVaryingMappedName = mState.getAttachedVertexShader()->getTransformFeedbackVaryingMappedName(tfVarying, context); transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName); } if (transformFeedbackVaryingMappedNames.empty()) { if (mFunctions->transformFeedbackVaryings) { mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr, mState.getTransformFeedbackBufferMode()); } } else { ASSERT(mFunctions->transformFeedbackVaryings); std::vector<const GLchar *> transformFeedbackVaryings; for (const auto &varying : transformFeedbackVaryingMappedNames) { transformFeedbackVaryings.push_back(varying.c_str()); } mFunctions->transformFeedbackVaryings( mProgramID, static_cast<GLsizei>(transformFeedbackVaryingMappedNames.size()), &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode()); } const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader()); const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader()); const ShaderGL *geometryShaderGL = rx::SafeGetImplAs<ShaderGL, gl::Shader>(mState.getAttachedGeometryShader()); // Attach the shaders mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID()); mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID()); if (geometryShaderGL) { mFunctions->attachShader(mProgramID, geometryShaderGL->getShaderID()); } // Bind attribute locations to match the GL layer. for (const sh::Attribute &attribute : mState.getAttributes()) { if (!attribute.staticUse || attribute.isBuiltIn()) { continue; } mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.mappedName.c_str()); } // Link and verify mFunctions->linkProgram(mProgramID); // Detach the shaders mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID()); mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID()); if (geometryShaderGL) { mFunctions->detachShader(mProgramID, geometryShaderGL->getShaderID()); } } // Verify the link if (!checkLinkStatus(infoLog)) { return false; } if (mWorkarounds.alwaysCallUseProgramAfterLink) { mStateManager->forceUseProgram(mProgramID); } linkResources(resources); postLink(); return true; }