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