Example #1
0
bool
WebGLProgram::LinkProgram()
{
    mContext->InvalidateBufferFetching(); // we do it early in this function
    // as some of the validation below changes program state

    mLinkLog.Truncate();
    mMostRecentLinkInfo = nullptr;

    if (!mVertShader || !mVertShader->IsCompiled()) {
        mLinkLog.AssignLiteral("Must have a compiled vertex shader attached.");
        mContext->GenerateWarning("linkProgram: %s", mLinkLog.BeginReading());
        return false;
    }

    if (!mFragShader || !mFragShader->IsCompiled()) {
        mLinkLog.AssignLiteral("Must have an compiled fragment shader attached.");
        mContext->GenerateWarning("linkProgram: %s", mLinkLog.BeginReading());
        return false;
    }

    if (!mFragShader->CanLinkTo(mVertShader, &mLinkLog)) {
        mContext->GenerateWarning("linkProgram: %s", mLinkLog.BeginReading());
        return false;
    }

    gl::GLContext* gl = mContext->gl;
    gl->MakeCurrent();

    if (gl->WorkAroundDriverBugs() &&
        mContext->mIsMesa)
    {
        // Bug 777028: Mesa can't handle more than 16 samplers per program,
        // counting each array entry.
        size_t numSamplerUniforms_upperBound = mVertShader->CalcNumSamplerUniforms() +
                                               mFragShader->CalcNumSamplerUniforms();
        if (numSamplerUniforms_upperBound > 16) {
            mLinkLog.AssignLiteral("Programs with more than 16 samplers are disallowed on"
                                   " Mesa drivers to avoid crashing.");
            mContext->GenerateWarning("linkProgram: %s", mLinkLog.BeginReading());
            return false;
        }

        // Bug 1203135: Mesa crashes internally if we exceed the reported maximum attribute count.
        if (mVertShader->NumAttributes() > mContext->MaxVertexAttribs()) {
            mLinkLog.AssignLiteral("Number of attributes exceeds Mesa's reported max attribute count.");
            mContext->GenerateWarning("linkProgram: %s", mLinkLog.BeginReading());
            return false;
        }
    }

    // Bind the attrib locations.
    // This can't be done trivially, because we have to deal with mapped attrib names.
    for (auto itr = mBoundAttribLocs.begin(); itr != mBoundAttribLocs.end(); ++itr) {
        const nsCString& name = itr->first;
        GLuint index = itr->second;

        mVertShader->BindAttribLocation(mGLName, name, index);
    }

    if (!mTransformFeedbackVaryings.empty()) {
        // Bind the transform feedback varyings.
        // This can't be done trivially, because we have to deal with mapped names too.
        mVertShader->ApplyTransformFeedbackVaryings(mGLName,
                                                    mTransformFeedbackVaryings,
                                                    mTransformFeedbackBufferMode,
                                                    &mTempMappedVaryings);
    }

    if (LinkAndUpdate())
        return true;

    // Failed link.
    if (mContext->ShouldGenerateWarnings()) {
        // report shader/program infoLogs as warnings.
        // note that shader compilation errors can be deferred to linkProgram,
        // which is why we can't do anything in compileShader. In practice we could
        // report in compileShader the translation errors generated by ANGLE,
        // but it seems saner to keep a single way of obtaining shader infologs.
        if (!mLinkLog.IsEmpty()) {
            mContext->GenerateWarning("linkProgram: Failed to link, leaving the following"
                                      " log:\n%s\n",
                                      mLinkLog.BeginReading());
        }
    }

    return false;
}
Example #2
0
void
WebGLProgram::LinkProgram()
{
    const char funcName[] = "linkProgram";

    if (mNumActiveTFOs) {
        mContext->ErrorInvalidOperation("%s: Program is in-use by one or more active"
                                        " transform feedback objects.",
                                        funcName);
        return;
    }

    mContext->MakeContextCurrent();
    mContext->InvalidateBufferFetching(); // we do it early in this function
    // as some of the validation changes program state

    mLinkLog.Truncate();
    mMostRecentLinkInfo = nullptr;

    if (!ValidateForLink()) {
        mContext->GenerateWarning("%s: %s", funcName, mLinkLog.BeginReading());
        return;
    }

    // Bind the attrib locations.
    // This can't be done trivially, because we have to deal with mapped attrib names.
    for (const auto& pair : mNextLink_BoundAttribLocs) {
        const auto& name = pair.first;
        const auto& index = pair.second;

        mVertShader->BindAttribLocation(mGLName, name, index);
    }

    // Storage for transform feedback varyings before link.
    // (Work around for bug seen on nVidia drivers.)
    std::vector<std::string> scopedMappedTFVaryings;

    if (mContext->IsWebGL2()) {
        mVertShader->MapTransformFeedbackVaryings(mNextLink_TransformFeedbackVaryings,
                                                  &scopedMappedTFVaryings);

        std::vector<const char*> driverVaryings;
        driverVaryings.reserve(scopedMappedTFVaryings.size());
        for (const auto& cur : scopedMappedTFVaryings) {
            driverVaryings.push_back(cur.c_str());
        }

        mContext->gl->fTransformFeedbackVaryings(mGLName, driverVaryings.size(),
                                                 driverVaryings.data(),
                                                 mNextLink_TransformFeedbackBufferMode);
    }

    LinkAndUpdate();

    if (mMostRecentLinkInfo) {
        nsCString postLinkLog;
        if (ValidateAfterTentativeLink(&postLinkLog))
            return;

        mMostRecentLinkInfo = nullptr;
        mLinkLog = postLinkLog;
    }

    // Failed link.
    if (mContext->ShouldGenerateWarnings()) {
        // report shader/program infoLogs as warnings.
        // note that shader compilation errors can be deferred to linkProgram,
        // which is why we can't do anything in compileShader. In practice we could
        // report in compileShader the translation errors generated by ANGLE,
        // but it seems saner to keep a single way of obtaining shader infologs.
        if (!mLinkLog.IsEmpty()) {
            mContext->GenerateWarning("linkProgram: Failed to link, leaving the following"
                                      " log:\n%s\n",
                                      mLinkLog.BeginReading());
        }
    }
}