Exemple #1
0
void ShaderD3D::parseVaryings(ShHandle compiler)
{
    if (!mTranslatedSource.empty())
    {
        const std::vector<sh::Varying> *varyings = ShGetVaryings(compiler);
        ASSERT(varyings);

        mVaryings = *varyings;

        for (size_t varyingIndex = 0; varyingIndex < varyings->size(); varyingIndex++)
        {
            mPackedVaryings.push_back(PackedVarying(mVaryings[varyingIndex]));
        }

        mUsesMultipleRenderTargets   = mTranslatedSource.find("GL_USES_MRT")                          != std::string::npos;
        mUsesFragColor               = mTranslatedSource.find("GL_USES_FRAG_COLOR")                   != std::string::npos;
        mUsesFragData                = mTranslatedSource.find("GL_USES_FRAG_DATA")                    != std::string::npos;
        mUsesFragCoord               = mTranslatedSource.find("GL_USES_FRAG_COORD")                   != std::string::npos;
        mUsesFrontFacing             = mTranslatedSource.find("GL_USES_FRONT_FACING")                 != std::string::npos;
        mUsesPointSize               = mTranslatedSource.find("GL_USES_POINT_SIZE")                   != std::string::npos;
        mUsesPointCoord              = mTranslatedSource.find("GL_USES_POINT_COORD")                  != std::string::npos;
        mUsesDepthRange              = mTranslatedSource.find("GL_USES_DEPTH_RANGE")                  != std::string::npos;
        mUsesFragDepth               = mTranslatedSource.find("GL_USES_FRAG_DEPTH")                   != std::string::npos;
        mUsesDiscardRewriting        = mTranslatedSource.find("ANGLE_USES_DISCARD_REWRITING")         != std::string::npos;
        mUsesNestedBreak             = mTranslatedSource.find("ANGLE_USES_NESTED_BREAK")              != std::string::npos;
        mUsesDeferredInit            = mTranslatedSource.find("ANGLE_USES_DEFERRED_INIT")             != std::string::npos;
        mRequiresIEEEStrictCompiling = mTranslatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;
    }
}
static bool getSymbolInfo(ShHandle compiler, ANGLEShaderSymbolType symbolType, Vector<ANGLEShaderSymbol>& symbols)
{
    switch (symbolType) {
    case SHADER_SYMBOL_TYPE_UNIFORM: {
        auto uniforms = ShGetUniforms(compiler);
        if (!uniforms)
            return false;
        for (const auto& uniform : *uniforms)
            getSymbolInfo(uniform, symbolType, symbols);
        break;
    }
    case SHADER_SYMBOL_TYPE_VARYING: {
        auto varyings = ShGetVaryings(compiler);
        if (!varyings)
            return false;
        for (const auto& varying : *varyings)
            getSymbolInfo(varying, symbolType, symbols);
        break;
    }
    case SHADER_SYMBOL_TYPE_ATTRIBUTE: {
        auto attributes = ShGetAttributes(compiler);
        if (!attributes)
            return false;
        for (const auto& attribute : *attributes)
            getSymbolInfo(attribute, symbolType, symbols);
        break;
    }
    default:
        ASSERT_NOT_REACHED();
        return false;
    }
    return true;
}
Exemple #3
0
void ShaderD3D::parseVaryings(void *compiler)
{
    if (!mHlsl.empty())
    {
        const std::vector<sh::Varying> *varyings = ShGetVaryings(compiler);
        ASSERT(varyings);

        for (size_t varyingIndex = 0; varyingIndex < varyings->size(); varyingIndex++)
        {
            mVaryings.push_back(gl::PackedVarying((*varyings)[varyingIndex]));
        }

        mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT")          != std::string::npos;
        mUsesFragColor             = mHlsl.find("GL_USES_FRAG_COLOR")   != std::string::npos;
        mUsesFragData              = mHlsl.find("GL_USES_FRAG_DATA")    != std::string::npos;
        mUsesFragCoord             = mHlsl.find("GL_USES_FRAG_COORD")   != std::string::npos;
        mUsesFrontFacing           = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos;
        mUsesPointSize             = mHlsl.find("GL_USES_POINT_SIZE")   != std::string::npos;
        mUsesPointCoord            = mHlsl.find("GL_USES_POINT_COORD")  != std::string::npos;
        mUsesDepthRange            = mHlsl.find("GL_USES_DEPTH_RANGE")  != std::string::npos;
        mUsesFragDepth             = mHlsl.find("GL_USES_FRAG_DEPTH")   != std::string::npos;
        mUsesDiscardRewriting      = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
        mUsesNestedBreak           = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
    }
}
bool
ShaderValidator::FindVaryingMappedNameByUserName(const std::string& userName,
                                                 const std::string** const out_mappedName) const
{
    const std::vector<sh::Varying>& attribs = *ShGetVaryings(mHandle);
    for (auto itr = attribs.begin(); itr != attribs.end(); ++itr) {
        if (itr->name == userName) {
            *out_mappedName = &(itr->mappedName);
            return true;
        }
    }

    return false;
}
bool
ShaderValidator::FindVaryingByMappedName(const std::string& mappedName,
                                         std::string* const out_userName,
                                         bool* const out_isArray) const
{
    const std::vector<sh::Varying>& varyings = *ShGetVaryings(mHandle);
    for (auto itr = varyings.begin(); itr != varyings.end(); ++itr) {
        const sh::ShaderVariable* found;
        if (!itr->findInfoByMappedName(mappedName, &found, out_userName))
            continue;

        *out_isArray = found->isArray();
        return true;
    }

    return false;
}
static void PrintActiveVariables(ShHandle compiler)
{
    const std::vector<sh::Uniform> *uniforms = ShGetUniforms(compiler);
    const std::vector<sh::Varying> *varyings = ShGetVaryings(compiler);
    const std::vector<sh::Attribute> *attributes = ShGetAttributes(compiler);
    for (size_t varCategory = 0; varCategory < 3; ++varCategory)
    {
        size_t numVars = 0;
        std::string varCategoryName;
        if (varCategory == 0)
        {
            numVars = uniforms->size();
            varCategoryName = "uniform";
        }
        else if (varCategory == 1)
        {
            numVars = varyings->size();
            varCategoryName = "varying";
        }
        else
        {
            numVars = attributes->size();
            varCategoryName = "attribute";
        }
        for (size_t i = 0; i < numVars; ++i)
        {
            const sh::ShaderVariable *var;
            if (varCategory == 0)
                var = &((*uniforms)[i]);
            else if (varCategory == 1)
                var = &((*varyings)[i]);
            else
                var = &((*attributes)[i]);
            PrintVariable(varCategoryName, i, *var);
        }
        printf("\n");
    }
}
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;
}
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 auto shaderVersion = ShGetShaderVersion(mHandle);
    if (ShGetShaderVersion(prev->mHandle) != shaderVersion) {
        nsPrintfCString error("Vertex shader version %d does not match"
                              " fragment shader version %d.",
                              ShGetShaderVersion(prev->mHandle),
                              ShGetShaderVersion(mHandle));
        *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 auto vertVars = sh::GetInterfaceBlocks(prev->mHandle);
        const auto fragVars = sh::GetInterfaceBlocks(mHandle);
        if (!vertVars || !fragVars) {
            nsPrintfCString error("Could not create uniform block list.");
            *out_log = error;
            return false;
        }

        for (const auto& fragVar : *fragVars) {
            for (const auto& vertVar : *vertVars) {
                if (vertVar.name != fragVar.name)
                    continue;

                if (!vertVar.isSameInterfaceBlockAtLinkTime(fragVar)) {
                    nsPrintfCString error("Interface block `%s` is not linkable between"
                                          " attached shaders.",
                                          fragVar.name.c_str());
                    *out_log = error;
                    return false;
                }

                break;
            }
        }
    }

    const auto& vertVaryings = ShGetVaryings(prev->mHandle);
    const auto& fragVaryings = ShGetVaryings(mHandle);
    if (!vertVaryings || !fragVaryings) {
        nsPrintfCString error("Could not create varying list.");
        *out_log = error;
        return false;
    }

    {
        std::vector<sh::ShaderVariable> staticUseVaryingList;

        for (const auto& fragVarying : *fragVaryings) {
            static const char prefix[] = "gl_";
            if (StartsWith(fragVarying.name, prefix)) {
                if (fragVarying.staticUse) {
                    staticUseVaryingList.push_back(fragVarying);
                }
                continue;
            }

            bool definedInVertShader = false;
            bool staticVertUse = false;

            for (const auto& vertVarying : *vertVaryings) {
                if (vertVarying.name != fragVarying.name)
                    continue;

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

                definedInVertShader = true;
                staticVertUse = vertVarying.staticUse;
                break;
            }

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

            if (staticVertUse && fragVarying.staticUse) {
                staticUseVaryingList.push_back(fragVarying);
            }
        }

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

    if (shaderVersion == 100) {
        // Enforce ESSL1 invariant linking rules.
        bool isInvariant_Position = false;
        bool isInvariant_PointSize = false;
        bool isInvariant_FragCoord = false;
        bool isInvariant_PointCoord = false;

        for (const auto& varying : *vertVaryings) {
            if (varying.name == "gl_Position") {
                isInvariant_Position = varying.isInvariant;
            } else if (varying.name == "gl_PointSize") {
                isInvariant_PointSize = varying.isInvariant;
            }
        }

        for (const auto& varying : *fragVaryings) {
            if (varying.name == "gl_FragCoord") {
                isInvariant_FragCoord = varying.isInvariant;
            } else if (varying.name == "gl_PointCoord") {
                isInvariant_PointCoord = varying.isInvariant;
            }
        }

        ////

        const auto fnCanBuiltInsLink = [](bool vertIsInvariant, bool fragIsInvariant) {
            if (vertIsInvariant)
                return true;

            return !fragIsInvariant;
        };

        if (!fnCanBuiltInsLink(isInvariant_Position, isInvariant_FragCoord)) {
            *out_log = "gl_Position must be invariant if gl_FragCoord is. (see GLSL ES"
                       " Specification 1.0.17, p39)";
            return false;
        }

        if (!fnCanBuiltInsLink(isInvariant_PointSize, isInvariant_PointCoord)) {
            *out_log = "gl_PointSize must be invariant if gl_PointCoord is. (see GLSL ES"
                       " Specification 1.0.17, p39)";
            return false;
        }
    }

    return true;
}
Exemple #9
0
void Shader::compile(Compiler *compiler)
{
    mData.mTranslatedSource.clear();
    mInfoLog.clear();
    mData.mShaderVersion = 100;
    mData.mVaryings.clear();
    mData.mUniforms.clear();
    mData.mInterfaceBlocks.clear();
    mData.mActiveAttributes.clear();
    mData.mActiveOutputVariables.clear();

    ShHandle compilerHandle = compiler->getCompilerHandle(mData.mShaderType);

    std::stringstream sourceStream;

    std::string sourcePath;
    int additionalOptions =
        mImplementation->prepareSourceAndReturnOptions(&sourceStream, &sourcePath);
    int compileOptions    = (SH_OBJECT_CODE | SH_VARIABLES | additionalOptions);

    // Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes
    // in fragment shaders. Shader compilation will fail. To provide a better error message we can
    // instruct the compiler to pre-validate.
    if (mRendererLimitations.shadersRequireIndexedLoopValidation)
    {
        compileOptions |= SH_VALIDATE_LOOP_INDEXING;
    }

    std::string sourceString  = sourceStream.str();
    std::vector<const char *> sourceCStrings;

    if (!sourcePath.empty())
    {
        sourceCStrings.push_back(sourcePath.c_str());
    }

    sourceCStrings.push_back(sourceString.c_str());

    bool result =
        ShCompile(compilerHandle, &sourceCStrings[0], sourceCStrings.size(), compileOptions);

    if (!result)
    {
        mInfoLog = ShGetInfoLog(compilerHandle);
        TRACE("\n%s", mInfoLog.c_str());
        mCompiled = false;
        return;
    }

    mData.mTranslatedSource = ShGetObjectCode(compilerHandle);

#ifndef NDEBUG
    // Prefix translated shader with commented out un-translated shader.
    // Useful in diagnostics tools which capture the shader source.
    std::ostringstream shaderStream;
    shaderStream << "// GLSL\n";
    shaderStream << "//\n";

    size_t curPos = 0;
    while (curPos != std::string::npos)
    {
        size_t nextLine = mData.mSource.find("\n", curPos);
        size_t len      = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);

        shaderStream << "// " << mData.mSource.substr(curPos, len);

        curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
    }
    shaderStream << "\n\n";
    shaderStream << mData.mTranslatedSource;
    mData.mTranslatedSource = shaderStream.str();
#endif

    // Gather the shader information
    mData.mShaderVersion = ShGetShaderVersion(compilerHandle);

    mData.mVaryings        = GetShaderVariables(ShGetVaryings(compilerHandle));
    mData.mUniforms        = GetShaderVariables(ShGetUniforms(compilerHandle));
    mData.mInterfaceBlocks = GetShaderVariables(ShGetInterfaceBlocks(compilerHandle));

    if (mData.mShaderType == GL_VERTEX_SHADER)
    {
        mData.mActiveAttributes = GetActiveShaderVariables(ShGetAttributes(compilerHandle));
    }
    else
    {
        ASSERT(mData.mShaderType == GL_FRAGMENT_SHADER);

        // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
        std::sort(mData.mVaryings.begin(), mData.mVaryings.end(), CompareShaderVar);
        mData.mActiveOutputVariables =
            GetActiveShaderVariables(ShGetOutputVariables(compilerHandle));
    }

    ASSERT(!mData.mTranslatedSource.empty());

    mCompiled = mImplementation->postTranslateCompile(compiler, &mInfoLog);
}