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; }
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; }