Edit

kc3-lang/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2015-05-04 11:24:57
    Hash : 55def583
    Message : translator: Fix variable collection for gl_DepthRange. *re-land with Linux fixes, and fix for locations* This built-in uniform wasn't being collected in VariableInfo.cpp. Also remove the existing workaround for D3D gl_DepthRange collection. BUG=angleproject:991 BUG=478570 Change-Id: Iba84651bfc58f82fd4ce039421874f561f83c348 Reviewed-on: https://chromium-review.googlesource.com/268840 Tested-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/renderer/d3d/ShaderD3D.cpp
  • //
    // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
    
    #include "libANGLE/Shader.h"
    #include "libANGLE/Compiler.h"
    #include "libANGLE/renderer/d3d/RendererD3D.h"
    #include "libANGLE/renderer/d3d/ShaderD3D.h"
    #include "libANGLE/renderer/d3d/CompilerD3D.h"
    #include "libANGLE/features.h"
    
    #include "common/utilities.h"
    
    // Definitions local to the translation unit
    namespace
    {
    
    const char *GetShaderTypeString(GLenum type)
    {
        switch (type)
        {
          case GL_VERTEX_SHADER:
            return "VERTEX";
    
          case GL_FRAGMENT_SHADER:
            return "FRAGMENT";
    
          default:
            UNREACHABLE();
            return "";
        }
    }
    
    }
    
    namespace rx
    {
    
    template <typename VarT>
    void FilterInactiveVariables(std::vector<VarT> *variableList)
    {
        ASSERT(variableList);
    
        for (size_t varIndex = 0; varIndex < variableList->size();)
        {
            if (!(*variableList)[varIndex].staticUse)
            {
                variableList->erase(variableList->begin() + varIndex);
            }
            else
            {
                varIndex++;
            }
        }
    }
    
    template <typename VarT>
    const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableList)
    {
        ASSERT(variableList);
        return variableList;
    }
    
    ShaderD3D::ShaderD3D(GLenum type)
        : mShaderType(type),
          mShaderVersion(100)
    {
        uncompile();
    }
    
    ShaderD3D::~ShaderD3D()
    {
    }
    
    std::string ShaderD3D::getDebugInfo() const
    {
        return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mShaderType) + " SHADER END\n";
    }
    
    
    void ShaderD3D::parseVaryings(ShHandle compiler)
    {
        if (!mTranslatedSource.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   = 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;
        }
    }
    
    void ShaderD3D::resetVaryingsRegisterAssignment()
    {
        for (size_t varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++)
        {
            mVaryings[varyingIndex].resetRegisterAssignment();
        }
    }
    
    // initialize/clean up previous state
    void ShaderD3D::uncompile()
    {
        // set by compileToHLSL
        mCompilerOutputType = SH_ESSL_OUTPUT;
        mTranslatedSource.clear();
        mInfoLog.clear();
    
        mUsesMultipleRenderTargets = false;
        mUsesFragColor = false;
        mUsesFragData = false;
        mUsesFragCoord = false;
        mUsesFrontFacing = false;
        mUsesPointSize = false;
        mUsesPointCoord = false;
        mUsesDepthRange = false;
        mUsesFragDepth = false;
        mShaderVersion = 100;
        mUsesDiscardRewriting = false;
        mUsesNestedBreak = false;
        mUsesDeferredInit = false;
        mRequiresIEEEStrictCompiling = false;
    
        mVaryings.clear();
        mUniforms.clear();
        mInterfaceBlocks.clear();
        mActiveAttributes.clear();
        mActiveOutputVariables.clear();
        mDebugInfo.clear();
    }
    
    void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source)
    {
        int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES);
        std::string sourcePath;
    
    #if !defined (ANGLE_ENABLE_WINDOWS_STORE)
        if (gl::DebugAnnotationsActive())
        {
            sourcePath = getTempPath();
            writeFile(sourcePath.c_str(), source.c_str(), source.length());
            compileOptions |= SH_LINE_DIRECTIVES;
        }
    #endif
    
        int result;
        if (sourcePath.empty())
        {
            const char* sourceStrings[] =
            {
                source.c_str(),
            };
    
            result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions);
        }
        else
        {
            const char* sourceStrings[] =
            {
                sourcePath.c_str(),
                source.c_str(),
            };
    
            result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH);
        }
    
        mShaderVersion = ShGetShaderVersion(compiler);
    
        if (result)
        {
            mTranslatedSource = ShGetObjectCode(compiler);
    
    #ifdef _DEBUG
            // Prefix hlsl shader with commented out glsl shader
            // Useful in diagnostics tools like pix which capture the hlsl shaders
            std::ostringstream hlslStream;
            hlslStream << "// GLSL\n";
            hlslStream << "//\n";
    
            size_t curPos = 0;
            while (curPos != std::string::npos)
            {
                size_t nextLine = source.find("\n", curPos);
                size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
    
                hlslStream << "// " << source.substr(curPos, len);
    
                curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
            }
            hlslStream << "\n\n";
            hlslStream << mTranslatedSource;
            mTranslatedSource = hlslStream.str();
    #endif
    
            mUniforms = *GetShaderVariables(ShGetUniforms(compiler));
    
            for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
            {
                const sh::Uniform &uniform = mUniforms[uniformIndex];
    
                if (uniform.staticUse && !uniform.isBuiltIn())
                {
                    unsigned int index = static_cast<unsigned int>(-1);
                    bool getUniformRegisterResult = ShGetUniformRegister(compiler, uniform.name, &index);
                    UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult);
                    ASSERT(getUniformRegisterResult);
    
                    mUniformRegisterMap[uniform.name] = index;
                }
            }
    
            mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler));
    
            for (size_t blockIndex = 0; blockIndex < mInterfaceBlocks.size(); blockIndex++)
            {
                const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex];
    
                if (interfaceBlock.staticUse)
                {
                    unsigned int index = static_cast<unsigned int>(-1);
                    bool blockRegisterResult = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index);
                    UNUSED_ASSERTION_VARIABLE(blockRegisterResult);
                    ASSERT(blockRegisterResult);
    
                    mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
                }
            }
        }
        else
        {
            mInfoLog = ShGetInfoLog(compiler);
    
            TRACE("\n%s", mInfoLog.c_str());
        }
    }
    
    void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const
    {
        if (mUsesDiscardRewriting)
        {
            // ANGLE issue 486:
            // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
            workarounds->skipOptimization = true;
        }
        else if (mUsesNestedBreak)
        {
            // ANGLE issue 603:
            // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
            // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
            workarounds->useMaxOptimization = true;
        }
    
        if (mRequiresIEEEStrictCompiling)
        {
            // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work.
            workarounds->enableIEEEStrictness = true;
        }
    }
    
    // true if varying x has a higher priority in packing than y
    bool ShaderD3D::compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y)
    {
        if (x.type == y.type)
        {
            return x.arraySize > y.arraySize;
        }
    
        // Special case for handling structs: we sort these to the end of the list
        if (x.type == GL_STRUCT_ANGLEX)
        {
            return false;
        }
    
        if (y.type == GL_STRUCT_ANGLEX)
        {
            return true;
        }
    
        return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
    }
    
    unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const
    {
        ASSERT(mUniformRegisterMap.count(uniformName) > 0);
        return mUniformRegisterMap.find(uniformName)->second;
    }
    
    unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) const
    {
        ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0);
        return mInterfaceBlockRegisterMap.find(blockName)->second;
    }
    
    GLenum ShaderD3D::getShaderType() const
    {
        return mShaderType;
    }
    
    ShShaderOutput ShaderD3D::getCompilerOutputType() const
    {
        return mCompilerOutputType;
    }
    
    bool ShaderD3D::compile(gl::Compiler *compiler, const std::string &source)
    {
        uncompile();
    
        CompilerD3D *compilerD3D = GetImplAs<CompilerD3D>(compiler);
        ShHandle compilerHandle = compilerD3D->getCompilerHandle(mShaderType);
    
        mCompilerOutputType = ShGetShaderOutputType(compilerHandle);
    
        compileToHLSL(compilerHandle, source);
    
        if (mShaderType == GL_VERTEX_SHADER)
        {
            parseAttributes(compilerHandle);
        }
    
        parseVaryings(compilerHandle);
    
        if (mShaderType == GL_FRAGMENT_SHADER)
        {
            std::sort(mVaryings.begin(), mVaryings.end(), compareVarying);
    
            const std::string &hlsl = getTranslatedSource();
            if (!hlsl.empty())
            {
                mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compilerHandle));
                FilterInactiveVariables(&mActiveOutputVariables);
            }
        }
    
    #if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
        mDebugInfo += std::string("// ") + GetShaderTypeString(mShaderType) + " SHADER BEGIN\n";
        mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n";
        mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + getTranslatedSource() + "\n// INITIAL HLSL END\n\n\n";
        // Successive steps will append more info
    #else
        mDebugInfo += getTranslatedSource();
    #endif
    
        return !getTranslatedSource().empty();
    }
    
    void ShaderD3D::parseAttributes(ShHandle compiler)
    {
        const std::string &hlsl = getTranslatedSource();
        if (!hlsl.empty())
        {
            mActiveAttributes = *GetShaderVariables(ShGetAttributes(compiler));
            FilterInactiveVariables(&mActiveAttributes);
        }
    }
    
    }