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_COMPILER_H_ 8 #define COMPILER_TRANSLATOR_COMPILER_H_ 9 10 // 11 // Machine independent part of the compiler private objects 12 // sent as ShHandle to the driver. 13 // 14 // This should not be included by driver code. 15 // 16 17 #include <GLSLANG/ShaderVars.h> 18 19 #include "compiler/translator/BuiltInFunctionEmulator.h" 20 #include "compiler/translator/CallDAG.h" 21 #include "compiler/translator/Diagnostics.h" 22 #include "compiler/translator/ExtensionBehavior.h" 23 #include "compiler/translator/HashNames.h" 24 #include "compiler/translator/InfoSink.h" 25 #include "compiler/translator/Pragma.h" 26 #include "compiler/translator/SymbolTable.h" 27 #include "compiler/translator/ValidateAST.h" 28 #include "third_party/compiler/ArrayBoundsClamper.h" 29 30 namespace sh 31 { 32 33 class TCompiler; 34 class TParseContext; 35 #ifdef ANGLE_ENABLE_HLSL 36 class TranslatorHLSL; 37 #endif // ANGLE_ENABLE_HLSL 38 39 // 40 // Helper function to check if the shader type is GLSL. 41 // 42 bool IsGLSL130OrNewer(ShShaderOutput output); 43 bool IsGLSL420OrNewer(ShShaderOutput output); 44 bool IsGLSL410OrOlder(ShShaderOutput output); 45 46 // 47 // Helper function to check if the invariant qualifier can be removed. 48 // 49 bool RemoveInvariant(sh::GLenum shaderType, 50 int shaderVersion, 51 ShShaderOutput outputType, 52 ShCompileOptions compileOptions); 53 54 // 55 // The base class used to back handles returned to the driver. 56 // 57 class TShHandleBase 58 { 59 public: 60 TShHandleBase(); 61 virtual ~TShHandleBase(); getAsCompiler()62 virtual TCompiler *getAsCompiler() { return 0; } 63 #ifdef ANGLE_ENABLE_HLSL getAsTranslatorHLSL()64 virtual TranslatorHLSL *getAsTranslatorHLSL() { return 0; } 65 #endif // ANGLE_ENABLE_HLSL 66 67 protected: 68 // Memory allocator. Allocates and tracks memory required by the compiler. 69 // Deallocates all memory when compiler is destructed. 70 angle::PoolAllocator allocator; 71 }; 72 73 // 74 // The base class for the machine dependent compiler to derive from 75 // for managing object code from the compile. 76 // 77 class TCompiler : public TShHandleBase 78 { 79 public: 80 TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); 81 ~TCompiler() override; getAsCompiler()82 TCompiler *getAsCompiler() override { return this; } 83 84 bool Init(const ShBuiltInResources &resources); 85 86 // compileTreeForTesting should be used only when tests require access to 87 // the AST. Users of this function need to manually manage the global pool 88 // allocator. Returns nullptr whenever there are compilation errors. 89 TIntermBlock *compileTreeForTesting(const char *const shaderStrings[], 90 size_t numStrings, 91 ShCompileOptions compileOptions); 92 93 bool compile(const char *const shaderStrings[], 94 size_t numStrings, 95 ShCompileOptions compileOptions); 96 97 // Get results of the last compilation. getShaderVersion()98 int getShaderVersion() const { return mShaderVersion; } getInfoSink()99 TInfoSink &getInfoSink() { return mInfoSink; } 100 isEarlyFragmentTestsSpecified()101 bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; } isEarlyFragmentTestsOptimized()102 bool isEarlyFragmentTestsOptimized() const { return mEarlyFragmentTestsOptimized; } 103 isComputeShaderLocalSizeDeclared()104 bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } getComputeShaderLocalSize()105 const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } getNumViews()106 int getNumViews() const { return mNumViews; } 107 108 // Clears the results from the previous compilation. 109 void clearResults(); 110 getAttributes()111 const std::vector<sh::ShaderVariable> &getAttributes() const { return mAttributes; } getOutputVariables()112 const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; } getUniforms()113 const std::vector<sh::ShaderVariable> &getUniforms() const { return mUniforms; } getInputVaryings()114 const std::vector<sh::ShaderVariable> &getInputVaryings() const { return mInputVaryings; } getOutputVaryings()115 const std::vector<sh::ShaderVariable> &getOutputVaryings() const { return mOutputVaryings; } getInterfaceBlocks()116 const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; } getUniformBlocks()117 const std::vector<sh::InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; } getShaderStorageBlocks()118 const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const 119 { 120 return mShaderStorageBlocks; 121 } getInBlocks()122 const std::vector<sh::InterfaceBlock> &getInBlocks() const { return mInBlocks; } 123 getHashFunction()124 ShHashFunction64 getHashFunction() const { return mResources.HashFunction; } getNameMap()125 NameMap &getNameMap() { return mNameMap; } getSymbolTable()126 TSymbolTable &getSymbolTable() { return mSymbolTable; } getShaderSpec()127 ShShaderSpec getShaderSpec() const { return mShaderSpec; } getOutputType()128 ShShaderOutput getOutputType() const { return mOutputType; } getBuiltInResourcesString()129 const std::string &getBuiltInResourcesString() const { return mBuiltInResourcesString; } 130 131 bool shouldRunLoopAndIndexingValidation(ShCompileOptions compileOptions) const; 132 133 // Get the resources set by InitBuiltInSymbolTable 134 const ShBuiltInResources &getResources() const; 135 getGeometryShaderMaxVertices()136 int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } getGeometryShaderInvocations()137 int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; } getGeometryShaderInputPrimitiveType()138 TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const 139 { 140 return mGeometryShaderInputPrimitiveType; 141 } getGeometryShaderOutputPrimitiveType()142 TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const 143 { 144 return mGeometryShaderOutputPrimitiveType; 145 } 146 147 unsigned int getStructSize(const ShaderVariable &var) const; 148 unsigned int getSharedMemorySize() const; 149 getShaderType()150 sh::GLenum getShaderType() const { return mShaderType; } 151 152 bool validateAST(TIntermNode *root); 153 154 protected: 155 // Add emulated functions to the built-in function emulator. initBuiltInFunctionEmulator(BuiltInFunctionEmulator * emu,ShCompileOptions compileOptions)156 virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, 157 ShCompileOptions compileOptions) 158 {} 159 // Translate to object code. May generate performance warnings through the diagnostics. 160 ANGLE_NO_DISCARD virtual bool translate(TIntermBlock *root, 161 ShCompileOptions compileOptions, 162 PerformanceDiagnostics *perfDiagnostics) = 0; 163 // Get built-in extensions with default behavior. 164 const TExtensionBehavior &getExtensionBehavior() const; 165 const char *getSourcePath() const; getPragma()166 const TPragma &getPragma() const { return mPragma; } 167 void writePragma(ShCompileOptions compileOptions); 168 // Relies on collectVariables having been called. 169 bool isVaryingDefined(const char *varyingName); 170 171 const ArrayBoundsClamper &getArrayBoundsClamper() const; 172 ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; 173 const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const; 174 175 virtual bool shouldFlattenPragmaStdglInvariantAll() = 0; 176 virtual bool shouldCollectVariables(ShCompileOptions compileOptions); 177 // If precision emulation needed, set isNeeded to true and emulate precision for given 178 // outputLanguage, returning false if that fails, else returning true. 179 bool emulatePrecisionIfNeeded(TIntermBlock *root, 180 TInfoSinkBase &sink, 181 bool *isNeeded, 182 const ShShaderOutput outputLanguage); 183 184 bool wereVariablesCollected() const; 185 std::vector<sh::ShaderVariable> mAttributes; 186 std::vector<sh::ShaderVariable> mOutputVariables; 187 std::vector<sh::ShaderVariable> mUniforms; 188 std::vector<sh::ShaderVariable> mInputVaryings; 189 std::vector<sh::ShaderVariable> mOutputVaryings; 190 std::vector<sh::ShaderVariable> mSharedVariables; 191 std::vector<sh::InterfaceBlock> mInterfaceBlocks; 192 std::vector<sh::InterfaceBlock> mUniformBlocks; 193 std::vector<sh::InterfaceBlock> mShaderStorageBlocks; 194 std::vector<sh::InterfaceBlock> mInBlocks; 195 196 private: 197 // Initialize symbol-table with built-in symbols. 198 bool initBuiltInSymbolTable(const ShBuiltInResources &resources); 199 // Compute the string representation of the built-in resources 200 void setResourceString(); 201 // Return false if the call depth is exceeded. 202 bool checkCallDepth(); 203 // Insert statements to reference all members in unused uniform blocks with standard and shared 204 // layout. This is to work around a Mac driver that treats unused standard/shared 205 // uniform blocks as inactive. 206 ANGLE_NO_DISCARD bool useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root); 207 // Insert statements to initialize output variables in the beginning of main(). 208 // This is to avoid undefined behaviors. 209 ANGLE_NO_DISCARD bool initializeOutputVariables(TIntermBlock *root); 210 // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). 211 // It is to work around a Linux driver bug where missing this causes compile failure 212 // while spec says it is allowed. 213 // This function should only be applied to vertex shaders. 214 ANGLE_NO_DISCARD bool initializeGLPosition(TIntermBlock *root); 215 // Return true if the maximum expression complexity is below the limit. 216 bool limitExpressionComplexity(TIntermBlock *root); 217 // Creates the function call DAG for further analysis, returning false if there is a recursion 218 bool initCallDag(TIntermNode *root); 219 // Return false if "main" doesn't exist 220 bool tagUsedFunctions(); 221 void internalTagUsedFunction(size_t index); 222 223 void collectInterfaceBlocks(); 224 225 bool mVariablesCollected; 226 227 bool mGLPositionInitialized; 228 229 // Removes unused function declarations and prototypes from the AST 230 class UnusedPredicate; 231 void pruneUnusedFunctions(TIntermBlock *root); 232 233 TIntermBlock *compileTreeImpl(const char *const shaderStrings[], 234 size_t numStrings, 235 const ShCompileOptions compileOptions); 236 237 // Fetches and stores shader metadata that is not stored within the AST itself, such as shader 238 // version. 239 void setASTMetadata(const TParseContext &parseContext); 240 241 // Check if shader version meets the requirement. 242 bool checkShaderVersion(TParseContext *parseContext); 243 244 // Does checks that need to be run after parsing is complete and returns true if they pass. 245 bool checkAndSimplifyAST(TIntermBlock *root, 246 const TParseContext &parseContext, 247 ShCompileOptions compileOptions); 248 249 sh::GLenum mShaderType; 250 ShShaderSpec mShaderSpec; 251 ShShaderOutput mOutputType; 252 253 struct FunctionMetadata 254 { FunctionMetadataFunctionMetadata255 FunctionMetadata() : used(false) {} 256 bool used; 257 }; 258 259 CallDAG mCallDag; 260 std::vector<FunctionMetadata> mFunctionMetadata; 261 262 ShBuiltInResources mResources; 263 std::string mBuiltInResourcesString; 264 265 // Built-in symbol table for the given language, spec, and resources. 266 // It is preserved from compile-to-compile. 267 TSymbolTable mSymbolTable; 268 // Built-in extensions with default behavior. 269 TExtensionBehavior mExtensionBehavior; 270 271 ArrayBoundsClamper mArrayBoundsClamper; 272 BuiltInFunctionEmulator mBuiltInFunctionEmulator; 273 274 // Results of compilation. 275 int mShaderVersion; 276 TInfoSink mInfoSink; // Output sink. 277 TDiagnostics mDiagnostics; 278 const char *mSourcePath; // Path of source file or NULL 279 280 // fragment shader early fragment tests 281 bool mEarlyFragmentTestsSpecified; 282 bool mEarlyFragmentTestsOptimized; 283 284 // compute shader local group size 285 bool mComputeShaderLocalSizeDeclared; 286 sh::WorkGroupSize mComputeShaderLocalSize; 287 288 // GL_OVR_multiview num_views. 289 int mNumViews; 290 291 // geometry shader parameters. 292 int mGeometryShaderMaxVertices; 293 int mGeometryShaderInvocations; 294 TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; 295 TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; 296 297 // name hashing. 298 NameMap mNameMap; 299 300 TPragma mPragma; 301 302 // Track what should be validated given passes currently applied. 303 ValidateASTOptions mValidateASTOptions; 304 305 ShCompileOptions mCompileOptions; 306 }; 307 308 // 309 // This is the interface between the machine independent code 310 // and the machine dependent code. 311 // 312 // The machine dependent code should derive from the classes 313 // above. Then Construct*() and Delete*() will create and 314 // destroy the machine dependent objects, which contain the 315 // above machine independent information. 316 // 317 TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); 318 void DeleteCompiler(TCompiler *); 319 320 void EmitEarlyFragmentTestsGLSL(const TCompiler &, TInfoSinkBase &sink); 321 void EmitWorkGroupSizeGLSL(const TCompiler &, TInfoSinkBase &sink); 322 void EmitMultiviewGLSL(const TCompiler &, 323 const ShCompileOptions &, 324 const TExtension, 325 const TBehavior, 326 TInfoSinkBase &sink); 327 328 } // namespace sh 329 330 #endif // COMPILER_TRANSLATOR_COMPILER_H_ 331