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 "common/PackedEnums.h" 20 #include "compiler/translator/BuiltInFunctionEmulator.h" 21 #include "compiler/translator/CallDAG.h" 22 #include "compiler/translator/Diagnostics.h" 23 #include "compiler/translator/ExtensionBehavior.h" 24 #include "compiler/translator/HashNames.h" 25 #include "compiler/translator/InfoSink.h" 26 #include "compiler/translator/Pragma.h" 27 #include "compiler/translator/SymbolTable.h" 28 #include "compiler/translator/ValidateAST.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 #ifdef ANGLE_ENABLE_METAL 39 class TranslatorMSL; 40 #endif // ANGLE_ENABLE_METAL 41 42 using MetadataFlagBits = angle::PackedEnumBitSet<sh::MetadataFlags, uint32_t>; 43 using SpecConstUsageBits = angle::PackedEnumBitSet<vk::SpecConstUsage, uint32_t>; 44 45 // 46 // Helper function to check if the shader type is GLSL. 47 // 48 bool IsGLSL130OrNewer(ShShaderOutput output); 49 bool IsGLSL420OrNewer(ShShaderOutput output); 50 bool IsGLSL410OrOlder(ShShaderOutput output); 51 52 // 53 // Helper function to check if the invariant qualifier can be removed. 54 // 55 bool RemoveInvariant(sh::GLenum shaderType, 56 int shaderVersion, 57 ShShaderOutput outputType, 58 const ShCompileOptions &compileOptions); 59 60 // 61 // The base class used to back handles returned to the driver. 62 // 63 class TShHandleBase 64 { 65 public: 66 TShHandleBase(); 67 virtual ~TShHandleBase(); getAsCompiler()68 virtual TCompiler *getAsCompiler() { return nullptr; } 69 #ifdef ANGLE_ENABLE_HLSL getAsTranslatorHLSL()70 virtual TranslatorHLSL *getAsTranslatorHLSL() { return nullptr; } 71 #endif // ANGLE_ENABLE_HLSL 72 #ifdef ANGLE_ENABLE_METAL getAsTranslatorMSL()73 virtual TranslatorMSL *getAsTranslatorMSL() { return nullptr; } 74 #endif // ANGLE_ENABLE_METAL 75 76 protected: 77 // Memory allocator. Allocates and tracks memory required by the compiler. 78 // Deallocates all memory when compiler is destructed. 79 angle::PoolAllocator allocator; 80 }; 81 82 struct TFunctionMetadata 83 { 84 bool used = false; 85 }; 86 87 // 88 // The base class for the machine dependent compiler to derive from 89 // for managing object code from the compile. 90 // 91 class TCompiler : public TShHandleBase 92 { 93 public: 94 TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); 95 ~TCompiler() override; getAsCompiler()96 TCompiler *getAsCompiler() override { return this; } 97 98 bool Init(const ShBuiltInResources &resources); 99 100 // compileTreeForTesting should be used only when tests require access to 101 // the AST. Users of this function need to manually manage the global pool 102 // allocator. Returns nullptr whenever there are compilation errors. 103 TIntermBlock *compileTreeForTesting(const char *const shaderStrings[], 104 size_t numStrings, 105 const ShCompileOptions &compileOptions); 106 107 bool compile(const char *const shaderStrings[], 108 size_t numStrings, 109 const ShCompileOptions &compileOptions); 110 111 // Get results of the last compilation. getShaderVersion()112 int getShaderVersion() const { return mShaderVersion; } getInfoSink()113 TInfoSink &getInfoSink() { return mInfoSink; } 114 specifyEarlyFragmentTests()115 bool specifyEarlyFragmentTests() { return mEarlyFragmentTestsSpecified = true; } isEarlyFragmentTestsSpecified()116 bool isEarlyFragmentTestsSpecified() const { return mEarlyFragmentTestsSpecified; } getMetadataFlags()117 MetadataFlagBits getMetadataFlags() const { return mMetadataFlags; } getSpecConstUsageBits()118 SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; } 119 isComputeShaderLocalSizeDeclared()120 bool isComputeShaderLocalSizeDeclared() const { return mComputeShaderLocalSizeDeclared; } getComputeShaderLocalSize()121 const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; } getNumViews()122 int getNumViews() const { return mNumViews; } 123 124 // Clears the results from the previous compilation. 125 void clearResults(); 126 getAttributes()127 const std::vector<sh::ShaderVariable> &getAttributes() const { return mAttributes; } getOutputVariables()128 const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; } getUniforms()129 const std::vector<sh::ShaderVariable> &getUniforms() const { return mUniforms; } getInputVaryings()130 const std::vector<sh::ShaderVariable> &getInputVaryings() const { return mInputVaryings; } getOutputVaryings()131 const std::vector<sh::ShaderVariable> &getOutputVaryings() const { return mOutputVaryings; } getInterfaceBlocks()132 const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; } getUniformBlocks()133 const std::vector<sh::InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; } getShaderStorageBlocks()134 const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const 135 { 136 return mShaderStorageBlocks; 137 } 138 getHashFunction()139 ShHashFunction64 getHashFunction() const { return mResources.HashFunction; } getNameMap()140 NameMap &getNameMap() { return mNameMap; } getSymbolTable()141 TSymbolTable &getSymbolTable() { return mSymbolTable; } getShaderSpec()142 ShShaderSpec getShaderSpec() const { return mShaderSpec; } getOutputType()143 ShShaderOutput getOutputType() const { return mOutputType; } getBuiltInResources()144 const ShBuiltInResources &getBuiltInResources() const { return mResources; } getBuiltInResourcesString()145 const std::string &getBuiltInResourcesString() const { return mBuiltInResourcesString; } 146 147 bool isHighPrecisionSupported() const; 148 149 bool shouldRunLoopAndIndexingValidation(const ShCompileOptions &compileOptions) const; 150 bool shouldLimitTypeSizes() const; 151 152 // Get the resources set by InitBuiltInSymbolTable 153 const ShBuiltInResources &getResources() const; 154 getPragma()155 const TPragma &getPragma() const { return mPragma; } 156 getGeometryShaderMaxVertices()157 int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; } getGeometryShaderInvocations()158 int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; } getGeometryShaderInputPrimitiveType()159 TLayoutPrimitiveType getGeometryShaderInputPrimitiveType() const 160 { 161 return mGeometryShaderInputPrimitiveType; 162 } getGeometryShaderOutputPrimitiveType()163 TLayoutPrimitiveType getGeometryShaderOutputPrimitiveType() const 164 { 165 return mGeometryShaderOutputPrimitiveType; 166 } 167 168 unsigned int getStructSize(const ShaderVariable &var) const; 169 getTessControlShaderOutputVertices()170 int getTessControlShaderOutputVertices() const { return mTessControlShaderOutputVertices; } getTessEvaluationShaderInputPrimitiveType()171 TLayoutTessEvaluationType getTessEvaluationShaderInputPrimitiveType() const 172 { 173 return mTessEvaluationShaderInputPrimitiveType; 174 } getTessEvaluationShaderInputVertexSpacingType()175 TLayoutTessEvaluationType getTessEvaluationShaderInputVertexSpacingType() const 176 { 177 return mTessEvaluationShaderInputVertexSpacingType; 178 } getTessEvaluationShaderInputOrderingType()179 TLayoutTessEvaluationType getTessEvaluationShaderInputOrderingType() const 180 { 181 return mTessEvaluationShaderInputOrderingType; 182 } getTessEvaluationShaderInputPointType()183 TLayoutTessEvaluationType getTessEvaluationShaderInputPointType() const 184 { 185 return mTessEvaluationShaderInputPointType; 186 } 187 hasAnyPreciseType()188 bool hasAnyPreciseType() const { return mHasAnyPreciseType; } 189 getAdvancedBlendEquations()190 AdvancedBlendEquations getAdvancedBlendEquations() const { return mAdvancedBlendEquations; } 191 hasPixelLocalStorageUniforms()192 bool hasPixelLocalStorageUniforms() const { return !mPixelLocalStorageFormats.empty(); } GetPixelLocalStorageFormats()193 const std::vector<ShPixelLocalStorageFormat> &GetPixelLocalStorageFormats() const 194 { 195 return mPixelLocalStorageFormats; 196 } 197 getPixelLocalStorageType()198 ShPixelLocalStorageType getPixelLocalStorageType() const { return mCompileOptions.pls.type; } 199 200 unsigned int getSharedMemorySize() const; 201 getShaderType()202 sh::GLenum getShaderType() const { return mShaderType; } 203 204 // Generate a self-contained binary representation of the shader. 205 bool getShaderBinary(const ShHandle compilerHandle, 206 const char *const shaderStrings[], 207 size_t numStrings, 208 const ShCompileOptions &compileOptions, 209 ShaderBinaryBlob *const binaryOut); 210 211 // Validate the AST and produce errors if it is inconsistent. 212 bool validateAST(TIntermNode *root); 213 // Some transformations may need to temporarily disable validation until they are complete. A 214 // set of disable/enable helpers are used for this purpose. 215 bool disableValidateFunctionCall(); 216 void restoreValidateFunctionCall(bool enable); 217 bool disableValidateVariableReferences(); 218 void restoreValidateVariableReferences(bool enable); 219 // When the AST is post-processed (such as to determine precise-ness of intermediate nodes), 220 // it's expected to no longer transform. 221 void enableValidateNoMoreTransformations(); 222 areClipDistanceOrCullDistanceUsed()223 bool areClipDistanceOrCullDistanceUsed() const 224 { 225 return mClipDistanceSize > 0 || mCullDistanceSize > 0; 226 } 227 getClipDistanceArraySize()228 uint8_t getClipDistanceArraySize() const { return mClipDistanceSize; } 229 getCullDistanceArraySize()230 uint8_t getCullDistanceArraySize() const { return mCullDistanceSize; } 231 usesDerivatives()232 bool usesDerivatives() const { return mUsesDerivatives; } 233 supportsAttributeAliasing()234 bool supportsAttributeAliasing() const 235 { 236 return mShaderVersion == 100 && !IsWebGLBasedSpec(mShaderSpec); 237 } 238 239 protected: 240 // Add emulated functions to the built-in function emulator. initBuiltInFunctionEmulator(BuiltInFunctionEmulator * emu,const ShCompileOptions & compileOptions)241 virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, 242 const ShCompileOptions &compileOptions) 243 {} 244 // Translate to object code. May generate performance warnings through the diagnostics. 245 [[nodiscard]] virtual bool translate(TIntermBlock *root, 246 const ShCompileOptions &compileOptions, 247 PerformanceDiagnostics *perfDiagnostics) = 0; 248 // Get built-in extensions with default behavior. 249 const TExtensionBehavior &getExtensionBehavior() const; 250 const char *getSourcePath() const; 251 // Relies on collectVariables having been called. 252 bool isVaryingDefined(const char *varyingName); 253 254 const BuiltInFunctionEmulator &getBuiltInFunctionEmulator() const; 255 256 virtual bool shouldFlattenPragmaStdglInvariantAll() = 0; 257 258 std::vector<sh::ShaderVariable> mAttributes; 259 std::vector<sh::ShaderVariable> mOutputVariables; 260 std::vector<sh::ShaderVariable> mUniforms; 261 std::vector<sh::ShaderVariable> mInputVaryings; 262 std::vector<sh::ShaderVariable> mOutputVaryings; 263 std::vector<sh::ShaderVariable> mSharedVariables; 264 std::vector<sh::InterfaceBlock> mInterfaceBlocks; 265 std::vector<sh::InterfaceBlock> mUniformBlocks; 266 std::vector<sh::InterfaceBlock> mShaderStorageBlocks; 267 268 // Track what should be validated given passes currently applied. 269 ValidateASTOptions mValidateASTOptions; 270 271 MetadataFlagBits mMetadataFlags; 272 273 // Specialization constant usage bits 274 SpecConstUsageBits mSpecConstUsageBits; 275 276 private: 277 // Initialize symbol-table with built-in symbols. 278 bool initBuiltInSymbolTable(const ShBuiltInResources &resources); 279 // Compute the string representation of the built-in resources 280 void setResourceString(); 281 // Return false if the call depth is exceeded. 282 bool checkCallDepth(); 283 // Insert statements to reference all members in unused uniform blocks with standard and shared 284 // layout. This is to work around a Mac driver that treats unused standard/shared 285 // uniform blocks as inactive. 286 [[nodiscard]] bool useAllMembersInUnusedStandardAndSharedBlocks(TIntermBlock *root); 287 // Insert statements to initialize output variables in the beginning of main(). 288 // This is to avoid undefined behaviors. 289 [[nodiscard]] bool initializeOutputVariables(TIntermBlock *root); 290 // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). 291 // It is to work around a Linux driver bug where missing this causes compile failure 292 // while spec says it is allowed. 293 // This function should only be applied to vertex shaders. 294 [[nodiscard]] bool initializeGLPosition(TIntermBlock *root); 295 // Return true if the maximum expression complexity is below the limit. 296 bool limitExpressionComplexity(TIntermBlock *root); 297 // Creates the function call DAG for further analysis, returning false if there is a recursion 298 bool initCallDag(TIntermNode *root); 299 // Return false if "main" doesn't exist 300 bool tagUsedFunctions(); 301 void internalTagUsedFunction(size_t index); 302 303 void collectInterfaceBlocks(); 304 305 bool mVariablesCollected; 306 307 bool mGLPositionInitialized; 308 309 // Removes unused function declarations and prototypes from the AST 310 bool pruneUnusedFunctions(TIntermBlock *root); 311 312 TIntermBlock *compileTreeImpl(const char *const shaderStrings[], 313 size_t numStrings, 314 const ShCompileOptions &compileOptions); 315 316 // Fetches and stores shader metadata that is not stored within the AST itself, such as shader 317 // version. 318 void setASTMetadata(const TParseContext &parseContext); 319 320 // Check if shader version meets the requirement. 321 bool checkShaderVersion(TParseContext *parseContext); 322 323 // Does checks that need to be run after parsing is complete and returns true if they pass. 324 bool checkAndSimplifyAST(TIntermBlock *root, 325 const TParseContext &parseContext, 326 const ShCompileOptions &compileOptions); 327 328 bool postParseChecks(const TParseContext &parseContext); 329 330 sh::GLenum mShaderType; 331 ShShaderSpec mShaderSpec; 332 ShShaderOutput mOutputType; 333 334 CallDAG mCallDag; 335 std::vector<TFunctionMetadata> mFunctionMetadata; 336 337 ShBuiltInResources mResources; 338 std::string mBuiltInResourcesString; 339 340 // Built-in symbol table for the given language, spec, and resources. 341 // It is preserved from compile-to-compile. 342 TSymbolTable mSymbolTable; 343 // Built-in extensions with default behavior. 344 TExtensionBehavior mExtensionBehavior; 345 346 BuiltInFunctionEmulator mBuiltInFunctionEmulator; 347 348 // Results of compilation. 349 int mShaderVersion; 350 TInfoSink mInfoSink; // Output sink. 351 TDiagnostics mDiagnostics; 352 const char *mSourcePath; // Path of source file or NULL 353 354 // Fragment shader early fragment tests 355 bool mEarlyFragmentTestsSpecified; 356 357 // compute shader local group size 358 bool mComputeShaderLocalSizeDeclared; 359 sh::WorkGroupSize mComputeShaderLocalSize; 360 361 // GL_OVR_multiview num_views. 362 int mNumViews; 363 364 // Track gl_ClipDistance / gl_CullDistance usage. 365 uint8_t mClipDistanceSize; 366 uint8_t mCullDistanceSize; 367 368 // geometry shader parameters. 369 int mGeometryShaderMaxVertices; 370 int mGeometryShaderInvocations; 371 TLayoutPrimitiveType mGeometryShaderInputPrimitiveType; 372 TLayoutPrimitiveType mGeometryShaderOutputPrimitiveType; 373 374 // tesssellation shader parameters 375 int mTessControlShaderOutputVertices; 376 TLayoutTessEvaluationType mTessEvaluationShaderInputPrimitiveType; 377 TLayoutTessEvaluationType mTessEvaluationShaderInputVertexSpacingType; 378 TLayoutTessEvaluationType mTessEvaluationShaderInputOrderingType; 379 TLayoutTessEvaluationType mTessEvaluationShaderInputPointType; 380 381 bool mHasAnyPreciseType; 382 383 // advanced blend equation parameters 384 AdvancedBlendEquations mAdvancedBlendEquations; 385 386 // ANGLE_shader_pixel_local_storage: A mapping from binding index to the PLS uniform format at 387 // that index. 388 std::vector<ShPixelLocalStorageFormat> mPixelLocalStorageFormats; 389 390 // Fragment shader uses screen-space derivatives 391 bool mUsesDerivatives; 392 393 // name hashing. 394 NameMap mNameMap; 395 396 TPragma mPragma; 397 398 ShCompileOptions mCompileOptions; 399 }; 400 401 // 402 // This is the interface between the machine independent code 403 // and the machine dependent code. 404 // 405 // The machine dependent code should derive from the classes 406 // above. Then Construct*() and Delete*() will create and 407 // destroy the machine dependent objects, which contain the 408 // above machine independent information. 409 // 410 TCompiler *ConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); 411 void DeleteCompiler(TCompiler *); 412 413 struct ShaderDumpHeader 414 { 415 uint32_t type; 416 uint32_t spec; 417 uint32_t output; 418 uint8_t basicCompileOptions[32]; 419 uint8_t metalCompileOptions[32]; 420 uint8_t plsCompileOptions[32]; 421 uint8_t padding[20]; 422 }; 423 static_assert(sizeof(ShaderDumpHeader) == 128); 424 425 } // namespace sh 426 427 #endif // COMPILER_TRANSLATOR_COMPILER_H_ 428