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