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