Esempio n. 1
0
bool Varying::isSameVaryingAtLinkTime(const Varying &other) const
{
    return isSameVaryingAtLinkTime(other, 100);
}
bool
ShaderValidator::CanLinkTo(const ShaderValidator* prev, nsCString* const out_log) const
{
    if (!prev) {
        nsPrintfCString error("Passed in NULL prev ShaderValidator.");
        *out_log = error;
        return false;
    }

    {
        const std::vector<sh::Uniform>* vertPtr = ShGetUniforms(prev->mHandle);
        const std::vector<sh::Uniform>* fragPtr = ShGetUniforms(mHandle);
        if (!vertPtr || !fragPtr) {
            nsPrintfCString error("Could not create uniform list.");
            *out_log = error;
            return false;
        }

        for (auto itrFrag = fragPtr->begin(); itrFrag != fragPtr->end(); ++itrFrag) {
            for (auto itrVert = vertPtr->begin(); itrVert != vertPtr->end(); ++itrVert) {
                if (itrVert->name != itrFrag->name)
                    continue;

                if (!itrVert->isSameUniformAtLinkTime(*itrFrag)) {
                    nsPrintfCString error("Uniform `%s`is not linkable between"
                                          " attached shaders.",
                                          itrFrag->name.c_str());
                    *out_log = error;
                    return false;
                }

                break;
            }
        }
    }
    {
        const std::vector<sh::Varying>* vertPtr = ShGetVaryings(prev->mHandle);
        const std::vector<sh::Varying>* fragPtr = ShGetVaryings(mHandle);
        if (!vertPtr || !fragPtr) {
            nsPrintfCString error("Could not create varying list.");
            *out_log = error;
            return false;
        }

        nsTArray<ShVariableInfo> staticUseVaryingList;

        for (auto itrFrag = fragPtr->begin(); itrFrag != fragPtr->end(); ++itrFrag) {
            const ShVariableInfo varInfo = { itrFrag->type,
                                             (int)itrFrag->elementCount() };

            static const char prefix[] = "gl_";
            if (StartsWith(itrFrag->name, prefix)) {
                if (itrFrag->staticUse)
                    staticUseVaryingList.AppendElement(varInfo);

                continue;
            }

            bool definedInVertShader = false;
            bool staticVertUse = false;

            for (auto itrVert = vertPtr->begin(); itrVert != vertPtr->end(); ++itrVert) {
                if (itrVert->name != itrFrag->name)
                    continue;

                if (!itrVert->isSameVaryingAtLinkTime(*itrFrag)) {
                    nsPrintfCString error("Varying `%s`is not linkable between"
                                          " attached shaders.",
                                          itrFrag->name.c_str());
                    *out_log = error;
                    return false;
                }

                definedInVertShader = true;
                staticVertUse = itrVert->staticUse;
                break;
            }

            if (!definedInVertShader && itrFrag->staticUse) {
                nsPrintfCString error("Varying `%s` has static-use in the frag"
                                      " shader, but is undeclared in the vert"
                                      " shader.", itrFrag->name.c_str());
                *out_log = error;
                return false;
            }

            if (staticVertUse && itrFrag->staticUse)
                staticUseVaryingList.AppendElement(varInfo);
        }

        if (!ShCheckVariablesWithinPackingLimits(mMaxVaryingVectors,
                                                 staticUseVaryingList.Elements(),
                                                 staticUseVaryingList.Length()))
        {
            *out_log = "Statically used varyings do not fit within packing limits. (see"
                       " GLSL ES Specification 1.0.17, p111)";
            return false;
        }
    }

    return true;
}