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