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