Edit

kc3-lang/angle/src/compiler/translator/OutputHLSL.h

Branch :

  • Show log

    Commit

  • Author : Daniel Bratell
    Date : 2015-02-20 16:42:54
    Hash : 29190088
    Message : Make Angle code 40 KB smaller by using string literals directly. The implicit conversion of hundreds of string literals to TString generated a lot of machine code. By keeping them as string literals all the way the code will be smaller and faster. This is the change with clang for x64 (note VisitUnary in particular): Total change: -41392 bytes ========================== 2 added, totalling +469 bytes across 1 sources 2 removed, totalling -472 bytes across 1 sources 5 shrunk, for a net change of -41389 bytes (54126 bytes before, 12737 bytes after) across 1 sources 279692 unchanged, totalling 51433327 bytes ------------------------------------------------------------------------------------------------------------------------------------ -41392 - Source: /home/bratell/src/chromium/src/third_party/angle/src/compiler/translator/OutputHLSL.cpp - (gained 469, lost 41861) ------------------------------------------------------------------------------------------------------------------------------------ New symbols: +328: sh::OutputHLSL::outputConstructor(Visit, TType const&, char const*, TVector<TIntermNode*> const*) type=t, size=328 bytes +141: sh::OutputHLSL::outputTriplet(Visit, char const*, char const*, char const*) type=t, size=141 bytes Removed symbols: -133: sh::OutputHLSL::outputTriplet(Visit, std::basic_string<char, std::char_traits<char>, pool_allocator<char> > const&, std::basic_string<char, std::char_traits<char>, pool_allocator<char> > const&, std::basic_string<char, std::char_traits<char>, pool_allocator<char> > const&) type=t, size=133 bytes -339: sh::OutputHLSL::outputConstructor(Visit, TType const&, std::basic_string<char, std::char_traits<char>, pool_allocator<char> > const&, TVector<TIntermNode*> const*) type=t, size=339 bytes Shrunk symbols: -388: sh::OutputHLSL::writeEmulatedFunctionTriplet(Visit, char const*) type=t, (was 628 bytes, now 240 bytes) -714: sh::OutputHLSL::visitBranch(Visit, TIntermBranch*) type=t, (was 1017 bytes, now 303 bytes) -9738: sh::OutputHLSL::visitAggregate(Visit, TIntermAggregate*) type=t, (was 17609 bytes, now 7871 bytes) -14132: sh::OutputHLSL::visitBinary(Visit, TIntermBinary*) type=t, (was 17627 bytes, now 3495 bytes) -16417: sh::OutputHLSL::visitUnary(Visit, TIntermUnary*) type=t, (was 17245 bytes, now 828 bytes) Change-Id: Id0f87d72f6d7f1ab7b543f0d28d5a8b7c7db9ec7 Reviewed-on: https://chromium-review.googlesource.com/251090 Reviewed-by: Geoff Lang <geofflang@chromium.org> Tested-by: bratell at Opera <bratell@opera.com>

  • src/compiler/translator/OutputHLSL.h
  • //
    // Copyright (c) 2002-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.
    //
    
    #ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_
    #define COMPILER_TRANSLATOR_OUTPUTHLSL_H_
    
    #include <list>
    #include <set>
    #include <map>
    #include <stack>
    
    #include "angle_gl.h"
    #include "compiler/translator/IntermNode.h"
    #include "compiler/translator/ParseContext.h"
    
    class BuiltInFunctionEmulatorHLSL;
    
    namespace sh
    {
    class UnfoldShortCircuit;
    class StructureHLSL;
    class UniformHLSL;
    
    typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
    
    class OutputHLSL : public TIntermTraverser
    {
      public:
        OutputHLSL(sh::GLenum shaderType, int shaderVersion,
            const TExtensionBehavior &extensionBehavior,
            const char *sourcePath, ShShaderOutput outputType,
            int numRenderTargets, const std::vector<Uniform> &uniforms,
            int compileOptions);
    
        ~OutputHLSL();
    
        void output(TIntermNode *treeRoot, TInfoSinkBase &objSink);
    
        const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const;
        const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
    
        static TString initializer(const TType &type);
    
        TInfoSinkBase &getInfoSink() { ASSERT(!mInfoSinkStack.empty()); return *mInfoSinkStack.top(); }
    
      protected:
        void header(const BuiltInFunctionEmulatorHLSL *builtInFunctionEmulator);
    
        // Visit AST nodes and output their code to the body stream
        void visitSymbol(TIntermSymbol*);
        void visitRaw(TIntermRaw*);
        void visitConstantUnion(TIntermConstantUnion*);
        bool visitBinary(Visit visit, TIntermBinary*);
        bool visitUnary(Visit visit, TIntermUnary*);
        bool visitSelection(Visit visit, TIntermSelection*);
        bool visitAggregate(Visit visit, TIntermAggregate*);
        bool visitLoop(Visit visit, TIntermLoop*);
        bool visitBranch(Visit visit, TIntermBranch*);
    
        void traverseStatements(TIntermNode *node);
        bool isSingleStatement(TIntermNode *node);
        bool handleExcessiveLoop(TIntermLoop *node);
    
        // Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString.
        void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString);
        void outputLineDirective(int line);
        TString argumentString(const TIntermSymbol *symbol);
        int vectorSize(const TType &type) const;
    
        // Emit constructor. Called with literal names so using const char* instead of TString.
        void outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters);
        const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
    
        void writeEmulatedFunctionTriplet(Visit visit, const char *preStr);
        void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
    
        // Returns true if it found a 'same symbol' initializer (initializer that references the variable it's initting)
        bool writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression);
        void writeDeferredGlobalInitializers(TInfoSinkBase &out);
    
        // Returns the function name
        TString addStructEqualityFunction(const TStructure &structure);
    
        sh::GLenum mShaderType;
        int mShaderVersion;
        const TExtensionBehavior &mExtensionBehavior;
        const char *mSourcePath;
        const ShShaderOutput mOutputType;
        int mCompileOptions;
    
        UnfoldShortCircuit *mUnfoldShortCircuit;
        bool mInsideFunction;
    
        // Output streams
        TInfoSinkBase mHeader;
        TInfoSinkBase mBody;
        TInfoSinkBase mFooter;
    
        // A stack is useful when we want to traverse in the header, or in helper functions, but not always
        // write to the body. Instead use an InfoSink stack to keep our current state intact.
        std::stack<TInfoSinkBase *> mInfoSinkStack;
    
        ReferencedSymbols mReferencedUniforms;
        ReferencedSymbols mReferencedInterfaceBlocks;
        ReferencedSymbols mReferencedAttributes;
        ReferencedSymbols mReferencedVaryings;
        ReferencedSymbols mReferencedOutputVariables;
    
        StructureHLSL *mStructureHLSL;
        UniformHLSL *mUniformHLSL;
    
        struct TextureFunction
        {
            enum Method
            {
                IMPLICIT,   // Mipmap LOD determined implicitly (standard lookup)
                BIAS,
                LOD,
                LOD0,
                LOD0BIAS,
                SIZE,   // textureSize()
                FETCH,
                GRAD
            };
    
            TBasicType sampler;
            int coords;
            bool proj;
            bool offset;
            Method method;
    
            TString name() const;
    
            bool operator<(const TextureFunction &rhs) const;
        };
    
        typedef std::set<TextureFunction> TextureFunctionSet;
    
        // Parameters determining what goes in the header output
        TextureFunctionSet mUsesTexture;
        bool mUsesFragColor;
        bool mUsesFragData;
        bool mUsesDepthRange;
        bool mUsesFragCoord;
        bool mUsesPointCoord;
        bool mUsesFrontFacing;
        bool mUsesPointSize;
        bool mUsesInstanceID;
        bool mUsesFragDepth;
        bool mUsesXor;
        bool mUsesDiscardRewriting;
        bool mUsesNestedBreak;
    
        int mNumRenderTargets;
    
        int mUniqueIndex;   // For creating unique names
    
        bool mContainsLoopDiscontinuity;
        bool mContainsAnyLoop;
        bool mOutputLod0Function;
        bool mInsideDiscontinuousLoop;
        int mNestedLoopDepth;
    
        TIntermSymbol *mExcessiveLoopIndex;
    
        TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName);
    
        std::map<TIntermTyped*, TString> mFlaggedStructMappedNames;
        std::map<TIntermTyped*, TString> mFlaggedStructOriginalNames;
    
        // Some initializers use varyings, uniforms or attributes, thus we can't evaluate some variables
        // at global static scope in HLSL. These variables depend on values which we retrieve from the
        // shader input structure, which we set in the D3D main function. Instead, we can initialize
        // these static globals after we initialize our other globals.
        std::vector<std::pair<TIntermSymbol*, TIntermTyped*>> mDeferredGlobalInitializers;
    
        // A list of structure equality comparison functions. It's important to preserve the order at
        // which we add the functions, since nested structures call each other recursively.
        struct StructEqualityFunction
        {
            const TStructure *structure;
            TString functionName;
            TString functionDefinition;
        };
    
        std::vector<StructEqualityFunction> mStructEqualityFunctions;
    };
    
    }
    
    #endif   // COMPILER_TRANSLATOR_OUTPUTHLSL_H_