1 // 2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 #ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_ 8 #define COMPILER_TRANSLATOR_OUTPUTHLSL_H_ 9 10 #include <list> 11 #include <map> 12 #include <stack> 13 14 #include "angle_gl.h" 15 #include "compiler/translator/ASTMetadataHLSL.h" 16 #include "compiler/translator/Compiler.h" 17 #include "compiler/translator/FlagStd140Structs.h" 18 #include "compiler/translator/IntermTraverse.h" 19 20 class BuiltInFunctionEmulator; 21 22 namespace sh 23 { 24 class StructureHLSL; 25 class TextureFunctionHLSL; 26 class TSymbolTable; 27 class ImageFunctionHLSL; 28 class UnfoldShortCircuit; 29 class UniformHLSL; 30 31 typedef std::map<TString, TIntermSymbol *> ReferencedSymbols; 32 33 class OutputHLSL : public TIntermTraverser 34 { 35 public: 36 OutputHLSL(sh::GLenum shaderType, 37 int shaderVersion, 38 const TExtensionBehavior &extensionBehavior, 39 const char *sourcePath, 40 ShShaderOutput outputType, 41 int numRenderTargets, 42 const std::vector<Uniform> &uniforms, 43 ShCompileOptions compileOptions, 44 TSymbolTable *symbolTable, 45 PerformanceDiagnostics *perfDiagnostics); 46 47 ~OutputHLSL(); 48 49 void output(TIntermNode *treeRoot, TInfoSinkBase &objSink); 50 51 const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const; 52 const std::map<std::string, unsigned int> &getUniformRegisterMap() const; 53 54 static TString initializer(const TType &type); 55 getInfoSink()56 TInfoSinkBase &getInfoSink() 57 { 58 ASSERT(!mInfoSinkStack.empty()); 59 return *mInfoSinkStack.top(); 60 } 61 62 static bool canWriteAsHLSLLiteral(TIntermTyped *expression); 63 64 protected: 65 void header(TInfoSinkBase &out, 66 const std::vector<MappedStruct> &std140Structs, 67 const BuiltInFunctionEmulator *builtInFunctionEmulator) const; 68 69 void writeFloat(TInfoSinkBase &out, float f); 70 void writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion); 71 const TConstantUnion *writeConstantUnionArray(TInfoSinkBase &out, 72 const TConstantUnion *const constUnion, 73 const size_t size); 74 75 // Visit AST nodes and output their code to the body stream 76 void visitSymbol(TIntermSymbol *) override; 77 void visitRaw(TIntermRaw *) override; 78 void visitConstantUnion(TIntermConstantUnion *) override; 79 bool visitSwizzle(Visit visit, TIntermSwizzle *node) override; 80 bool visitBinary(Visit visit, TIntermBinary *) override; 81 bool visitUnary(Visit visit, TIntermUnary *) override; 82 bool visitTernary(Visit visit, TIntermTernary *) override; 83 bool visitIfElse(Visit visit, TIntermIfElse *) override; 84 bool visitSwitch(Visit visit, TIntermSwitch *) override; 85 bool visitCase(Visit visit, TIntermCase *) override; 86 bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override; 87 bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; 88 bool visitAggregate(Visit visit, TIntermAggregate *) override; 89 bool visitBlock(Visit visit, TIntermBlock *node) override; 90 bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override; 91 bool visitDeclaration(Visit visit, TIntermDeclaration *node) override; 92 bool visitLoop(Visit visit, TIntermLoop *) override; 93 bool visitBranch(Visit visit, TIntermBranch *) override; 94 95 bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node); 96 97 // Emit one of three strings depending on traverse phase. Called with literal strings so using 98 // const char* instead of TString. 99 void outputTriplet(TInfoSinkBase &out, 100 Visit visit, 101 const char *preString, 102 const char *inString, 103 const char *postString); 104 void outputLineDirective(TInfoSinkBase &out, int line); 105 TString argumentString(const TIntermSymbol *symbol); 106 107 void outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node); 108 const TConstantUnion *writeConstantUnion(TInfoSinkBase &out, 109 const TType &type, 110 const TConstantUnion *constUnion); 111 112 void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out); 113 void outputAssign(Visit visit, const TType &type, TInfoSinkBase &out); 114 115 void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op); 116 117 // Returns true if it found a 'same symbol' initializer (initializer that references the 118 // variable it's initting) 119 bool writeSameSymbolInitializer(TInfoSinkBase &out, 120 TIntermSymbol *symbolNode, 121 TIntermTyped *expression); 122 // Returns true if variable initializer could be written using literal {} notation. 123 bool writeConstantInitialization(TInfoSinkBase &out, 124 TIntermSymbol *symbolNode, 125 TIntermTyped *expression); 126 127 void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node); 128 129 // Returns the function name 130 TString addStructEqualityFunction(const TStructure &structure); 131 TString addArrayEqualityFunction(const TType &type); 132 TString addArrayAssignmentFunction(const TType &type); 133 TString addArrayConstructIntoFunction(const TType &type); 134 135 // Ensures if the type is a struct, the struct is defined 136 void ensureStructDefined(const TType &type); 137 138 sh::GLenum mShaderType; 139 int mShaderVersion; 140 const TExtensionBehavior &mExtensionBehavior; 141 const char *mSourcePath; 142 const ShShaderOutput mOutputType; 143 ShCompileOptions mCompileOptions; 144 145 bool mInsideFunction; 146 147 // Output streams 148 TInfoSinkBase mHeader; 149 TInfoSinkBase mBody; 150 TInfoSinkBase mFooter; 151 152 // A stack is useful when we want to traverse in the header, or in helper functions, but not 153 // always write to the body. Instead use an InfoSink stack to keep our current state intact. 154 // TODO (jmadill): Just passing an InfoSink in function parameters would be simpler. 155 std::stack<TInfoSinkBase *> mInfoSinkStack; 156 157 ReferencedSymbols mReferencedUniforms; 158 ReferencedSymbols mReferencedUniformBlocks; 159 ReferencedSymbols mReferencedAttributes; 160 ReferencedSymbols mReferencedVaryings; 161 ReferencedSymbols mReferencedOutputVariables; 162 163 StructureHLSL *mStructureHLSL; 164 UniformHLSL *mUniformHLSL; 165 TextureFunctionHLSL *mTextureFunctionHLSL; 166 ImageFunctionHLSL *mImageFunctionHLSL; 167 168 // Parameters determining what goes in the header output 169 bool mUsesFragColor; 170 bool mUsesFragData; 171 bool mUsesDepthRange; 172 bool mUsesFragCoord; 173 bool mUsesPointCoord; 174 bool mUsesFrontFacing; 175 bool mUsesPointSize; 176 bool mUsesInstanceID; 177 bool mHasMultiviewExtensionEnabled; 178 bool mUsesViewID; 179 bool mUsesVertexID; 180 bool mUsesFragDepth; 181 bool mUsesNumWorkGroups; 182 bool mUsesWorkGroupID; 183 bool mUsesLocalInvocationID; 184 bool mUsesGlobalInvocationID; 185 bool mUsesLocalInvocationIndex; 186 bool mUsesXor; 187 bool mUsesDiscardRewriting; 188 bool mUsesNestedBreak; 189 bool mRequiresIEEEStrictCompiling; 190 191 int mNumRenderTargets; 192 193 int mUniqueIndex; // For creating unique names 194 195 CallDAG mCallDag; 196 MetadataList mASTMetadataList; 197 ASTMetadataHLSL *mCurrentFunctionMetadata; 198 bool mOutputLod0Function; 199 bool mInsideDiscontinuousLoop; 200 int mNestedLoopDepth; 201 202 TIntermSymbol *mExcessiveLoopIndex; 203 204 TString structInitializerString(int indent, const TType &type, const TString &name) const; 205 206 struct HelperFunction 207 { 208 TString functionName; 209 TString functionDefinition; 210 ~HelperFunctionHelperFunction211 virtual ~HelperFunction() {} 212 }; 213 214 // A list of all equality comparison functions. It's important to preserve the order at 215 // which we add the functions, since nested structures call each other recursively, and 216 // structure equality functions may need to call array equality functions and vice versa. 217 // The ownership of the pointers is maintained by the type-specific arrays. 218 std::vector<HelperFunction *> mEqualityFunctions; 219 220 struct StructEqualityFunction : public HelperFunction 221 { 222 const TStructure *structure; 223 }; 224 std::vector<StructEqualityFunction *> mStructEqualityFunctions; 225 226 struct ArrayHelperFunction : public HelperFunction 227 { 228 TType type; 229 }; 230 std::vector<ArrayHelperFunction *> mArrayEqualityFunctions; 231 232 std::vector<ArrayHelperFunction> mArrayAssignmentFunctions; 233 234 // The construct-into functions are functions that fill an N-element array passed as an out 235 // parameter with the other N parameters of the function. This is used to work around that 236 // arrays can't be return values in HLSL. 237 std::vector<ArrayHelperFunction> mArrayConstructIntoFunctions; 238 239 PerformanceDiagnostics *mPerfDiagnostics; 240 241 private: 242 TString generateStructMapping(const std::vector<MappedStruct> &std140Structs) const; 243 TString samplerNamePrefixFromStruct(TIntermTyped *node); 244 bool ancestorEvaluatesToSamplerInStruct(); 245 }; 246 } 247 248 #endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_ 249