// // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2012-2016 LunarG, Inc. // Copyright (C) 2015-2020 Google, Inc. // Copyright (C) 2017, 2022-2024 Arm Limited. // Modifications Copyright (C) 2020-2021 Advanced Micro Devices, Inc. All rights reserved. // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // // Neither the name of 3Dlabs Inc. Ltd. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // // Create strings that declare built-in definitions, add built-ins programmatically // that cannot be expressed in the strings, and establish mappings between // built-in functions and operators. // // Where to put a built-in: // TBuiltIns::initialize(version,profile) context-independent textual built-ins; add them to the right string // TBuiltIns::initialize(resources,...) context-dependent textual built-ins; add them to the right string // TBuiltIns::identifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table, // including identifying what extensions are needed if a version does not allow a symbol // TBuiltIns::identifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the symbol table, // including identifying what extensions are needed if a version does not allow a symbol // #include <array> #include "Initialize.h" #include "span.h" namespace glslang { // TODO: ARB_Compatability: do full extension support const bool ARBCompatibility = …; const bool ForwardCompatibility = …; namespace { // // A set of definitions for tabling of the built-in functions. // // Order matters here, as does correlation with the subsequent // "const int ..." declarations and the ArgType enumerants. const char* TypeString[] = …; const int TypeStringCount = …; // number of entries in 'TypeString' const int TypeStringRowShift = …; // shift amount to go downe one row in 'TypeString' const int TypeStringColumnMask = …; // reduce type to its column number in 'TypeString' const int TypeStringScalarMask = …; // take type to its scalar column in 'TypeString' enum ArgType { … }; // Mixtures of the above, to help the function tables const ArgType TypeFI = …; const ArgType TypeFIB = …; const ArgType TypeIU = …; // The relationships between arguments and return type, whether anything is // output, or other unusual situations. enum ArgClass { … }; // Mixtures of the above, to help the function tables const ArgClass ClassV1FIOCV = …; const ArgClass ClassBNS = …; const ArgClass ClassRSNS = …; // A descriptor, for a single profile, of when something is available. // If the current profile does not match 'profile' mask below, the other fields // do not apply (nor validate). // profiles == EBadProfile is the end of an array of these struct Versioning { … }; EProfile EDesktopProfile = …; // Declare pointers to put into the table for versioning. const std::array Es300Desktop130Version = …; const std::array Es310Desktop400Version = …; const std::array Es310Desktop450Version = …; // The main descriptor of what a set of function prototypes can look like, and // a pointer to extra versioning information, when needed. struct BuiltInFunction { … }; // The tables can have the same built-in function name more than one time, // but the exact same prototype must be indicated at most once. // The prototypes that get declared are the union of all those indicated. // This is important when different releases add new prototypes for the same name. // It also also congnitively simpler tiling of the prototype space. // In practice, most names can be fully represented with one entry. // // Table is terminated by an OpNull TOperator. const std::array BaseFunctions = …; const std::array DerivativeFunctions = …; // For functions declared some other way, but still use the table to relate to operator. struct CustomFunction { … }; const CustomFunction CustomFunctions[] = …; // For the given table of functions, add all the indicated prototypes for each // one, to be returned in the passed in decls. void AddTabledBuiltin(TString& decls, const BuiltInFunction& function) { … } // See if the tabled versioning information allows the current version. bool ValidVersion(const BuiltInFunction& function, int version, EProfile profile, const SpvVersion& /* spVersion */) { … } // Relate a single table of built-ins to their AST operator. // This can get called redundantly (especially for the common built-ins, when // called once per stage). This is a performance issue only, not a correctness // concern. It is done for quality arising from simplicity, as there are subtleties // to get correct if instead trying to do it surgically. template<class FunctionContainer> void RelateTabledBuiltins(const FunctionContainer& functions, TSymbolTable& symbolTable) { … } } // end anonymous namespace // Add declarations for all tables of built-in functions. void TBuiltIns::addTabledBuiltins(int version, EProfile profile, const SpvVersion& spvVersion) { … } // Relate all tables of built-ins to the AST operators. void TBuiltIns::relateTabledBuiltins(int /* version */, EProfile /* profile */, const SpvVersion& /* spvVersion */, EShLanguage /* stage */, TSymbolTable& symbolTable) { … } inline bool IncludeLegacy(int version, EProfile profile, const SpvVersion& spvVersion) { … } // Construct TBuiltInParseables base class. This can be used for language-common constructs. TBuiltInParseables::TBuiltInParseables() { … } // Destroy TBuiltInParseables. TBuiltInParseables::~TBuiltInParseables() { … } TBuiltIns::TBuiltIns() { … } TBuiltIns::~TBuiltIns() { … } // // Add all context-independent built-in functions and variables that are present // for the given version and profile. Share common ones across stages, otherwise // make stage-specific entries. // // Most built-ins variables can be added as simple text strings. Some need to // be added programmatically, which is done later in IdentifyBuiltIns() below. // void TBuiltIns::initialize(int version, EProfile profile, const SpvVersion& spvVersion) { … } // // Helper function for initialize(), to add the second set of names for texturing, // when adding context-independent built-in functions. // void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile, const SpvVersion& spvVersion) { … } // // Helper function for add2ndGenerationSamplingImaging(), // when adding context-independent built-in functions. // // Add all the query functions for the given type. // void TBuiltIns::addQueryFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) { … } // // Helper function for add2ndGenerationSamplingImaging(), // when adding context-independent built-in functions. // // Add all the image access functions for the given type. // void TBuiltIns::addImageFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) { … } // // Helper function for initialize(), // when adding context-independent built-in functions. // // Add all the subpass access functions for the given type. // void TBuiltIns::addSubpassSampling(TSampler sampler, const TString& typeName, int /*version*/, EProfile /*profile*/) { … } // // Helper function for add2ndGenerationSamplingImaging(), // when adding context-independent built-in functions. // // Add all the texture lookup functions for the given type. // void TBuiltIns::addSamplingFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) { … } // // Helper function for add2ndGenerationSamplingImaging(), // when adding context-independent built-in functions. // // Add all the texture gather functions for the given type. // void TBuiltIns::addGatherFunctions(TSampler sampler, const TString& typeName, int version, EProfile profile) { … } // // Add context-dependent built-in functions and variables that are present // for the given version and profile. All the results are put into just the // commonBuiltins, because it is called for just a specific stage. So, // add stage-specific entries to the commonBuiltins, and only if that stage // was requested. // void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language) { … } // // To support special built-ins that have a special qualifier that cannot be declared textually // in a shader, like gl_Position. // // This lets the type of the built-in be declared textually, and then have just its qualifier be // updated afterward. // // Safe to call even if name is not present. // // Only use this for built-in variables that have a special qualifier in TStorageQualifier. // New built-in variables should use a generic (textually declarable) qualifier in // TStoraregQualifier and only call BuiltInVariable(). // static void SpecialQualifier(const char* name, TStorageQualifier qualifier, TBuiltInVariable builtIn, TSymbolTable& symbolTable) { … } // // Modify the symbol's flat decoration. // // Safe to call even if name is not present. // // Originally written to transform gl_SubGroupSizeARB from uniform to fragment input in Vulkan. // static void ModifyFlatDecoration(const char* name, bool flat, TSymbolTable& symbolTable) { … } // // To tag built-in variables with their TBuiltInVariable enum. Use this when the // normal declaration text already gets the qualifier right, and all that's needed // is setting the builtIn field. This should be the normal way for all new // built-in variables. // // If SpecialQualifier() was called, this does not need to be called. // // Safe to call even if name is not present. // static void BuiltInVariable(const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable) { … } static void RetargetVariable(const char* from, const char* to, TSymbolTable& symbolTable) { … } // // For built-in variables inside a named block. // SpecialQualifier() won't ever go inside a block; their member's qualifier come // from the qualification of the block. // // See comments above for other detail. // static void BuiltInVariable(const char* blockName, const char* name, TBuiltInVariable builtIn, TSymbolTable& symbolTable) { … } // // Finish adding/processing context-independent built-in symbols. // 1) Programmatically add symbols that could not be added by simple text strings above. // 2) Map built-in functions to operators, for those that will turn into an operation node // instead of remaining a function call. // 3) Tag extension-related symbols added to their base version with their extensions, so // that if an early version has the extension turned off, there is an error reported on use. // void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable) { … } // // Add context-dependent (resource-specific) built-ins not handled by the above. These // would be ones that need to be programmatically added because they cannot // be added by simple text strings. For these, also // 1) Map built-in functions to operators, for those that will turn into an operation node // instead of remaining a function call. // 2) Tag extension-related symbols added to their base version with their extensions, so // that if an early version has the extension turned off, there is an error reported on use. // void TBuiltIns::identifyBuiltIns(int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources) { … } } // end namespace glslang