// // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. // Copyright (C) 2013-2016 LunarG, Inc. // Copyright (C) 2016-2020 Google, Inc. // Modifications Copyright(C) 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. // // this only applies to the standalone wrapper, not the front end in general #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif #include "glslang/Public/ResourceLimits.h" #include "Worklist.h" #include "DirStackFileIncluder.h" #include "./../glslang/Public/ShaderLang.h" #include "../glslang/MachineIndependent/localintermediate.h" #include "../SPIRV/GlslangToSpv.h" #include "../SPIRV/GLSL.std.450.h" #include "../SPIRV/disassemble.h" #include <array> #include <atomic> #include <cctype> #include <cmath> #include <cstdlib> #include <cstring> #include <map> #include <memory> #include <set> #include <thread> #include "../glslang/OSDependent/osinclude.h" // Build-time generated includes #include "glslang/build_info.h" #include "glslang/glsl_intrinsic_header.h" extern "C" { GLSLANG_EXPORT void ShOutputHtml(); } // Command-line options enum TOptions : uint64_t { … }; bool targetHlslFunctionality1 = …; bool SpvToolsDisassembler = …; bool SpvToolsValidate = …; bool NaNClamp = …; bool stripDebugInfo = …; bool emitNonSemanticShaderDebugInfo = …; bool emitNonSemanticShaderDebugSource = …; bool beQuiet = …; bool VulkanRulesRelaxed = …; bool autoSampledTextures = …; // // Return codes from main/exit(). // enum TFailCode { … }; // // Forward declarations. // EShLanguage FindLanguage(const std::string& name, bool parseSuffix=true); void CompileFile(const char* fileName, ShHandle); void usage(); char* ReadFileData(const char* fileName); void FreeFileData(char* data); void InfoLogMsg(const char* msg, const char* name, const int num); // Globally track if any compile or link failure. std::atomic<int8_t> CompileFailed{0}; std::atomic<int8_t> LinkFailed{0}; std::atomic<int8_t> CompileOrLinkFailed{0}; // array of unique places to leave the shader names and infologs for the asynchronous compiles std::vector<std::unique_ptr<glslang::TWorkItem>> WorkItems; std::string ConfigFile; // // Parse either a .conf file provided by the user or the default from glslang::DefaultTBuiltInResource // void ProcessConfigFile() { … } int ReflectOptions = …; std::underlying_type_t<TOptions> Options = EOptionNone; const char* ExecutableName = …; const char* binaryFileName = …; const char* depencyFileName = …; const char* entryPointName = …; const char* sourceEntryPointName = …; const char* shaderStageName = …; const char* variableName = …; bool HlslEnable16BitTypes = …; bool HlslDX9compatible = …; bool HlslDxPositionW = …; bool EnhancedMsgs = …; bool AbsolutePath = …; bool DumpBuiltinSymbols = …; std::vector<std::string> IncludeDirectoryList; // Source environment // (source 'Client' is currently the same as target 'Client') int ClientInputSemanticsVersion = …; // Target environment glslang::EShClient Client = …; // will stay EShClientNone if only validating glslang::EShTargetClientVersion ClientVersion; // not valid until Client is set glslang::EShTargetLanguage TargetLanguage = …; glslang::EShTargetLanguageVersion TargetVersion; // not valid until TargetLanguage is set // GLSL version int GlslVersion = …; // GLSL version specified on CLI, overrides #version in shader source std::vector<std::string> Processes; // what should be recorded by OpModuleProcessed, or equivalent // Per descriptor-set binding base data TPerSetBaseBinding; std::vector<std::pair<std::string, int>> uniformLocationOverrides; int uniformBase = …; std::array<std::array<unsigned int, EShLangCount>, glslang::EResCount> baseBinding; std::array<std::array<TPerSetBaseBinding, EShLangCount>, glslang::EResCount> baseBindingForSet; std::array<std::vector<std::string>, EShLangCount> baseResourceSetBinding; std::vector<std::pair<std::string, glslang::TBlockStorageClass>> blockStorageOverrides; bool setGlobalUniformBlock = …; std::string globalUniformName; unsigned int globalUniformBinding; unsigned int globalUniformSet; bool setGlobalBufferBlock = …; std::string atomicCounterBlockName; unsigned int atomicCounterBlockSet; // Add things like "#define ..." to a preamble to use in the beginning of the shader. class TPreamble { … }; // Track the user's #define and #undef from the command line. TPreamble UserPreamble; std::string PreambleString; // // Create the default name for saving a binary if -o is not provided. // const char* GetBinaryName(EShLanguage stage) { … } // // *.conf => this is a config file that can set limits/resources // bool SetConfigFile(const std::string& name) { … } // // Give error and exit with failure code. // void Error(const char* message, const char* detail = nullptr) { … } // // Process an optional binding base of one the forms: // --argname [stage] base // base for stage (if given) or all stages (if not) // --argname [stage] [base set]... // set/base pairs: set the base for given binding set. // Where stage is one of the forms accepted by FindLanguage, and base is an integer // void ProcessBindingBase(int& argc, char**& argv, glslang::TResourceType res) { … } void ProcessResourceSetBindingBase(int& argc, char**& argv, std::array<std::vector<std::string>, EShLangCount>& base) { … } // // Process an optional binding base of one the forms: // --argname name {uniform|buffer|push_constant} void ProcessBlockStorage(int& argc, char**& argv, std::vector<std::pair<std::string, glslang::TBlockStorageClass>>& storage) { … } inline bool isNonDigit(char c) { … } // whether string isa valid identifier to be used in glsl bool isValidIdentifier(const char* str) { … } // Process settings for either the global buffer block or global unfirom block // of the form: // --argname name set binding void ProcessGlobalBlockSettings(int& argc, char**& argv, std::string* name, unsigned int* set, unsigned int* binding) { … } // // Do all command-line argument parsing. This includes building up the work-items // to be processed later, and saving all the command-line options. // // Does not return (it exits) if command-line is fatally flawed. // void ProcessArguments(std::vector<std::unique_ptr<glslang::TWorkItem>>& workItems, int argc, char* argv[]) { … } // // Translate the meaningful subset of command-line options to parser-behavior options. // void SetMessageOptions(EShMessages& messages) { … } // // Thread entry point, for non-linking asynchronous mode. // void CompileShaders(glslang::TWorklist& worklist) { … } // Outputs the given string, but only if it is non-null and non-empty. // This prevents erroneous newlines from appearing. void PutsIfNonEmpty(const char* str) { … } // Outputs the given string to stderr, but only if it is non-null and non-empty. // This prevents erroneous newlines from appearing. void StderrIfNonEmpty(const char* str) { … } // Simple bundling of what makes a compilation unit for ease in passing around, // and separation of handling file IO versus API (programmatic) compilation. struct ShaderCompUnit { … }; // Writes a string into a depfile, escaping some special characters following the Makefile rules. static void writeEscapedDepString(std::ofstream& file, const std::string& str) { … } // Writes a depfile similar to gcc -MMD foo.c bool writeDepFile(std::string depfile, std::vector<std::string>& binaryFiles, const std::vector<std::string>& sources) { … } // // For linking mode: Will independently parse each compilation unit, but then put them // in the same program and link them together, making at most one linked module per // pipeline stage. // // Uses the new C++ interface instead of the old handle-based interface. // void CompileAndLinkShaderUnits(std::vector<ShaderCompUnit> compUnits) { … } // // Do file IO part of compile and link, handing off the pure // API/programmatic mode to CompileAndLinkShaderUnits(), which can // be put in a loop for testing memory footprint and performance. // // This is just for linking mode: meaning all the shaders will be put into the // the same program linked together. // // This means there are a limited number of work items (not multi-threading mode) // and that the point is testing at the linking level. Hence, to enable // performance and memory testing, the actual compile/link can be put in // a loop, independent of processing the work items and file IO. // void CompileAndLinkShaderFiles(glslang::TWorklist& Worklist) { … } int singleMain() { … } int C_DECL main(int argc, char* argv[]) { … } // // Deduce the language from the filename. Files must end in one of the // following extensions: // // .vert = vertex // .tesc = tessellation control // .tese = tessellation evaluation // .geom = geometry // .frag = fragment // .comp = compute // .rgen = ray generation // .rint = ray intersection // .rahit = ray any hit // .rchit = ray closest hit // .rmiss = ray miss // .rcall = ray callable // .mesh = mesh // .task = task // Additionally, the file names may end in .<stage>.glsl and .<stage>.hlsl // where <stage> is one of the stages listed above. // EShLanguage FindLanguage(const std::string& name, bool parseStageName) { … } // // Read a file's data into a string, and compile it using the old interface ShCompile, // for non-linkable results. // void CompileFile(const char* fileName, ShHandle compiler) { … } // // print usage to stdout // void usage() { … } #if !defined _MSC_VER && !defined MINGW_HAS_SECURE_API #include <errno.h> int fopen_s( FILE** pFile, const char* filename, const char* mode ) { … } #endif // // Malloc a string of sufficient size and read a string into it. // char* ReadFileData(const char* fileName) { … } void FreeFileData(char* data) { … } void InfoLogMsg(const char* msg, const char* name, const int num) { … }