diff --git a/Android.mk b/Android.mk index 524afe8cba..98b7f4658f 100644 --- a/Android.mk +++ b/Android.mk @@ -1,5 +1,23 @@ LOCAL_PATH := $(call my-dir) +# Generate glslang/build_info.h +GLSLANG_GENERATED_INCLUDEDIR:=$(TARGET_OUT)/include +GLSLANG_BUILD_INFO_H:=$(GLSLANG_GENERATED_INCLUDEDIR)/glslang/build_info.h + +define gen_glslang_build_info_h +$(call generate-file-dir,$(GLSLANG_GENERATED_INCLUDEDIR)/dummy_filename) +$(GLSLANG_BUILD_INFO_H): \ + $(LOCAL_PATH)/build_info.py \ + $(LOCAL_PATH)/build_info.h.tmpl \ + $(LOCAL_PATH)/CHANGES.md + @$(HOST_PYTHON) $(LOCAL_PATH)/build_info.py \ + $(LOCAL_PATH) \ + -i $(LOCAL_PATH)/build_info.h.tmpl \ + -o $(GLSLANG_BUILD_INFO_H) + @echo "[$(TARGET_ARCH_ABI)] Generate : $(GLSLANG_BUILD_INFO_H) <= CHANGES.md" +endef +$(eval $(call gen_glslang_build_info_h)) + GLSLANG_OS_FLAGS := -DGLSLANG_OSINCLUDE_UNIX # AMD and NV extensions are turned on by default in upstream Glslang. GLSLANG_DEFINES:= -DAMD_EXTENSIONS -DNV_EXTENSIONS -DENABLE_HLSL $(GLSLANG_OS_FLAGS) @@ -22,18 +40,14 @@ LOCAL_C_INCLUDES:=$(LOCAL_PATH)/OGLCompiler LOCAL_STATIC_LIBRARIES:=OSDependent include $(BUILD_STATIC_LIBRARY) -# Build Glslang's HLSL parser library. +# Build the stubbed HLSL library. +# The HLSL source is now directly referenced by the glslang static library +# instead. include $(CLEAR_VARS) LOCAL_MODULE:=HLSL LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES) LOCAL_SRC_FILES:= \ - glslang/HLSL/hlslAttributes.cpp \ - glslang/HLSL/hlslGrammar.cpp \ - glslang/HLSL/hlslOpMap.cpp \ - glslang/HLSL/hlslParseables.cpp \ - glslang/HLSL/hlslParseHelper.cpp \ - glslang/HLSL/hlslScanContext.cpp \ - glslang/HLSL/hlslTokenStream.cpp + hlsl/stub.cpp LOCAL_C_INCLUDES:=$(LOCAL_PATH) \ $(LOCAL_PATH)/glslang/HLSL include $(BUILD_STATIC_LIBRARY) @@ -41,12 +55,23 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) GLSLANG_OUT_PATH=$(if $(call host-path-is-absolute,$(TARGET_OUT)),$(TARGET_OUT),$(abspath $(TARGET_OUT))) +# ShaderLang.cpp depends on the generated build_info.h +$(LOCAL_PATH)/glslang/MachineIndependent/ShaderLang.cpp: \ + $(GLSLANG_BUILD_INFO_H) + LOCAL_MODULE:=glslang LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti $(GLSLANG_DEFINES) LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH) LOCAL_SRC_FILES:= \ glslang/GenericCodeGen/CodeGen.cpp \ glslang/GenericCodeGen/Link.cpp \ + glslang/HLSL/hlslAttributes.cpp \ + glslang/HLSL/hlslGrammar.cpp \ + glslang/HLSL/hlslOpMap.cpp \ + glslang/HLSL/hlslParseables.cpp \ + glslang/HLSL/hlslParseHelper.cpp \ + glslang/HLSL/hlslScanContext.cpp \ + glslang/HLSL/hlslTokenStream.cpp \ glslang/MachineIndependent/attribute.cpp \ glslang/MachineIndependent/Constant.cpp \ glslang/MachineIndependent/glslang_tab.cpp \ @@ -76,14 +101,19 @@ LOCAL_SRC_FILES:= \ glslang/MachineIndependent/preprocessor/PpTokens.cpp LOCAL_C_INCLUDES:=$(LOCAL_PATH) \ $(LOCAL_PATH)/glslang/MachineIndependent \ + $(GLSLANG_GENERATED_INCLUDEDIR) \ $(GLSLANG_OUT_PATH) LOCAL_STATIC_LIBRARIES:=OSDependent OGLCompiler HLSL include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) + +# GlslangToSpv.cpp depends on the generated build_info.h +$(LOCAL_PATH)/glslang/MachineIndependent/GlslangToSpv.cpp: \ + $(GLSLANG_BUILD_INFO_H) + LOCAL_MODULE:=SPIRV LOCAL_CXXFLAGS:=-std=c++11 -fno-exceptions -fno-rtti -Werror $(GLSLANG_DEFINES) -LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH) LOCAL_SRC_FILES:= \ SPIRV/GlslangToSpv.cpp \ SPIRV/InReadableOrder.cpp \ @@ -94,7 +124,9 @@ LOCAL_SRC_FILES:= \ SPIRV/SpvTools.cpp \ SPIRV/disassemble.cpp \ SPIRV/doc.cpp -LOCAL_C_INCLUDES:=$(LOCAL_PATH) $(LOCAL_PATH)/glslang/SPIRV +LOCAL_C_INCLUDES:=$(LOCAL_PATH) \ + $(LOCAL_PATH)/glslang/SPIRV \ + $(GLSLANG_GENERATED_INCLUDEDIR) LOCAL_EXPORT_C_INCLUDES:=$(LOCAL_PATH)/glslang/SPIRV LOCAL_STATIC_LIBRARIES:=glslang include $(BUILD_STATIC_LIBRARY) diff --git a/BUILD.bazel b/BUILD.bazel index 442a94c2a9..b8542ab26c 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -10,6 +10,20 @@ licenses(["notice"]) exports_files(["LICENSE"]) +# Build information generation script +py_binary( + name = "build_info", + srcs = ["build_info.py"], +) + +genrule( + name = "gen_build_info_h", + srcs = ["CHANGES.md", "build_info.h.tmpl"], + outs = ["glslang/build_info.h"], + cmd = "$(location build_info) $$(dirname $(location CHANGES.md)) -i $(location build_info.h.tmpl) -o $(location glslang/build_info.h)", + tools = [":build_info"], +) + COMMON_COPTS = select({ "@bazel_tools//src/conditions:windows": [""], "//conditions:default": [ @@ -62,6 +76,7 @@ cc_library( "StandAlone/DirStackFileIncluder.h", "glslang/OSDependent/osinclude.h", "glslang/Public/ShaderLang.h", + ":gen_build_info_h", ], copts = COMMON_COPTS, defines = [ diff --git a/BUILD.gn b/BUILD.gn index cb44707c70..51babad767 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -46,6 +46,29 @@ if (defined(is_fuchsia_tree) && is_fuchsia_tree) { _configs_to_add = [ "//build/config/compiler:no_chromium_code" ] } +action("glslang_build_info") { + script = "build_info.py" + + src_dir = "." + changes_file = "CHANGES.md" + template_file = "build_info.h.tmpl" + out_file = "${target_gen_dir}/include/glslang/build_info.h" + + inputs = [ + changes_file, + script, + template_file, + ] + outputs = [ + out_file + ] + args = [ + rebase_path(src_dir, root_build_dir), + "-i", rebase_path(template_file, root_build_dir), + "-o", rebase_path(out_file, root_build_dir), + ] +} + spirv_tools_dir = glslang_spirv_tools_dir config("glslang_public") { @@ -114,7 +137,6 @@ source_set("glslang_sources") { "glslang/Include/Types.h", "glslang/Include/arrays.h", "glslang/Include/intermediate.h", - "glslang/Include/revision.h", "glslang/MachineIndependent/Constant.cpp", "glslang/MachineIndependent/InfoSink.cpp", "glslang/MachineIndependent/Initialize.cpp", @@ -194,10 +216,13 @@ source_set("glslang_sources") { } deps = [ + ":glslang_build_info", "${spirv_tools_dir}:spvtools_opt", "${spirv_tools_dir}:spvtools_val", ] + include_dirs = [ "${target_gen_dir}/include" ] + configs -= _configs_to_remove configs += _configs_to_add } @@ -230,6 +255,8 @@ executable("glslang_validator") { ":glslang_sources", ] + include_dirs = [ "${target_gen_dir}/include" ] + configs -= _configs_to_remove configs += _configs_to_add } diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000000..20eefdb781 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,24 @@ +# Revision history for `glslang` + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](https://semver.org/). + +## 10.15.3802-dev 2020-06-16 + +### Breaking changes + +* The following files have been removed: + * `glslang/include/revision.h` + * `glslang/include/revision.template` + +The `GLSLANG_MINOR_VERSION` and `GLSLANG_PATCH_LEVEL` defines have been removed +from the public headers. \ +Instead each build script now uses the new `build_info.py` +script along with the `build_info.h.tmpl` and this `CHANGES.md` file to generate +the glslang build-time generated header `glslang/build_info.h`. + +The new public API to obtain the `glslang` version is `glslang::GetVersion()`. + +### Other changes +* `glslang` shared objects produced by CMake are now `SONAME` versioned using + [Semantic Versioning 2.0.0](https://semver.org/). diff --git a/CMakeLists.txt b/CMakeLists.txt index cbf8378afa..11975e2ff4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,10 +181,49 @@ endfunction(glslang_set_link_args) # CMake needs to find the right version of python, right from the beginning, # otherwise, it will find the wrong version and fail later -if(BUILD_EXTERNAL AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/External) - find_package(PythonInterp 3 REQUIRED) +find_package(PythonInterp 3 REQUIRED) + +# Root directory for build-time generated include files +set(GLSLANG_GENERATED_INCLUDEDIR "${CMAKE_BINARY_DIR}/include") + +################################################################################ +# Build version information generation +################################################################################ +set(GLSLANG_CHANGES_FILE "${CMAKE_SOURCE_DIR}/CHANGES.md") +set(GLSLANG_BUILD_INFO_PY "${CMAKE_SOURCE_DIR}/build_info.py") +set(GLSLANG_BUILD_INFO_H_TMPL "${CMAKE_SOURCE_DIR}/build_info.h.tmpl") +set(GLSLANG_BUILD_INFO_H "${GLSLANG_GENERATED_INCLUDEDIR}/glslang/build_info.h") + +# Command to build the build_info.h file +add_custom_command( + OUTPUT ${GLSLANG_BUILD_INFO_H} + COMMAND ${PYTHON_EXECUTABLE} "${GLSLANG_BUILD_INFO_PY}" + ${CMAKE_CURRENT_SOURCE_DIR} + "-i" ${GLSLANG_BUILD_INFO_H_TMPL} + "-o" ${GLSLANG_BUILD_INFO_H} + DEPENDS ${GLSLANG_BUILD_INFO_PY} + ${GLSLANG_CHANGES_FILE} + ${GLSLANG_BUILD_INFO_H_TMPL} + COMMENT "Generating ${GLSLANG_BUILD_INFO_H}") - # We depend on these for later projects, so they should come first. +# Target to build the build_info.h file +add_custom_target(glslang-build-info DEPENDS ${GLSLANG_BUILD_INFO_H}) + +# Populate the CMake GLSLANG_VERSION* variables with the build version +# information. +execute_process( + COMMAND ${PYTHON_EXECUTABLE} "${GLSLANG_BUILD_INFO_PY}" + ${CMAKE_CURRENT_SOURCE_DIR} "..<-flavor>;;;;" + OUTPUT_VARIABLE "GLSLANG_VERSIONS" + OUTPUT_STRIP_TRAILING_WHITESPACE) +list(GET "GLSLANG_VERSIONS" 0 "GLSLANG_VERSION") +list(GET "GLSLANG_VERSIONS" 1 "GLSLANG_VERSION_MAJOR") +list(GET "GLSLANG_VERSIONS" 2 "GLSLANG_VERSION_MINOR") +list(GET "GLSLANG_VERSIONS" 3 "GLSLANG_VERSION_PATCH") +list(GET "GLSLANG_VERSIONS" 4 "GLSLANG_VERSION_FLAVOR") + +if(BUILD_EXTERNAL AND IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/External) + # We depend on these for later projects, so they should come first. add_subdirectory(External) endif() diff --git a/SPIRV/CMakeLists.txt b/SPIRV/CMakeLists.txt index 5e90086dae..7910a89d7e 100644 --- a/SPIRV/CMakeLists.txt +++ b/SPIRV/CMakeLists.txt @@ -40,7 +40,9 @@ set_property(TARGET SPIRV PROPERTY FOLDER glslang) set_property(TARGET SPIRV PROPERTY POSITION_INDEPENDENT_CODE ON) target_include_directories(SPIRV PUBLIC $ + $ $) +add_dependencies(SPIRV glslang-build-info) if (ENABLE_SPVREMAPPER) add_library(SPVRemapper ${LIB_TYPE} ${SPVREMAP_SOURCES} ${SPVREMAP_HEADERS}) diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 4800c51356..9766063d4a 100644 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -56,7 +56,9 @@ namespace spv { #include "../glslang/MachineIndependent/localintermediate.h" #include "../glslang/MachineIndependent/SymbolTable.h" #include "../glslang/Include/Common.h" -#include "../glslang/Include/revision.h" + +// Build-time generated includes +#include "glslang/build_info.h" #include #include @@ -1613,7 +1615,7 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, case EShLangAnyHit: case EShLangClosestHit: case EShLangMiss: - case EShLangCallable: + case EShLangCallable: { auto& extensions = glslangIntermediate->getRequestedExtensions(); if (extensions.find("GL_NV_ray_tracing") == extensions.end()) { @@ -2194,7 +2196,7 @@ bool TGlslangToSpvTraverser::visitUnary(glslang::TVisit /* visit */, glslang::TI operandNode = node->getOperand()->getAsBinaryNode()->getLeft(); else operandNode = node->getOperand(); - + operandNode->traverse(this); spv::Id operand = spv::NoResult; @@ -3065,7 +3067,7 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt break; case 1: { - OpDecorations decorations = { precision, + OpDecorations decorations = { precision, TranslateNoContractionDecoration(node->getType().getQualifier()), TranslateNonUniformDecoration(node->getType().getQualifier()) }; result = createUnaryOperation( @@ -3186,7 +3188,7 @@ bool TGlslangToSpvTraverser::visitSelection(glslang::TVisit /* visit */, glslang // smear condition to vector, if necessary (AST is always scalar) // Before 1.4, smear like for mix(), starting with 1.4, keep it scalar if (glslangIntermediate->getSpv().spv < glslang::EShTargetSpv_1_4 && builder.isVector(trueValue)) { - condition = builder.smearScalar(spv::NoPrecision, condition, + condition = builder.smearScalar(spv::NoPrecision, condition, builder.makeVectorType(builder.makeBoolType(), builder.getNumComponents(trueValue))); } @@ -5201,10 +5203,10 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO assert(builder.isStructType(resultStructType)); //resType (SPIR-V type) contains 6 elements: - //Member 0 must be a Boolean type scalar(LOD), - //Member 1 must be a vector of integer type, whose Signedness operand is 0(anchor), - //Member 2 must be a vector of integer type, whose Signedness operand is 0(offset), - //Member 3 must be a vector of integer type, whose Signedness operand is 0(mask), + //Member 0 must be a Boolean type scalar(LOD), + //Member 1 must be a vector of integer type, whose Signedness operand is 0(anchor), + //Member 2 must be a vector of integer type, whose Signedness operand is 0(offset), + //Member 3 must be a vector of integer type, whose Signedness operand is 0(mask), //Member 4 must be a scalar of integer type, whose Signedness operand is 0(lod), //Member 5 must be a scalar of integer type, whose Signedness operand is 0(granularity). std::vector members; @@ -5217,7 +5219,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO //call ImageFootprintNV spv::Id res = builder.createTextureCall(precision, resType, sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params, signExtensionMask()); - + //copy resType (SPIR-V type) to resultStructType(OpenGL type) for (int i = 0; i < 5; i++) { builder.clearAccessChain(); @@ -5270,7 +5272,7 @@ spv::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO } #endif - std::vector result( 1, + std::vector result( 1, builder.createTextureCall(precision, resultType(), sparse, cracked.fetch, cracked.proj, cracked.gather, noImplicitLod, params, signExtensionMask()) ); @@ -6750,7 +6752,7 @@ spv::Id TGlslangToSpvTraverser::createAtomicOperation(glslang::TOperator op, spv } else { scopeId = builder.makeUintConstant(spv::ScopeDevice); } - // semantics default to relaxed + // semantics default to relaxed spv::Id semanticsId = builder.makeUintConstant(lvalueCoherentFlags.isVolatile() && glslangIntermediate->usingVulkanMemoryModel() ? spv::MemorySemanticsVolatileMask : @@ -8680,9 +8682,10 @@ void OutputSpvHex(const std::vector& spirv, const char* baseName, out.open(baseName, std::ios::binary | std::ios::out); if (out.fail()) printf("ERROR: Failed to open file: %s\n", baseName); - out << "\t// " << - GetSpirvGeneratorVersion() << "." << GLSLANG_MINOR_VERSION << "." << GLSLANG_PATCH_LEVEL << - std::endl; + out << "\t// " << + GetSpirvGeneratorVersion() << + GLSLANG_VERSION_MAJOR << "." << GLSLANG_VERSION_MINOR << "." << GLSLANG_VERSION_PATCH << + GLSLANG_VERSION_FLAVOR << std::endl; if (varName != nullptr) { out << "\t #pragma once" << std::endl; out << "const uint32_t " << varName << "[] = {" << std::endl; diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp index 5e17affefc..8fe8d3dfaf 100644 --- a/StandAlone/StandAlone.cpp +++ b/StandAlone/StandAlone.cpp @@ -40,67 +40,69 @@ #define _CRT_SECURE_NO_WARNINGS #endif -#include "ResourceLimits.h" -#include "Worklist.h" -#include "DirStackFileIncluder.h" -#include "./../glslang/Include/ShHandle.h" -#include "./../glslang/Include/revision.h" -#include "./../glslang/Public/ShaderLang.h" -#include "../SPIRV/GlslangToSpv.h" #include "../SPIRV/GLSL.std.450.h" -#include "../SPIRV/doc.h" +#include "../SPIRV/GlslangToSpv.h" #include "../SPIRV/disassemble.h" +#include "../SPIRV/doc.h" +#include "./../glslang/Include/ShHandle.h" +#include "./../glslang/Public/ShaderLang.h" +#include "DirStackFileIncluder.h" +#include "ResourceLimits.h" +#include "Worklist.h" -#include -#include +#include #include #include -#include +#include +#include #include #include #include #include "../glslang/OSDependent/osinclude.h" +// Build-time generated includes +#include "glslang/build_info.h" + extern "C" { - SH_IMPORT_EXPORT void ShOutputHtml(); +SH_IMPORT_EXPORT void ShOutputHtml(); } // Command-line options enum TOptions { - EOptionNone = 0, - EOptionIntermediate = (1 << 0), - EOptionSuppressInfolog = (1 << 1), - EOptionMemoryLeakMode = (1 << 2), - EOptionRelaxedErrors = (1 << 3), - EOptionGiveWarnings = (1 << 4), - EOptionLinkProgram = (1 << 5), - EOptionMultiThreaded = (1 << 6), - EOptionDumpConfig = (1 << 7), - EOptionDumpReflection = (1 << 8), - EOptionSuppressWarnings = (1 << 9), - EOptionDumpVersions = (1 << 10), - EOptionSpv = (1 << 11), - EOptionHumanReadableSpv = (1 << 12), - EOptionVulkanRules = (1 << 13), - EOptionDefaultDesktop = (1 << 14), - EOptionOutputPreprocessed = (1 << 15), - EOptionOutputHexadecimal = (1 << 16), - EOptionReadHlsl = (1 << 17), - EOptionCascadingErrors = (1 << 18), - EOptionAutoMapBindings = (1 << 19), + EOptionNone = 0, + EOptionIntermediate = (1 << 0), + EOptionSuppressInfolog = (1 << 1), + EOptionMemoryLeakMode = (1 << 2), + EOptionRelaxedErrors = (1 << 3), + EOptionGiveWarnings = (1 << 4), + EOptionLinkProgram = (1 << 5), + EOptionMultiThreaded = (1 << 6), + EOptionDumpConfig = (1 << 7), + EOptionDumpReflection = (1 << 8), + EOptionSuppressWarnings = (1 << 9), + EOptionDumpVersions = (1 << 10), + EOptionSpv = (1 << 11), + EOptionHumanReadableSpv = (1 << 12), + EOptionVulkanRules = (1 << 13), + EOptionDefaultDesktop = (1 << 14), + EOptionOutputPreprocessed = (1 << 15), + EOptionOutputHexadecimal = (1 << 16), + EOptionReadHlsl = (1 << 17), + EOptionCascadingErrors = (1 << 18), + EOptionAutoMapBindings = (1 << 19), EOptionFlattenUniformArrays = (1 << 20), - EOptionNoStorageFormat = (1 << 21), - EOptionKeepUncalled = (1 << 22), - EOptionHlslOffsets = (1 << 23), - EOptionHlslIoMapping = (1 << 24), - EOptionAutoMapLocations = (1 << 25), - EOptionDebug = (1 << 26), - EOptionStdin = (1 << 27), - EOptionOptimizeDisable = (1 << 28), - EOptionOptimizeSize = (1 << 29), - EOptionInvertY = (1 << 30), - EOptionDumpBareVersion = (1 << 31), + EOptionNoStorageFormat = (1 << 21), + EOptionKeepUncalled = (1 << 22), + EOptionHlslOffsets = (1 << 23), + EOptionHlslIoMapping = (1 << 24), + EOptionAutoMapLocations = (1 << 25), + EOptionDebug = (1 << 26), + EOptionStdin = (1 << 27), + EOptionOptimizeDisable = (1 << 28), + EOptionOptimizeSize = (1 << 29), + EOptionInvertY = (1 << 30), + EOptionDumpBareVersion = (1 << 31), }; bool targetHlslFunctionality1 = false; bool SpvToolsDisassembler = false; @@ -124,7 +126,7 @@ enum TFailCode { // // Forward declarations. // -EShLanguage FindLanguage(const std::string& name, bool parseSuffix=true); +EShLanguage FindLanguage(const std::string& name, bool parseSuffix = true); void CompileFile(const char* fileName, ShHandle); void usage(); char* ReadFileData(const char* fileName); @@ -151,7 +153,7 @@ void ProcessConfigFile() #ifndef GLSLANG_WEB else { char* configString = ReadFileData(ConfigFile.c_str()); - glslang::DecodeResourceLimits(&Resources, configString); + glslang::DecodeResourceLimits(&Resources, configString); FreeFileData(configString); } #endif @@ -175,12 +177,12 @@ std::vector IncludeDirectoryList; int ClientInputSemanticsVersion = 100; // Target environment -glslang::EShClient Client = glslang::EShClientNone; // will stay EShClientNone if only validating -glslang::EShTargetClientVersion ClientVersion; // not valid until Client is set +glslang::EShClient Client = glslang::EShClientNone; // will stay EShClientNone if only validating +glslang::EShTargetClientVersion ClientVersion; // not valid until Client is set glslang::EShTargetLanguage TargetLanguage = glslang::EShTargetNone; -glslang::EShTargetLanguageVersion TargetVersion; // not valid until TargetLanguage is set +glslang::EShTargetLanguageVersion TargetVersion; // not valid until TargetLanguage is set -std::vector Processes; // what should be recorded by OpModuleProcessed, or equivalent +std::vector Processes; // what should be recorded by OpModuleProcessed, or equivalent // Per descriptor-set binding base data typedef std::map TPerSetBaseBinding; @@ -195,7 +197,7 @@ std::array, EShLangCount> baseResourceSetBinding; // Add things like "#define ..." to a preamble to use in the beginning of the shader. class TPreamble { public: - TPreamble() { } + TPreamble() {} bool isSet() const { return text.size() > 0; } const char* get() const { return text.c_str(); } @@ -240,7 +242,7 @@ class TPreamble { line = line.substr(0, end); } - std::string text; // contents of preamble + std::string text; // contents of preamble }; // Track the user's #define and #undef from the command line. @@ -254,21 +256,51 @@ const char* GetBinaryName(EShLanguage stage) const char* name; if (binaryFileName == nullptr) { switch (stage) { - case EShLangVertex: name = "vert.spv"; break; - case EShLangTessControl: name = "tesc.spv"; break; - case EShLangTessEvaluation: name = "tese.spv"; break; - case EShLangGeometry: name = "geom.spv"; break; - case EShLangFragment: name = "frag.spv"; break; - case EShLangCompute: name = "comp.spv"; break; - case EShLangRayGen: name = "rgen.spv"; break; - case EShLangIntersect: name = "rint.spv"; break; - case EShLangAnyHit: name = "rahit.spv"; break; - case EShLangClosestHit: name = "rchit.spv"; break; - case EShLangMiss: name = "rmiss.spv"; break; - case EShLangCallable: name = "rcall.spv"; break; - case EShLangMeshNV: name = "mesh.spv"; break; - case EShLangTaskNV: name = "task.spv"; break; - default: name = "unknown"; break; + case EShLangVertex: + name = "vert.spv"; + break; + case EShLangTessControl: + name = "tesc.spv"; + break; + case EShLangTessEvaluation: + name = "tese.spv"; + break; + case EShLangGeometry: + name = "geom.spv"; + break; + case EShLangFragment: + name = "frag.spv"; + break; + case EShLangCompute: + name = "comp.spv"; + break; + case EShLangRayGen: + name = "rgen.spv"; + break; + case EShLangIntersect: + name = "rint.spv"; + break; + case EShLangAnyHit: + name = "rahit.spv"; + break; + case EShLangClosestHit: + name = "rchit.spv"; + break; + case EShLangMiss: + name = "rmiss.spv"; + break; + case EShLangCallable: + name = "rcall.spv"; + break; + case EShLangMeshNV: + name = "mesh.spv"; + break; + case EShLangTaskNV: + name = "task.spv"; + break; + default: + name = "unknown"; + break; } } else name = binaryFileName; @@ -329,9 +361,9 @@ void ProcessBindingBase(int& argc, char**& argv, glslang::TResourceType res) lang = FindLanguage(argv[arg++], false); } - if ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) { + if ((argc - arg) > 2 && isdigit(argv[arg + 0][0]) && isdigit(argv[arg + 1][0])) { // Parse a per-set binding base - while ((argc - arg) > 2 && isdigit(argv[arg+0][0]) && isdigit(argv[arg+1][0])) { + while ((argc - arg) > 2 && isdigit(argv[arg + 0][0]) && isdigit(argv[arg + 1][0])) { const int baseNum = atoi(argv[arg++]); const int setNum = atoi(argv[arg++]); perSetBase[setNum] = baseNum; @@ -341,12 +373,12 @@ void ProcessBindingBase(int& argc, char**& argv, glslang::TResourceType res) singleBase = atoi(argv[arg++]); } - argc -= (arg-1); - argv += (arg-1); + argc -= (arg - 1); + argv += (arg - 1); // Set one or all languages - const int langMin = (lang < EShLangCount) ? lang+0 : 0; - const int langMax = (lang < EShLangCount) ? lang+1 : EShLangCount; + const int langMin = (lang < EShLangCount) ? lang + 0 : 0; + const int langMax = (lang < EShLangCount) ? lang + 1 : EShLangCount; for (int lang = langMin; lang < langMax; ++lang) { if (!perSetBase.empty()) @@ -385,7 +417,7 @@ void ProcessResourceSetBindingBase(int& argc, char**& argv, std::array>& workItem }; const auto getUniformOverride = [getStringOperand]() { - const char *arg = getStringOperand("-u:"); - const char *split = strchr(arg, ':'); + const char* arg = getStringOperand("-u:"); + const char* split = strchr(arg, ':'); if (split == NULL) { printf("%s: missing location\n", arg); exit(EFailUsage); @@ -473,204 +505,187 @@ void ProcessArguments(std::vector>& workItem for (bumpArg(); argc >= 1; bumpArg()) { if (argv[0][0] == '-') { switch (argv[0][1]) { - case '-': - { - std::string lowerword(argv[0]+2); - std::transform(lowerword.begin(), lowerword.end(), lowerword.begin(), ::tolower); - - // handle --word style options - if (lowerword == "auto-map-bindings" || // synonyms - lowerword == "auto-map-binding" || - lowerword == "amb") { - Options |= EOptionAutoMapBindings; - } else if (lowerword == "auto-map-locations" || // synonyms - lowerword == "aml") { - Options |= EOptionAutoMapLocations; - } else if (lowerword == "uniform-base") { - if (argc <= 1) - Error("no provided", lowerword.c_str()); - uniformBase = ::strtol(argv[1], NULL, 10); - bumpArg(); - break; - } else if (lowerword == "client") { - if (argc > 1) { - if (strcmp(argv[1], "vulkan100") == 0) - setVulkanSpv(); - else if (strcmp(argv[1], "opengl100") == 0) - setOpenGlSpv(); - else - Error("expects vulkan100 or opengl100", lowerword.c_str()); - } else - Error("expects vulkan100 or opengl100", lowerword.c_str()); - bumpArg(); - } else if (lowerword == "define-macro" || - lowerword == "d") { - if (argc > 1) - UserPreamble.addDef(argv[1]); - else - Error("expects ", argv[0]); - bumpArg(); - } else if (lowerword == "dump-builtin-symbols") { - DumpBuiltinSymbols = true; - } else if (lowerword == "entry-point") { - entryPointName = argv[1]; - if (argc <= 1) - Error("no provided", lowerword.c_str()); - bumpArg(); - } else if (lowerword == "flatten-uniform-arrays" || // synonyms - lowerword == "flatten-uniform-array" || - lowerword == "fua") { - Options |= EOptionFlattenUniformArrays; - } else if (lowerword == "hlsl-offsets") { - Options |= EOptionHlslOffsets; - } else if (lowerword == "hlsl-iomap" || - lowerword == "hlsl-iomapper" || - lowerword == "hlsl-iomapping") { - Options |= EOptionHlslIoMapping; - } else if (lowerword == "hlsl-enable-16bit-types") { - HlslEnable16BitTypes = true; - } else if (lowerword == "hlsl-dx9-compatible") { - HlslDX9compatible = true; - } else if (lowerword == "invert-y" || // synonyms - lowerword == "iy") { - Options |= EOptionInvertY; - } else if (lowerword == "keep-uncalled" || // synonyms - lowerword == "ku") { - Options |= EOptionKeepUncalled; - } else if (lowerword == "nan-clamp") { - NaNClamp = true; - } else if (lowerword == "no-storage-format" || // synonyms - lowerword == "nsf") { - Options |= EOptionNoStorageFormat; - } else if (lowerword == "relaxed-errors") { - Options |= EOptionRelaxedErrors; - } else if (lowerword == "reflect-strict-array-suffix") { - ReflectOptions |= EShReflectionStrictArraySuffix; - } else if (lowerword == "reflect-basic-array-suffix") { - ReflectOptions |= EShReflectionBasicArraySuffix; - } else if (lowerword == "reflect-intermediate-io") { - ReflectOptions |= EShReflectionIntermediateIO; - } else if (lowerword == "reflect-separate-buffers") { - ReflectOptions |= EShReflectionSeparateBuffers; - } else if (lowerword == "reflect-all-block-variables") { - ReflectOptions |= EShReflectionAllBlockVariables; - } else if (lowerword == "reflect-unwrap-io-blocks") { - ReflectOptions |= EShReflectionUnwrapIOBlocks; - } else if (lowerword == "reflect-all-io-variables") { - ReflectOptions |= EShReflectionAllIOVariables; - } else if (lowerword == "reflect-shared-std140-ubo") { - ReflectOptions |= EShReflectionSharedStd140UBO; - } else if (lowerword == "reflect-shared-std140-ssbo") { - ReflectOptions |= EShReflectionSharedStd140SSBO; - } else if (lowerword == "resource-set-bindings" || // synonyms - lowerword == "resource-set-binding" || - lowerword == "rsb") { - ProcessResourceSetBindingBase(argc, argv, baseResourceSetBinding); - } else if (lowerword == "shift-image-bindings" || // synonyms - lowerword == "shift-image-binding" || - lowerword == "sib") { - ProcessBindingBase(argc, argv, glslang::EResImage); - } else if (lowerword == "shift-sampler-bindings" || // synonyms - lowerword == "shift-sampler-binding" || - lowerword == "ssb") { - ProcessBindingBase(argc, argv, glslang::EResSampler); - } else if (lowerword == "shift-uav-bindings" || // synonyms - lowerword == "shift-uav-binding" || - lowerword == "suavb") { - ProcessBindingBase(argc, argv, glslang::EResUav); - } else if (lowerword == "shift-texture-bindings" || // synonyms - lowerword == "shift-texture-binding" || - lowerword == "stb") { - ProcessBindingBase(argc, argv, glslang::EResTexture); - } else if (lowerword == "shift-ubo-bindings" || // synonyms - lowerword == "shift-ubo-binding" || - lowerword == "shift-cbuffer-bindings" || - lowerword == "shift-cbuffer-binding" || - lowerword == "sub" || - lowerword == "scb") { - ProcessBindingBase(argc, argv, glslang::EResUbo); - } else if (lowerword == "shift-ssbo-bindings" || // synonyms - lowerword == "shift-ssbo-binding" || - lowerword == "sbb") { - ProcessBindingBase(argc, argv, glslang::EResSsbo); - } else if (lowerword == "source-entrypoint" || // synonyms - lowerword == "sep") { - if (argc <= 1) - Error("no provided", lowerword.c_str()); - sourceEntryPointName = argv[1]; - bumpArg(); - break; - } else if (lowerword == "spirv-dis") { - SpvToolsDisassembler = true; - } else if (lowerword == "spirv-val") { - SpvToolsValidate = true; - } else if (lowerword == "stdin") { - Options |= EOptionStdin; - shaderStageName = argv[1]; - } else if (lowerword == "suppress-warnings") { - Options |= EOptionSuppressWarnings; - } else if (lowerword == "target-env") { - if (argc > 1) { - if (strcmp(argv[1], "vulkan1.0") == 0) { - setVulkanSpv(); - ClientVersion = glslang::EShTargetVulkan_1_0; - } else if (strcmp(argv[1], "vulkan1.1") == 0) { - setVulkanSpv(); - ClientVersion = glslang::EShTargetVulkan_1_1; - } else if (strcmp(argv[1], "vulkan1.2") == 0) { - setVulkanSpv(); - ClientVersion = glslang::EShTargetVulkan_1_2; - } else if (strcmp(argv[1], "opengl") == 0) { - setOpenGlSpv(); - ClientVersion = glslang::EShTargetOpenGL_450; - } else if (strcmp(argv[1], "spirv1.0") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_0; - } else if (strcmp(argv[1], "spirv1.1") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_1; - } else if (strcmp(argv[1], "spirv1.2") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_2; - } else if (strcmp(argv[1], "spirv1.3") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_3; - } else if (strcmp(argv[1], "spirv1.4") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_4; - } else if (strcmp(argv[1], "spirv1.5") == 0) { - TargetLanguage = glslang::EShTargetSpv; - TargetVersion = glslang::EShTargetSpv_1_5; - } else - Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2, opengl,\n" - "spirv1.0, spirv1.1, spirv1.2, spirv1.3, spirv1.4, or spirv1.5"); - } - bumpArg(); - } else if (lowerword == "undef-macro" || - lowerword == "u") { - if (argc > 1) - UserPreamble.addUndef(argv[1]); + case '-': { + std::string lowerword(argv[0] + 2); + std::transform(lowerword.begin(), lowerword.end(), lowerword.begin(), ::tolower); + + // handle --word style options + if (lowerword == "auto-map-bindings" || // synonyms + lowerword == "auto-map-binding" || lowerword == "amb") { + Options |= EOptionAutoMapBindings; + } else if (lowerword == "auto-map-locations" || // synonyms + lowerword == "aml") { + Options |= EOptionAutoMapLocations; + } else if (lowerword == "uniform-base") { + if (argc <= 1) + Error("no provided", lowerword.c_str()); + uniformBase = ::strtol(argv[1], NULL, 10); + bumpArg(); + break; + } else if (lowerword == "client") { + if (argc > 1) { + if (strcmp(argv[1], "vulkan100") == 0) + setVulkanSpv(); + else if (strcmp(argv[1], "opengl100") == 0) + setOpenGlSpv(); else - Error("expects ", argv[0]); - bumpArg(); - } else if (lowerword == "variable-name" || // synonyms - lowerword == "vn") { - Options |= EOptionOutputHexadecimal; - if (argc <= 1) - Error("no provided", lowerword.c_str()); - variableName = argv[1]; - bumpArg(); - break; - } else if (lowerword == "version") { - Options |= EOptionDumpVersions; - } else if (lowerword == "help") { - usage(); - break; - } else { - Error("unrecognized command-line option", argv[0]); + Error("expects vulkan100 or opengl100", lowerword.c_str()); + } else + Error("expects vulkan100 or opengl100", lowerword.c_str()); + bumpArg(); + } else if (lowerword == "define-macro" || lowerword == "d") { + if (argc > 1) + UserPreamble.addDef(argv[1]); + else + Error("expects ", argv[0]); + bumpArg(); + } else if (lowerword == "dump-builtin-symbols") { + DumpBuiltinSymbols = true; + } else if (lowerword == "entry-point") { + entryPointName = argv[1]; + if (argc <= 1) + Error("no provided", lowerword.c_str()); + bumpArg(); + } else if (lowerword == "flatten-uniform-arrays" || // synonyms + lowerword == "flatten-uniform-array" || lowerword == "fua") { + Options |= EOptionFlattenUniformArrays; + } else if (lowerword == "hlsl-offsets") { + Options |= EOptionHlslOffsets; + } else if (lowerword == "hlsl-iomap" || lowerword == "hlsl-iomapper" || lowerword == "hlsl-iomapping") { + Options |= EOptionHlslIoMapping; + } else if (lowerword == "hlsl-enable-16bit-types") { + HlslEnable16BitTypes = true; + } else if (lowerword == "hlsl-dx9-compatible") { + HlslDX9compatible = true; + } else if (lowerword == "invert-y" || // synonyms + lowerword == "iy") { + Options |= EOptionInvertY; + } else if (lowerword == "keep-uncalled" || // synonyms + lowerword == "ku") { + Options |= EOptionKeepUncalled; + } else if (lowerword == "nan-clamp") { + NaNClamp = true; + } else if (lowerword == "no-storage-format" || // synonyms + lowerword == "nsf") { + Options |= EOptionNoStorageFormat; + } else if (lowerword == "relaxed-errors") { + Options |= EOptionRelaxedErrors; + } else if (lowerword == "reflect-strict-array-suffix") { + ReflectOptions |= EShReflectionStrictArraySuffix; + } else if (lowerword == "reflect-basic-array-suffix") { + ReflectOptions |= EShReflectionBasicArraySuffix; + } else if (lowerword == "reflect-intermediate-io") { + ReflectOptions |= EShReflectionIntermediateIO; + } else if (lowerword == "reflect-separate-buffers") { + ReflectOptions |= EShReflectionSeparateBuffers; + } else if (lowerword == "reflect-all-block-variables") { + ReflectOptions |= EShReflectionAllBlockVariables; + } else if (lowerword == "reflect-unwrap-io-blocks") { + ReflectOptions |= EShReflectionUnwrapIOBlocks; + } else if (lowerword == "reflect-all-io-variables") { + ReflectOptions |= EShReflectionAllIOVariables; + } else if (lowerword == "reflect-shared-std140-ubo") { + ReflectOptions |= EShReflectionSharedStd140UBO; + } else if (lowerword == "reflect-shared-std140-ssbo") { + ReflectOptions |= EShReflectionSharedStd140SSBO; + } else if (lowerword == "resource-set-bindings" || // synonyms + lowerword == "resource-set-binding" || lowerword == "rsb") { + ProcessResourceSetBindingBase(argc, argv, baseResourceSetBinding); + } else if (lowerword == "shift-image-bindings" || // synonyms + lowerword == "shift-image-binding" || lowerword == "sib") { + ProcessBindingBase(argc, argv, glslang::EResImage); + } else if (lowerword == "shift-sampler-bindings" || // synonyms + lowerword == "shift-sampler-binding" || lowerword == "ssb") { + ProcessBindingBase(argc, argv, glslang::EResSampler); + } else if (lowerword == "shift-uav-bindings" || // synonyms + lowerword == "shift-uav-binding" || lowerword == "suavb") { + ProcessBindingBase(argc, argv, glslang::EResUav); + } else if (lowerword == "shift-texture-bindings" || // synonyms + lowerword == "shift-texture-binding" || lowerword == "stb") { + ProcessBindingBase(argc, argv, glslang::EResTexture); + } else if (lowerword == "shift-ubo-bindings" || // synonyms + lowerword == "shift-ubo-binding" || lowerword == "shift-cbuffer-bindings" || + lowerword == "shift-cbuffer-binding" || lowerword == "sub" || lowerword == "scb") { + ProcessBindingBase(argc, argv, glslang::EResUbo); + } else if (lowerword == "shift-ssbo-bindings" || // synonyms + lowerword == "shift-ssbo-binding" || lowerword == "sbb") { + ProcessBindingBase(argc, argv, glslang::EResSsbo); + } else if (lowerword == "source-entrypoint" || // synonyms + lowerword == "sep") { + if (argc <= 1) + Error("no provided", lowerword.c_str()); + sourceEntryPointName = argv[1]; + bumpArg(); + break; + } else if (lowerword == "spirv-dis") { + SpvToolsDisassembler = true; + } else if (lowerword == "spirv-val") { + SpvToolsValidate = true; + } else if (lowerword == "stdin") { + Options |= EOptionStdin; + shaderStageName = argv[1]; + } else if (lowerword == "suppress-warnings") { + Options |= EOptionSuppressWarnings; + } else if (lowerword == "target-env") { + if (argc > 1) { + if (strcmp(argv[1], "vulkan1.0") == 0) { + setVulkanSpv(); + ClientVersion = glslang::EShTargetVulkan_1_0; + } else if (strcmp(argv[1], "vulkan1.1") == 0) { + setVulkanSpv(); + ClientVersion = glslang::EShTargetVulkan_1_1; + } else if (strcmp(argv[1], "vulkan1.2") == 0) { + setVulkanSpv(); + ClientVersion = glslang::EShTargetVulkan_1_2; + } else if (strcmp(argv[1], "opengl") == 0) { + setOpenGlSpv(); + ClientVersion = glslang::EShTargetOpenGL_450; + } else if (strcmp(argv[1], "spirv1.0") == 0) { + TargetLanguage = glslang::EShTargetSpv; + TargetVersion = glslang::EShTargetSpv_1_0; + } else if (strcmp(argv[1], "spirv1.1") == 0) { + TargetLanguage = glslang::EShTargetSpv; + TargetVersion = glslang::EShTargetSpv_1_1; + } else if (strcmp(argv[1], "spirv1.2") == 0) { + TargetLanguage = glslang::EShTargetSpv; + TargetVersion = glslang::EShTargetSpv_1_2; + } else if (strcmp(argv[1], "spirv1.3") == 0) { + TargetLanguage = glslang::EShTargetSpv; + TargetVersion = glslang::EShTargetSpv_1_3; + } else if (strcmp(argv[1], "spirv1.4") == 0) { + TargetLanguage = glslang::EShTargetSpv; + TargetVersion = glslang::EShTargetSpv_1_4; + } else if (strcmp(argv[1], "spirv1.5") == 0) { + TargetLanguage = glslang::EShTargetSpv; + TargetVersion = glslang::EShTargetSpv_1_5; + } else + Error("--target-env expected one of: vulkan1.0, vulkan1.1, vulkan1.2, opengl,\n" + "spirv1.0, spirv1.1, spirv1.2, spirv1.3, spirv1.4, or spirv1.5"); } + bumpArg(); + } else if (lowerword == "undef-macro" || lowerword == "u") { + if (argc > 1) + UserPreamble.addUndef(argv[1]); + else + Error("expects ", argv[0]); + bumpArg(); + } else if (lowerword == "variable-name" || // synonyms + lowerword == "vn") { + Options |= EOptionOutputHexadecimal; + if (argc <= 1) + Error("no provided", lowerword.c_str()); + variableName = argv[1]; + bumpArg(); + break; + } else if (lowerword == "version") { + Options |= EOptionDumpVersions; + } else if (lowerword == "help") { + usage(); + break; + } else { + Error("unrecognized command-line option", argv[0]); } - break; + } break; case 'C': Options |= EOptionCascadingErrors; break; @@ -804,7 +819,7 @@ void ProcessArguments(std::vector>& workItem } } else { std::string name(argv[0]); - if (! SetConfigFile(name)) { + if (!SetConfigFile(name)) { workItems.push_back(std::unique_ptr(new glslang::TWorkItem(name))); } } @@ -831,8 +846,7 @@ void ProcessArguments(std::vector>& workItem if (binaryFileName && (Options & EOptionSpv) == 0) Error("no binary generation requested (e.g., -V)"); - if ((Options & EOptionFlattenUniformArrays) != 0 && - (Options & EOptionReadHlsl) == 0) + if ((Options & EOptionFlattenUniformArrays) != 0 && (Options & EOptionReadHlsl) == 0) Error("uniform array flattening only valid when compiling HLSL source."); // rationalize client and target language @@ -916,7 +930,7 @@ void CompileShaders(glslang::TWorklist& worklist) CompileFile("stdin", compiler); - if (! (Options & EOptionSuppressInfolog)) + if (!(Options & EOptionSuppressInfolog)) workItem->results = ShGetInfoLog(compiler); ShDestruct(compiler); @@ -929,7 +943,7 @@ void CompileShaders(glslang::TWorklist& worklist) CompileFile(workItem->name.c_str(), compiler); - if (! (Options & EOptionSuppressInfolog)) + if (!(Options & EOptionSuppressInfolog)) workItem->results = ShGetInfoLog(compiler); ShDestruct(compiler); @@ -964,7 +978,7 @@ struct ShaderCompUnit { std::string fileName[maxCount]; // hold's the memory, but... const char* fileNameList[maxCount]; // downstream interface wants pointers - ShaderCompUnit(EShLanguage stage) : stage(stage), count(0) { } + ShaderCompUnit(EShLanguage stage) : stage(stage), count(0) {} ShaderCompUnit(const ShaderCompUnit& rhs) { @@ -1009,7 +1023,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) glslang::TProgram& program = *new glslang::TProgram; for (auto it = compUnits.cbegin(); it != compUnits.cend(); ++it) { - const auto &compUnit = *it; + const auto& compUnit = *it; glslang::TShader* shader = new glslang::TShader(compUnit.stage); shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, compUnit.count); if (entryPointName) @@ -1048,8 +1062,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) shader->setAutoMapLocations(true); for (auto& uniOverride : uniformLocationOverrides) { - shader->addUniformLocationOverride(uniOverride.first.c_str(), - uniOverride.second); + shader->addUniformLocationOverride(uniOverride.first.c_str(), uniOverride.second); } shader->setUniformLocationBase(uniformBase); @@ -1069,8 +1082,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) // Set up the environment, some subsettings take precedence over earlier // ways of setting things. if (Options & EOptionSpv) { - shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl - : glslang::EShSourceGlsl, + shader->setEnvInput((Options & EOptionReadHlsl) ? glslang::EShSourceHlsl : glslang::EShSourceGlsl, compUnit.stage, Client, ClientInputSemanticsVersion); shader->setEnvClient(Client, ClientVersion); shader->setEnvTarget(TargetLanguage, TargetVersion); @@ -1085,8 +1097,8 @@ void CompileAndLinkShaderUnits(std::vector compUnits) const int defaultVersion = Options & EOptionDefaultDesktop ? 110 : 100; DirStackFileIncluder includer; - std::for_each(IncludeDirectoryList.rbegin(), IncludeDirectoryList.rend(), [&includer](const std::string& dir) { - includer.pushExternalLocalDirectory(dir); }); + std::for_each(IncludeDirectoryList.rbegin(), IncludeDirectoryList.rend(), + [&includer](const std::string& dir) { includer.pushExternalLocalDirectory(dir); }); #ifndef GLSLANG_WEB if (Options & EOptionOutputPreprocessed) { std::string str; @@ -1101,13 +1113,12 @@ void CompileAndLinkShaderUnits(std::vector compUnits) } #endif - if (! shader->parse(&Resources, defaultVersion, false, messages, includer)) + if (!shader->parse(&Resources, defaultVersion, false, messages, includer)) CompileFailed = true; program.addShader(shader); - if (! (Options & EOptionSuppressInfolog) && - ! (Options & EOptionMemoryLeakMode)) { + if (!(Options & EOptionSuppressInfolog) && !(Options & EOptionMemoryLeakMode)) { PutsIfNonEmpty(compUnit.fileName[0].c_str()); PutsIfNonEmpty(shader->getInfoLog()); PutsIfNonEmpty(shader->getInfoDebugLog()); @@ -1119,7 +1130,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) // // Link - if (! (Options & EOptionOutputPreprocessed) && ! program.link(messages)) + if (!(Options & EOptionOutputPreprocessed) && !program.link(messages)) LinkFailed = true; #ifndef GLSLANG_WEB @@ -1131,8 +1142,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) #endif // Report - if (! (Options & EOptionSuppressInfolog) && - ! (Options & EOptionMemoryLeakMode)) { + if (!(Options & EOptionSuppressInfolog) && !(Options & EOptionMemoryLeakMode)) { PutsIfNonEmpty(program.getInfoLog()); PutsIfNonEmpty(program.getInfoDebugLog()); } @@ -1167,7 +1177,7 @@ void CompileAndLinkShaderUnits(std::vector compUnits) // Dump the spv to a file or stdout, etc., but only if not doing // memory/perf testing, as it's not internal to programmatic use. - if (! (Options & EOptionMemoryLeakMode)) { + if (!(Options & EOptionMemoryLeakMode)) { printf("%s", logger.getAllMessages().c_str()); if (Options & EOptionOutputHexadecimal) { glslang::OutputSpvHex(spirv, GetBinaryName((EShLanguage)stage), variableName); @@ -1245,7 +1255,7 @@ void CompileAndLinkShaderFiles(glslang::TWorklist& Worklist) // all the perf/memory that a programmatic consumer will care about. for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) { for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) - CompileAndLinkShaderUnits(compUnits); + CompileAndLinkShaderUnits(compUnits); if (Options & EOptionMemoryLeakMode) glslang::OS_DumpMemoryCounters(); @@ -1274,13 +1284,13 @@ int singleMain() #endif if (Options & EOptionDumpBareVersion) { - printf("%d.%d.%d\n", - glslang::GetSpirvGeneratorVersion(), GLSLANG_MINOR_VERSION, GLSLANG_PATCH_LEVEL); + printf("%d:%d.%d.%d%s\n", glslang::GetSpirvGeneratorVersion(), GLSLANG_VERSION_MAJOR, GLSLANG_VERSION_MINOR, + GLSLANG_VERSION_PATCH, GLSLANG_VERSION_FLAVOR); if (workList.empty()) return ESuccess; } else if (Options & EOptionDumpVersions) { - printf("Glslang Version: %d.%d.%d\n", - glslang::GetSpirvGeneratorVersion(), GLSLANG_MINOR_VERSION, GLSLANG_PATCH_LEVEL); + printf("Glslang Version: %d:%d.%d.%d%s\n", glslang::GetSpirvGeneratorVersion(), GLSLANG_VERSION_MAJOR, + GLSLANG_VERSION_MINOR, GLSLANG_VERSION_PATCH, GLSLANG_VERSION_FLAVOR); printf("ESSL Version: %s\n", glslang::GetEsslVersionString()); printf("GLSL Version: %s\n", glslang::GetGlslVersionString()); std::string spirvVersion; @@ -1316,16 +1326,16 @@ int singleMain() // if (Options & (EOptionLinkProgram | EOptionOutputPreprocessed)) { glslang::InitializeProcess(); - glslang::InitializeProcess(); // also test reference counting of users - glslang::InitializeProcess(); // also test reference counting of users - glslang::FinalizeProcess(); // also test reference counting of users - glslang::FinalizeProcess(); // also test reference counting of users + glslang::InitializeProcess(); // also test reference counting of users + glslang::InitializeProcess(); // also test reference counting of users + glslang::FinalizeProcess(); // also test reference counting of users + glslang::FinalizeProcess(); // also test reference counting of users CompileAndLinkShaderFiles(workList); glslang::FinalizeProcess(); } else { ShInitialize(); - ShInitialize(); // also test reference counting of users - ShFinalize(); // also test reference counting of users + ShInitialize(); // also test reference counting of users + ShFinalize(); // also test reference counting of users bool printShaderNames = workList.size() > 1; @@ -1493,7 +1503,8 @@ void CompileFile(const char* fileName, ShHandle compiler) for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) { for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) { // ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); - ret = ShCompile(compiler, &shaderString, 1, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); + ret = ShCompile(compiler, &shaderString, 1, nullptr, EShOptNone, &Resources, Options, + (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages); // const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err", // "or should be l", "ine 1", "string 5\n", "float glo", "bal", // ";\n#error should be line 2\n void main() {", "global = 2.3;}" }; @@ -1505,7 +1516,7 @@ void CompileFile(const char* fileName, ShHandle compiler) glslang::OS_DumpMemoryCounters(); } - delete [] lengths; + delete[] lengths; FreeFileData(shaderString); if (ret == 0) @@ -1682,8 +1693,7 @@ void usage() " --variable-name \n" " --vn creates a C header file that contains a\n" " uint32_t array named \n" - " initialized with the shader binary code\n" - ); + " initialized with the shader binary code\n"); exit(EFailUsage); } @@ -1692,27 +1702,23 @@ void usage() #include -int fopen_s( - FILE** pFile, - const char* filename, - const char* mode -) +int fopen_s(FILE** pFile, const char* filename, const char* mode) { - if (!pFile || !filename || !mode) { - return EINVAL; - } - - FILE* f = fopen(filename, mode); - if (! f) { - if (errno != 0) { - return errno; - } else { - return ENOENT; - } - } - *pFile = f; - - return 0; + if (!pFile || !filename || !mode) { + return EINVAL; + } + + FILE* f = fopen(filename, mode); + if (!f) { + if (errno != 0) { + return errno; + } else { + return ENOENT; + } + } + *pFile = f; + + return 0; } #endif @@ -1722,7 +1728,7 @@ int fopen_s( // char* ReadFileData(const char* fileName) { - FILE *in = nullptr; + FILE* in = nullptr; int errorCode = fopen_s(&in, fileName, "r"); if (errorCode || in == nullptr) Error("unable to open input file"); @@ -1733,7 +1739,7 @@ char* ReadFileData(const char* fileName) fseek(in, 0, SEEK_SET); - char* return_data = (char*)malloc(count + 1); // freed in FreeFileData() + char* return_data = (char*)malloc(count + 1); // freed in FreeFileData() if ((int)fread(return_data, 1, count, in) != count) { free(return_data); Error("can't read input file"); @@ -1745,14 +1751,11 @@ char* ReadFileData(const char* fileName) return return_data; } -void FreeFileData(char* data) -{ - free(data); -} +void FreeFileData(char* data) { free(data); } void InfoLogMsg(const char* msg, const char* name, const int num) { - if (num >= 0 ) + if (num >= 0) printf("#### %s %s %d INFO LOG ####\n", msg, name, num); else printf("#### %s %s INFO LOG ####\n", msg, name); diff --git a/build_info.h.tmpl b/build_info.h.tmpl new file mode 100644 index 0000000000..a73f3c3013 --- /dev/null +++ b/build_info.h.tmpl @@ -0,0 +1,29 @@ +#ifndef GLSLANG_BUILD_INFO +#define GLSLANG_BUILD_INFO + +#define GLSLANG_VERSION_MAJOR +#define GLSLANG_VERSION_MINOR +#define GLSLANG_VERSION_PATCH +#define GLSLANG_VERSION_FLAVOR "" + +#define GLSLANG_VERSION_GREATER_THAN(major, minor, patch) \ + (((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \ + (((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \ + ((patch) > GLSLANG_VERSION_PATCH))))) + +#define GLSLANG_VERSION_GREATER_OR_EQUAL_TO(major, minor, patch) \ + (((major) > GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \ + (((minor) > GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \ + ((patch) >= GLSLANG_VERSION_PATCH))))) + +#define GLSLANG_VERSION_LESS_THAN(major, minor, patch) \ + (((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \ + (((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \ + ((patch) < GLSLANG_VERSION_PATCH))))) + +#define GLSLANG_VERSION_LESS_OR_EQUAL_TO(major, minor, patch) \ + (((major) < GLSLANG_VERSION_MAJOR) || ((major) == GLSLANG_VERSION_MAJOR && \ + (((minor) < GLSLANG_VERSION_MINOR) || ((minor) == GLSLANG_VERSION_MINOR && \ + ((patch) <= GLSLANG_VERSION_PATCH))))) + +#endif // GLSLANG_BUILD_INFO diff --git a/build_info.py b/build_info.py new file mode 100644 index 0000000000..4806a3e33c --- /dev/null +++ b/build_info.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python + +# Copyright (c) 2020 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import datetime +import errno +import os +import os.path +import re +import subprocess +import sys +import time + +usage = """{} emits a string to stdout or file with project version information. + +args: [] [-i ] [-o ] + +Either or -i needs to be provided. + +The tool will output the provided string or file content with the following +tokens substituted: + + - The major version point parsed from the CHANGES.md file. + - The minor version point parsed from the CHANGES.md file. + - The point version point parsed from the CHANGES.md file. + - The optional dash suffix parsed from the CHANGES.md file (excluding + dash prefix). + <-flavor> - The optional dash suffix parsed from the CHANGES.md file (including + dash prefix). + - The optional date of the release in the form YYYY-MM-DD + - The git commit information for the directory taken from + "git describe" if that succeeds, or "git rev-parse HEAD" + if that succeeds, or otherwise a message containing the phrase + "unknown hash". + +-o is an optional flag for writing the output string to the given file. If + ommitted then the string is printed to stdout. +""" + +def mkdir_p(directory): + """Make the directory, and all its ancestors as required. Any of the + directories are allowed to already exist.""" + + if directory == "": + # We're being asked to make the current directory. + return + + try: + os.makedirs(directory) + except OSError as e: + if e.errno == errno.EEXIST and os.path.isdir(directory): + pass + else: + raise + + +def command_output(cmd, directory): + """Runs a command in a directory and returns its standard output stream. + + Captures the standard error stream. + + Raises a RuntimeError if the command fails to launch or otherwise fails. + """ + p = subprocess.Popen(cmd, + cwd=directory, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + (stdout, _) = p.communicate() + if p.returncode != 0: + raise RuntimeError('Failed to run %s in %s' % (cmd, directory)) + return stdout + + +def deduce_software_version(directory): + """Returns a software version number parsed from the CHANGES.md file + in the given directory. + + The CHANGES.md file describes most recent versions first. + """ + + # Match the first well-formed version-and-date line. + # Allow trailing whitespace in the checked-out source code has + # unexpected carriage returns on a linefeed-only system such as + # Linux. + pattern = re.compile(r'^#*\s+(\d+)\.(\d+)\.(\d+)(-\w+)? (\d\d\d\d-\d\d-\d\d)?\s*$') + changes_file = os.path.join(directory, 'CHANGES.md') + with open(changes_file, mode='r') as f: + for line in f.readlines(): + match = pattern.match(line) + if match: + return { + "major": match.group(1), + "minor": match.group(2), + "patch": match.group(3), + "flavor": match.group(4), + "date": match.group(5), + } + raise Exception('No version number found in {}'.format(changes_file)) + + +def describe(directory): + """Returns a string describing the current Git HEAD version as descriptively + as possible. + + Runs 'git describe', or alternately 'git rev-parse HEAD', in directory. If + successful, returns the output; otherwise returns 'unknown hash, '.""" + try: + # decode() is needed here for Python3 compatibility. In Python2, + # str and bytes are the same type, but not in Python3. + # Popen.communicate() returns a bytes instance, which needs to be + # decoded into text data first in Python3. And this decode() won't + # hurt Python2. + return command_output(['git', 'describe'], directory).rstrip().decode() + except: + try: + return command_output( + ['git', 'rev-parse', 'HEAD'], directory).rstrip().decode() + except: + # This is the fallback case where git gives us no information, + # e.g. because the source tree might not be in a git tree. + # In this case, usually use a timestamp. However, to ensure + # reproducible builds, allow the builder to override the wall + # clock time with environment variable SOURCE_DATE_EPOCH + # containing a (presumably) fixed timestamp. + timestamp = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) + formatted = datetime.datetime.utcfromtimestamp(timestamp).isoformat() + return 'unknown hash, {}'.format(formatted) + +def parse_args(): + directory = None + input_string = None + input_file = None + output_file = None + + if len(sys.argv) < 2: + raise Exception("Invalid number of arguments") + + directory = sys.argv[1] + i = 2 + + if not sys.argv[i].startswith("-"): + input_string = sys.argv[i] + i = i + 1 + + while i < len(sys.argv): + opt = sys.argv[i] + i = i + 1 + + if opt == "-i" or opt == "-o": + if i == len(sys.argv): + raise Exception("Expected path after {}".format(opt)) + val = sys.argv[i] + i = i + 1 + if (opt == "-i"): + input_file = val + elif (opt == "-o"): + output_file = val + else: + raise Exception("Unknown flag {}".format(opt)) + + return { + "directory": directory, + "input_string": input_string, + "input_file": input_file, + "output_file": output_file, + } + +def main(): + args = None + try: + args = parse_args() + except Exception as e: + print(e) + print("\nUsage:\n") + print(usage.format(sys.argv[0])) + sys.exit(1) + + directory = args["directory"] + template = args["input_string"] + if template == None: + with open(args["input_file"], 'r') as f: + template = f.read() + output_file = args["output_file"] + + software_version = deduce_software_version(directory) + commit = describe(directory) + output = template \ + .replace("", software_version["major"]) \ + .replace("", software_version["minor"]) \ + .replace("", software_version["patch"]) \ + .replace("", software_version["flavor"]) \ + .replace("", software_version["date"]) \ + .replace("", commit) + + if output_file is None: + print(output) + else: + mkdir_p(os.path.dirname(output_file)) + + if os.path.isfile(output_file): + with open(output_file, 'r') as f: + if output == f.read(): + return + + with open(output_file, 'w') as f: + f.write(output) + +if __name__ == '__main__': + main() diff --git a/glslang/CMakeLists.txt b/glslang/CMakeLists.txt index e37b9e1375..6b730f2d2d 100644 --- a/glslang/CMakeLists.txt +++ b/glslang/CMakeLists.txt @@ -58,7 +58,6 @@ set(HEADERS Include/intermediate.h Include/PoolAlloc.h Include/ResourceLimits.h - Include/revision.h Include/ShHandle.h Include/Types.h MachineIndependent/attribute.h @@ -104,12 +103,17 @@ if(ENABLE_HLSL) endif(ENABLE_HLSL) add_library(glslang ${LIB_TYPE} ${BISON_GLSLParser_OUTPUT_SOURCE} ${SOURCES} ${HEADERS}) -set_property(TARGET glslang PROPERTY FOLDER glslang) -set_property(TARGET glslang PROPERTY POSITION_INDEPENDENT_CODE ON) +set_target_properties(glslang PROPERTIES + FOLDER glslang + POSITION_INDEPENDENT_CODE ON + VERSION "${GLSLANG_VERSION}" + SOVERSION "${GLSLANG_VERSION_MAJOR}") target_link_libraries(glslang OGLCompiler OSDependent) target_include_directories(glslang PUBLIC $ + $ $) +add_dependencies(glslang glslang-build-info) if(WIN32 AND BUILD_SHARED_LIBS) set_target_properties(glslang PROPERTIES PREFIX "") @@ -136,11 +140,12 @@ if(ENABLE_GLSLANG_INSTALL) ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() install(EXPORT glslangTargets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake) -endif(ENABLE_GLSLANG_INSTALL) -if(ENABLE_GLSLANG_INSTALL) foreach(file ${HEADERS}) get_filename_component(dir ${file} DIRECTORY) install(FILES ${file} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang/${dir}) endforeach() + + install(FILES ${GLSLANG_BUILD_INFO_H} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/glslang) + endif(ENABLE_GLSLANG_INSTALL) diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h deleted file mode 100644 index a99244be39..0000000000 --- a/glslang/Include/revision.h +++ /dev/null @@ -1,3 +0,0 @@ -// This header is generated by the make-revision script. - -#define GLSLANG_PATCH_LEVEL 3802 diff --git a/glslang/Include/revision.template b/glslang/Include/revision.template deleted file mode 100644 index 4a16beeb0f..0000000000 --- a/glslang/Include/revision.template +++ /dev/null @@ -1,13 +0,0 @@ -// The file revision.h should be updated to the latest version, somehow, on -// check-in, if glslang has changed. -// -// revision.template is the source for revision.h when using SubWCRev as the -// method of updating revision.h. You don't have to do it this way, the -// requirement is only that revision.h gets updated. -// -// revision.h is under source control so that not all consumers of glslang -// source have to figure out how to create revision.h just to get a build -// going. However, if it is not updated, it can be a version behind. - -#define GLSLANG_REVISION "$WCREV$" -#define GLSLANG_DATE "$WCDATE$" diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 476d179840..f399f0d03d 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -41,14 +41,14 @@ // This is the platform independent interface between an OGL driver // and the shading language compiler/linker. // -#include -#include -#include -#include -#include "SymbolTable.h" #include "ParseHelper.h" #include "Scan.h" #include "ScanContext.h" +#include "SymbolTable.h" +#include +#include +#include +#include #ifdef ENABLE_HLSL #include "../HLSL/hlslParseHelper.h" @@ -56,22 +56,25 @@ #include "../HLSL/hlslScanContext.h" #endif -#include "../Include/ShHandle.h" #include "../../OGLCompilersDLL/InitializeDll.h" +#include "../Include/ShHandle.h" #include "preprocessor/PpContext.h" #define SH_EXPORTING #include "../Public/ShaderLang.h" -#include "reflection.h" -#include "iomapper.h" #include "Initialize.h" +#include "iomapper.h" +#include "reflection.h" // TODO: this really shouldn't be here, it is only because of the trial addition // of printing pre-processed tokens, which requires knowing the string literal // token to print ", but none of that seems appropriate for this file. #include "preprocessor/PpTokens.h" +// Build-time generated includes +#include "glslang/build_info.h" + namespace { // anonymous namespace for file-local functions and symbols // Total number of successful initializers of glslang: a refcount @@ -84,9 +87,11 @@ using namespace glslang; TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource source) { switch (source) { - case EShSourceGlsl: return new TBuiltIns(); // GLSL builtIns + case EShSourceGlsl: + return new TBuiltIns(); // GLSL builtIns #ifdef ENABLE_HLSL - case EShSourceHlsl: return new TBuiltInParseablesHlsl(); // HLSL intrinsics + case EShSourceHlsl: + return new TBuiltInParseablesHlsl(); // HLSL intrinsics #endif default: @@ -96,9 +101,8 @@ TBuiltInParseables* CreateBuiltInParseables(TInfoSink& infoSink, EShSource sourc } // Create a language specific version of a parse context. -TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& intermediate, - int version, EProfile profile, EShSource source, - EShLanguage language, TInfoSink& infoSink, +TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& intermediate, int version, + EProfile profile, EShSource source, EShLanguage language, TInfoSink& infoSink, SpvVersion spvVersion, bool forwardCompatible, EShMessages messages, bool parsingBuiltIns, std::string sourceEntryPointName = "") { @@ -107,13 +111,13 @@ TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& if (sourceEntryPointName.size() == 0) intermediate.setEntryPointName("main"); TString entryPoint = sourceEntryPointName.c_str(); - return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, - language, infoSink, forwardCompatible, messages, &entryPoint); + return new TParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, language, + infoSink, forwardCompatible, messages, &entryPoint); } #ifdef ENABLE_HLSL case EShSourceHlsl: - return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, - language, infoSink, sourceEntryPointName.c_str(), forwardCompatible, messages); + return new HlslParseContext(symbolTable, intermediate, parsingBuiltIns, version, profile, spvVersion, language, + infoSink, sourceEntryPointName.c_str(), forwardCompatible, messages); #endif default: infoSink.info.message(EPrefixInternalError, "Unable to determine source language"); @@ -123,32 +127,70 @@ TParseContextBase* CreateParseContext(TSymbolTable& symbolTable, TIntermediate& // Local mapping functions for making arrays of symbol tables.... -const int VersionCount = 17; // index range in MapVersionToIndex +const int VersionCount = 17; // index range in MapVersionToIndex int MapVersionToIndex(int version) { int index = 0; switch (version) { - case 100: index = 0; break; - case 110: index = 1; break; - case 120: index = 2; break; - case 130: index = 3; break; - case 140: index = 4; break; - case 150: index = 5; break; - case 300: index = 6; break; - case 330: index = 7; break; - case 400: index = 8; break; - case 410: index = 9; break; - case 420: index = 10; break; - case 430: index = 11; break; - case 440: index = 12; break; - case 310: index = 13; break; - case 450: index = 14; break; - case 500: index = 0; break; // HLSL - case 320: index = 15; break; - case 460: index = 16; break; - default: assert(0); break; + case 100: + index = 0; + break; + case 110: + index = 1; + break; + case 120: + index = 2; + break; + case 130: + index = 3; + break; + case 140: + index = 4; + break; + case 150: + index = 5; + break; + case 300: + index = 6; + break; + case 330: + index = 7; + break; + case 400: + index = 8; + break; + case 410: + index = 9; + break; + case 420: + index = 10; + break; + case 430: + index = 11; + break; + case 440: + index = 12; + break; + case 310: + index = 13; + break; + case 450: + index = 14; + break; + case 500: + index = 0; + break; // HLSL + case 320: + index = 15; + break; + case 460: + index = 16; + break; + default: + assert(0); + break; } assert(index < VersionCount); @@ -156,7 +198,7 @@ int MapVersionToIndex(int version) return index; } -const int SpvVersionCount = 3; // index range in MapSpvVersionToIndex +const int SpvVersionCount = 3; // index range in MapSpvVersionToIndex int MapSpvVersionToIndex(const SpvVersion& spvVersion) { @@ -172,18 +214,27 @@ int MapSpvVersionToIndex(const SpvVersion& spvVersion) return index; } -const int ProfileCount = 4; // index range in MapProfileToIndex +const int ProfileCount = 4; // index range in MapProfileToIndex int MapProfileToIndex(EProfile profile) { int index = 0; switch (profile) { - case ENoProfile: index = 0; break; - case ECoreProfile: index = 1; break; - case ECompatibilityProfile: index = 2; break; - case EEsProfile: index = 3; break; - default: break; + case ENoProfile: + index = 0; + break; + case ECoreProfile: + index = 1; + break; + case ECompatibilityProfile: + index = 2; + break; + case EEsProfile: + index = 3; + break; + default: + break; } assert(index < ProfileCount); @@ -198,9 +249,14 @@ int MapSourceToIndex(EShSource source) int index = 0; switch (source) { - case EShSourceGlsl: index = 0; break; - case EShSourceHlsl: index = 1; break; - default: break; + case EShSourceGlsl: + index = 0; + break; + case EShSourceHlsl: + index = 1; + break; + default: + break; } assert(index < SourceCount); @@ -209,11 +265,7 @@ int MapSourceToIndex(EShSource source) } // only one of these needed for non-ES; ES needs 2 for different precision defaults of built-ins -enum EPrecisionClass { - EPcGeneral, - EPcFragment, - EPcCount -}; +enum EPrecisionClass { EPcGeneral, EPcFragment, EPcCount }; // A process-global symbol table per version per profile for built-ins common // to multiple stages (languages), and a process-global symbol table per version @@ -231,16 +283,16 @@ TPoolAllocator* PerProcessGPA = nullptr; // // Parse and add to the given symbol table the content of the given shader string. // -bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, - EShSource source, TInfoSink& infoSink, TSymbolTable& symbolTable) +bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, const SpvVersion& spvVersion, + EShLanguage language, EShSource source, TInfoSink& infoSink, TSymbolTable& symbolTable) { TIntermediate intermediate(language, version, profile); intermediate.setSource(source); - std::unique_ptr parseContext(CreateParseContext(symbolTable, intermediate, version, profile, source, - language, infoSink, spvVersion, true, EShMsgDefault, - true)); + std::unique_ptr parseContext(CreateParseContext(symbolTable, intermediate, version, profile, + source, language, infoSink, spvVersion, true, + EShMsgDefault, true)); TShader::ForbidIncluder includer; TPpContext ppContext(*parseContext, "", includer); @@ -265,7 +317,7 @@ bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profil return true; TInputScanner input(1, builtInShaders, builtInLengths); - if (! parseContext->parseShaderStrings(ppContext, input) != 0) { + if (!parseContext->parseShaderStrings(ppContext, input) != 0) { infoSink.info.message(EPrefixInternalError, "Unable to parse built-ins"); printf("Unable to parse built-ins\n%s\n", infoSink.info.c_str()); printf("%s\n", builtInShaders[0]); @@ -284,9 +336,9 @@ int CommonIndex(EProfile profile, EShLanguage language) // // To initialize per-stage shared tables, with the common table already complete. // -void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int version, EProfile profile, const SpvVersion& spvVersion, - EShLanguage language, EShSource source, TInfoSink& infoSink, TSymbolTable** commonTable, - TSymbolTable** symbolTables) +void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int version, EProfile profile, + const SpvVersion& spvVersion, EShLanguage language, EShSource source, + TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables) { #ifdef GLSLANG_WEB profile = EEsProfile; @@ -307,7 +359,8 @@ void InitializeStageSymbolTable(TBuiltInParseables& builtInParseables, int versi // Initialize the full set of shareable symbol tables; // The common (cross-stage) and those shareable per-stage. // -bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables, int version, EProfile profile, const SpvVersion& spvVersion, EShSource source) +bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TSymbolTable** symbolTables, int version, + EProfile profile, const SpvVersion& spvVersion, EShSource source) { #ifdef GLSLANG_WEB profile = EEsProfile; @@ -325,21 +378,20 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangVertex, source, infoSink, *commonTable[EPcGeneral]); if (profile == EEsProfile) - InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangFragment, source, - infoSink, *commonTable[EPcFragment]); + InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, EShLangFragment, + source, infoSink, *commonTable[EPcFragment]); // do the per-stage tables // always have vertex and fragment - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangVertex, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangFragment, source, - infoSink, commonTable, symbolTables); + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangVertex, source, infoSink, + commonTable, symbolTables); + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangFragment, source, infoSink, + commonTable, symbolTables); #ifndef GLSLANG_WEB // check for tessellation - if ((profile != EEsProfile && version >= 150) || - (profile == EEsProfile && version >= 310)) { + if ((profile != EEsProfile && version >= 150) || (profile == EEsProfile && version >= 310)) { InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessControl, source, infoSink, commonTable, symbolTables); InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTessEvaluation, source, @@ -347,51 +399,48 @@ bool InitializeSymbolTables(TInfoSink& infoSink, TSymbolTable** commonTable, TS } // check for geometry - if ((profile != EEsProfile && version >= 150) || - (profile == EEsProfile && version >= 310)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source, - infoSink, commonTable, symbolTables); + if ((profile != EEsProfile && version >= 150) || (profile == EEsProfile && version >= 310)) + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangGeometry, source, infoSink, + commonTable, symbolTables); #endif // check for compute - if ((profile != EEsProfile && version >= 420) || - (profile == EEsProfile && version >= 310)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source, - infoSink, commonTable, symbolTables); + if ((profile != EEsProfile && version >= 420) || (profile == EEsProfile && version >= 310)) + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCompute, source, infoSink, + commonTable, symbolTables); // check for ray tracing stages if (profile != EEsProfile && version >= 450) { - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source, - infoSink, commonTable, symbolTables); + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangRayGen, source, infoSink, + commonTable, symbolTables); + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangIntersect, source, infoSink, + commonTable, symbolTables); + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangAnyHit, source, infoSink, + commonTable, symbolTables); InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangClosestHit, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source, - infoSink, commonTable, symbolTables); - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source, - infoSink, commonTable, symbolTables); + infoSink, commonTable, symbolTables); + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMiss, source, infoSink, + commonTable, symbolTables); + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangCallable, source, infoSink, + commonTable, symbolTables); } // check for mesh - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 320)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMeshNV, source, - infoSink, commonTable, symbolTables); + if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangMeshNV, source, infoSink, + commonTable, symbolTables); // check for task - if ((profile != EEsProfile && version >= 450) || - (profile == EEsProfile && version >= 320)) - InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source, - infoSink, commonTable, symbolTables); + if ((profile != EEsProfile && version >= 450) || (profile == EEsProfile && version >= 320)) + InitializeStageSymbolTable(*builtInParseables, version, profile, spvVersion, EShLangTaskNV, source, infoSink, + commonTable, symbolTables); return true; } -bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable& symbolTable, int version, - EProfile profile, const SpvVersion& spvVersion, EShLanguage language, EShSource source) +bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& infoSink, TSymbolTable& symbolTable, + int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, + EShSource source) { std::unique_ptr builtInParseables(CreateBuiltInParseables(infoSink, source)); @@ -399,7 +448,8 @@ bool AddContextSpecificSymbols(const TBuiltInResource* resources, TInfoSink& inf return false; builtInParseables->initialize(*resources, version, profile, spvVersion, language); - InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, language, source, infoSink, symbolTable); + InitializeSymbolTable(builtInParseables->getCommonString(), version, profile, spvVersion, language, source, + infoSink, symbolTable); builtInParseables->identifyBuiltIns(version, profile, spvVersion, language, symbolTable, *resources); return true; @@ -456,18 +506,21 @@ void SetupBuiltinSymbolTable(int version, EProfile profile, const SpvVersion& sp // Copy the local symbol tables from the new pool to the global tables using the process-global pool for (int precClass = 0; precClass < EPcCount; ++precClass) { - if (! commonTable[precClass]->isEmpty()) { + if (!commonTable[precClass]->isEmpty()) { CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass] = new TSymbolTable; - CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->copyTable(*commonTable[precClass]); + CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->copyTable( + *commonTable[precClass]); CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex][precClass]->readOnly(); } } for (int stage = 0; stage < EShLangCount; ++stage) { - if (! stageTables[stage]->isEmpty()) { + if (!stageTables[stage]->isEmpty()) { SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage] = new TSymbolTable; - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->adoptLevels(*CommonSymbolTable - [versionIndex][spvVersionIndex][profileIndex][sourceIndex][CommonIndex(profile, (EShLanguage)stage)]); - SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->copyTable(*stageTables[stage]); + SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->adoptLevels( + *CommonSymbolTable[versionIndex][spvVersionIndex][profileIndex][sourceIndex] + [CommonIndex(profile, (EShLanguage)stage)]); + SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->copyTable( + *stageTables[stage]); SharedSymbolTables[versionIndex][spvVersionIndex][profileIndex][sourceIndex][stage]->readOnly(); } } @@ -519,7 +572,8 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo if (profile == ENoProfile) { if (version == 300 || version == 310 || version == 320) { correct = false; - infoSink.info.message(EPrefixError, "#version: versions 300, 310, and 320 require specifying the 'es' profile"); + infoSink.info.message(EPrefixError, + "#version: versions 300, 310, and 320 require specifying the 'es' profile"); profile = EEsProfile; } else if (version == 100) profile = EEsProfile; @@ -558,25 +612,42 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo // Fix version... switch (version) { // ES versions - case 100: break; - case 300: break; - case 310: break; - case 320: break; + case 100: + break; + case 300: + break; + case 310: + break; + case 320: + break; // desktop versions - case 110: break; - case 120: break; - case 130: break; - case 140: break; - case 150: break; - case 330: break; - case 400: break; - case 410: break; - case 420: break; - case 430: break; - case 440: break; - case 450: break; - case 460: break; + case 110: + break; + case 120: + break; + case 130: + break; + case 140: + break; + case 150: + break; + case 330: + break; + case 400: + break; + case 410: + break; + case 420: + break; + case 430: + break; + case 440: + break; + case 450: + break; + case 460: + break; // unknown version default: @@ -595,10 +666,10 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo // Correct for stage type... switch (stage) { case EShLangGeometry: - if ((profile == EEsProfile && version < 310) || - (profile != EEsProfile && version < 150)) { + if ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 150)) { correct = false; - infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or non-es profile with version 150 or above"); + infoSink.info.message(EPrefixError, "#version: geometry shaders require es profile with version 310 or " + "non-es profile with version 150 or above"); version = (profile == EEsProfile) ? 310 : 150; if (profile == EEsProfile || profile == ENoProfile) profile = ECoreProfile; @@ -606,20 +677,21 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo break; case EShLangTessControl: case EShLangTessEvaluation: - if ((profile == EEsProfile && version < 310) || - (profile != EEsProfile && version < 150)) { + if ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 150)) { correct = false; - infoSink.info.message(EPrefixError, "#version: tessellation shaders require es profile with version 310 or non-es profile with version 150 or above"); - version = (profile == EEsProfile) ? 310 : 400; // 150 supports the extension, correction is to 400 which does not + infoSink.info.message(EPrefixError, "#version: tessellation shaders require es profile with version 310 or " + "non-es profile with version 150 or above"); + version = + (profile == EEsProfile) ? 310 : 400; // 150 supports the extension, correction is to 400 which does not if (profile == EEsProfile || profile == ENoProfile) profile = ECoreProfile; } break; case EShLangCompute: - if ((profile == EEsProfile && version < 310) || - (profile != EEsProfile && version < 420)) { + if ((profile == EEsProfile && version < 310) || (profile != EEsProfile && version < 420)) { correct = false; - infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or above, or non-es profile with version 420 or above"); + infoSink.info.message(EPrefixError, "#version: compute shaders require es profile with version 310 or " + "above, or non-es profile with version 420 or above"); version = profile == EEsProfile ? 310 : 420; } break; @@ -631,16 +703,17 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo case EShLangCallable: if (profile == EEsProfile || version < 460) { correct = false; - infoSink.info.message(EPrefixError, "#version: ray tracing shaders require non-es profile with version 460 or above"); + infoSink.info.message(EPrefixError, + "#version: ray tracing shaders require non-es profile with version 460 or above"); version = 460; } break; case EShLangMeshNV: case EShLangTaskNV: - if ((profile == EEsProfile && version < 320) || - (profile != EEsProfile && version < 450)) { + if ((profile == EEsProfile && version < 320) || (profile != EEsProfile && version < 450)) { correct = false; - infoSink.info.message(EPrefixError, "#version: mesh/task shaders require es profile with version 320 or above, or non-es profile with version 450 or above"); + infoSink.info.message(EPrefixError, "#version: mesh/task shaders require es profile with version 320 or " + "above, or non-es profile with version 450 or above"); version = profile == EEsProfile ? 320 : 450; } default: @@ -649,7 +722,8 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo if (profile == EEsProfile && version >= 300 && versionNotFirst) { correct = false; - infoSink.info.message(EPrefixError, "#version: statement must appear first in es-profile shader; before comments or newlines"); + infoSink.info.message( + EPrefixError, "#version: statement must appear first in es-profile shader; before comments or newlines"); } // Check for SPIR-V compatibility @@ -663,17 +737,20 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo } break; case ECompatibilityProfile: - infoSink.info.message(EPrefixError, "#version: compilation for SPIR-V does not support the compatibility profile"); + infoSink.info.message(EPrefixError, + "#version: compilation for SPIR-V does not support the compatibility profile"); break; default: if (spvVersion.vulkan > 0 && version < 140) { correct = false; - infoSink.info.message(EPrefixError, "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher"); + infoSink.info.message(EPrefixError, + "#version: Desktop shaders for Vulkan SPIR-V require version 140 or higher"); version = 140; } if (spvVersion.openGl >= 100 && version < 330) { correct = false; - infoSink.info.message(EPrefixError, "#version: Desktop shaders for OpenGL SPIR-V require version 330 or higher"); + infoSink.info.message(EPrefixError, + "#version: Desktop shaders for OpenGL SPIR-V require version 330 or higher"); version = 330; } break; @@ -688,8 +765,8 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo // TEnvironment takes precedence, for what it sets, so sort all this out. // Ideally, the internal code could be made to use TEnvironment, but for // now, translate it to the historically used parameters. -void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages, EShSource& source, - EShLanguage& stage, SpvVersion& spvVersion) +void TranslateEnvironment(const TEnvironment* environment, EShMessages& messages, EShSource& source, EShLanguage& stage, + SpvVersion& spvVersion) { // Set up environmental defaults, first ignoring 'environment'. if (messages & EShMsgSpvRules) @@ -782,29 +859,22 @@ void RecordProcesses(TIntermediate& intermediate, EShMessages messages, const st // EShOptimizationLevel , EShMessages ); // Which returns false if a failure was detected and true otherwise. // -template +template bool ProcessDeferred( - TCompiler* compiler, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const char* const stringNames[], - const char* customPreamble, - const EShOptimizationLevel optLevel, + TCompiler* compiler, const char* const shaderStrings[], const int numStrings, const int* inputLengths, + const char* const stringNames[], const char* customPreamble, const EShOptimizationLevel optLevel, const TBuiltInResource* resources, - int defaultVersion, // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan + int defaultVersion, // use 100 for ES environment, 110 for desktop; this is the GLSL version, not SPIR-V or Vulkan EProfile defaultProfile, // set version/profile to defaultVersion/defaultProfile regardless of the #version // directive in the source code bool forceDefaultVersionAndProfile, - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages, // warnings/errors/AST; things to print out + bool forwardCompatible, // give errors for use of deprecated features + EShMessages messages, // warnings/errors/AST; things to print out TIntermediate& intermediate, // returned tree, etc. - ProcessingContext& processingContext, - bool requireNonempty, - TShader::Includer& includer, + ProcessingContext& processingContext, bool requireNonempty, TShader::Includer& includer, const std::string sourceEntryPointName = "", - const TEnvironment* environment = nullptr) // optional way of fully setting all versions, overriding the above + const TEnvironment* environment = nullptr) // optional way of fully setting all versions, overriding the above { // This must be undone (.pop()) by the caller, after it finishes consuming the created tree. GetThreadPoolAllocator().push(); @@ -822,7 +892,7 @@ bool ProcessDeferred( // string 2...numStrings+1: user's shader // string numStrings+2: "int;" const int numPre = 2; - const int numPost = requireNonempty? 1 : 0; + const int numPost = requireNonempty ? 1 : 0; const int numTotal = numPre + numStrings + numPost; std::unique_ptr lengths(new size_t[numTotal]); std::unique_ptr strings(new const char*[numTotal]); @@ -862,18 +932,16 @@ bool ProcessDeferred( int version = 0; EProfile profile = ENoProfile; bool versionNotFirstToken = false; - bool versionNotFirst = (source == EShSourceHlsl) - ? true - : userInput.scanVersion(version, profile, versionNotFirstToken); + bool versionNotFirst = + (source == EShSourceHlsl) ? true : userInput.scanVersion(version, profile, versionNotFirstToken); bool versionNotFound = version == 0; if (forceDefaultVersionAndProfile && source == EShSourceGlsl) { #ifndef GLSLANG_WEB - if (! (messages & EShMsgSuppressWarnings) && ! versionNotFound && + if (!(messages & EShMsgSuppressWarnings) && !versionNotFound && (version != defaultVersion || profile != defaultProfile)) { - compiler->infoSink.info << "Warning, (version, profile) forced to be (" - << defaultVersion << ", " << ProfileName(defaultProfile) - << "), while in source code it is (" - << version << ", " << ProfileName(profile) << ")\n"; + compiler->infoSink.info << "Warning, (version, profile) forced to be (" << defaultVersion << ", " + << ProfileName(defaultProfile) << "), while in source code it is (" << version + << ", " << ProfileName(profile) << ")\n"; } #endif if (versionNotFound) { @@ -885,8 +953,8 @@ bool ProcessDeferred( profile = defaultProfile; } - bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage, - versionNotFirst, defaultVersion, source, version, profile, spvVersion); + bool goodVersion = DeduceVersionProfile(compiler->infoSink, stage, versionNotFirst, defaultVersion, source, version, + profile, spvVersion); #ifdef GLSLANG_WEB profile = EEsProfile; version = 310; @@ -895,7 +963,7 @@ bool ProcessDeferred( bool versionWillBeError = (versionNotFound || (profile == EEsProfile && version >= 300 && versionNotFirst)); #ifndef GLSLANG_WEB bool warnVersionNotFirst = false; - if (! versionWillBeError && versionNotFirstToken) { + if (!versionWillBeError && versionNotFirstToken) { if (messages & EShMsgRelaxedErrors) warnVersionNotFirst = true; else @@ -924,11 +992,8 @@ bool ProcessDeferred( } SetupBuiltinSymbolTable(version, profile, spvVersion, source); - TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)] - [MapSpvVersionToIndex(spvVersion)] - [MapProfileToIndex(profile)] - [MapSourceToIndex(source)] - [stage]; + TSymbolTable* cachedTable = SharedSymbolTables[MapVersionToIndex(version)][MapSpvVersionToIndex(spvVersion)] + [MapProfileToIndex(profile)][MapSourceToIndex(source)][stage]; // Dynamically allocate the symbol table so we can control when it is deallocated WRT the pool. std::unique_ptr symbolTable(new TSymbolTable); @@ -937,8 +1002,8 @@ bool ProcessDeferred( // Add built-in symbols that are potentially context dependent; // they get popped again further down. - if (! AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion, - stage, source)) { + if (!AddContextSpecificSymbols(resources, compiler->infoSink, *symbolTable, version, profile, spvVersion, stage, + source)) { return false; } @@ -949,9 +1014,9 @@ bool ProcessDeferred( // Now we can process the full shader under proper symbols and rules. // - std::unique_ptr parseContext(CreateParseContext(*symbolTable, intermediate, version, profile, source, - stage, compiler->infoSink, - spvVersion, forwardCompatible, messages, false, sourceEntryPointName)); + std::unique_ptr parseContext( + CreateParseContext(*symbolTable, intermediate, version, profile, source, stage, compiler->infoSink, spvVersion, + forwardCompatible, messages, false, sourceEntryPointName)); TPpContext ppContext(*parseContext, names[numPre] ? names[numPre] : "", includer); // only GLSL (bison triggered, really) needs an externally set scan context @@ -961,7 +1026,7 @@ bool ProcessDeferred( parseContext->setPpContext(&ppContext); parseContext->setLimits(*resources); - if (! goodVersion) + if (!goodVersion) parseContext->addError(); #ifndef GLSLANG_WEB if (warnVersionNotFirst) { @@ -994,8 +1059,7 @@ bool ProcessDeferred( // Push a new symbol allocation scope that will get used for the shader's globals. symbolTable->push(); - bool success = processingContext(*parseContext, ppContext, fullInput, - versionWillBeError, *symbolTable, + bool success = processingContext(*parseContext, ppContext, fullInput, versionWillBeError, *symbolTable, intermediate, optLevel, messages); return success; } @@ -1007,16 +1071,18 @@ bool ProcessDeferred( // or line changes. class SourceLineSynchronizer { public: - SourceLineSynchronizer(const std::function& lastSourceIndex, - std::string* output) - : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) {} -// SourceLineSynchronizer(const SourceLineSynchronizer&) = delete; -// SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete; + SourceLineSynchronizer(const std::function& lastSourceIndex, std::string* output) + : getLastSourceIndex(lastSourceIndex), output(output), lastSource(-1), lastLine(0) + { + } + // SourceLineSynchronizer(const SourceLineSynchronizer&) = delete; + // SourceLineSynchronizer& operator=(const SourceLineSynchronizer&) = delete; // Sets the internally tracked source string index to that of the most // recently read token. If we switched to a new source string, returns // true and inserts a newline. Otherwise, returns false and outputs nothing. - bool syncToMostRecentString() { + bool syncToMostRecentString() + { if (getLastSourceIndex() != lastSource) { // After switching to a new source string, we need to reset lastLine // because line number resets every time a new source string is @@ -1034,11 +1100,13 @@ class SourceLineSynchronizer { // Calls syncToMostRecentString() and then sets the internally tracked line // number to tokenLine. If we switched to a new line, returns true and inserts // newlines appropriately. Otherwise, returns false and outputs nothing. - bool syncToLine(int tokenLine) { + bool syncToLine(int tokenLine) + { syncToMostRecentString(); const bool newLineStarted = lastLine < tokenLine; for (; lastLine < tokenLine; ++lastLine) { - if (lastLine > 0) *output += '\n'; + if (lastLine > 0) + *output += '\n'; } return newLineStarted; } @@ -1072,11 +1140,9 @@ class SourceLineSynchronizer { // // This is not an officially supported or fully working path. struct DoPreprocessing { - explicit DoPreprocessing(std::string* string): outputString(string) {} - bool operator()(TParseContextBase& parseContext, TPpContext& ppContext, - TInputScanner& input, bool versionWillBeError, - TSymbolTable&, TIntermediate&, - EShOptimizationLevel, EShMessages) + explicit DoPreprocessing(std::string* string) : outputString(string) {} + bool operator()(TParseContextBase& parseContext, TPpContext& ppContext, TInputScanner& input, + bool versionWillBeError, TSymbolTable&, TIntermediate&, EShOptimizationLevel, EShMessages) { // This is a list of tokens that do not require a space before or after. static const std::string unNeededSpaceTokens = ";()[]"; @@ -1087,20 +1153,20 @@ struct DoPreprocessing { ppContext.setInput(input, versionWillBeError); std::string outputBuffer; - SourceLineSynchronizer lineSync( - std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputBuffer); + SourceLineSynchronizer lineSync(std::bind(&TInputScanner::getLastValidSourceIndex, &input), &outputBuffer); - parseContext.setExtensionCallback([&lineSync, &outputBuffer]( - int line, const char* extension, const char* behavior) { + parseContext.setExtensionCallback( + [&lineSync, &outputBuffer](int line, const char* extension, const char* behavior) { lineSync.syncToLine(line); outputBuffer += "#extension "; outputBuffer += extension; outputBuffer += " : "; outputBuffer += behavior; - }); + }); - parseContext.setLineCallback([&lineSync, &outputBuffer, &parseContext]( - int curLineNum, int newLineNum, bool hasSource, int sourceNum, const char* sourceName) { + parseContext.setLineCallback([&lineSync, &outputBuffer, &parseContext](int curLineNum, int newLineNum, + bool hasSource, int sourceNum, + const char* sourceName) { // SourceNum is the number of the source-string that is being parsed. lineSync.syncToLine(curLineNum); outputBuffer += "#line "; @@ -1125,31 +1191,29 @@ struct DoPreprocessing { lineSync.setLineNum(newLineNum + 1); }); - parseContext.setVersionCallback( - [&lineSync, &outputBuffer](int line, int version, const char* str) { - lineSync.syncToLine(line); - outputBuffer += "#version "; - outputBuffer += std::to_string(version); - if (str) { - outputBuffer += ' '; - outputBuffer += str; - } - }); + parseContext.setVersionCallback([&lineSync, &outputBuffer](int line, int version, const char* str) { + lineSync.syncToLine(line); + outputBuffer += "#version "; + outputBuffer += std::to_string(version); + if (str) { + outputBuffer += ' '; + outputBuffer += str; + } + }); - parseContext.setPragmaCallback([&lineSync, &outputBuffer]( - int line, const glslang::TVector& ops) { + parseContext.setPragmaCallback( + [&lineSync, &outputBuffer](int line, const glslang::TVector& ops) { lineSync.syncToLine(line); outputBuffer += "#pragma "; - for(size_t i = 0; i < ops.size(); ++i) { + for (size_t i = 0; i < ops.size(); ++i) { outputBuffer += ops[i].c_str(); } - }); + }); - parseContext.setErrorCallback([&lineSync, &outputBuffer]( - int line, const char* errorMessage) { - lineSync.syncToLine(line); - outputBuffer += "#error "; - outputBuffer += errorMessage; + parseContext.setErrorCallback([&lineSync, &outputBuffer](int line, const char* errorMessage) { + lineSync.syncToLine(line); + outputBuffer += "#error "; + outputBuffer += errorMessage; }); int lastToken = EndOfInput; // lastToken records the last token processed. @@ -1202,23 +1266,23 @@ struct DoPreprocessing { // DoFullParse is a valid ProcessingConext template argument for fully // parsing the shader. It populates the "intermediate" with the AST. -struct DoFullParse{ - bool operator()(TParseContextBase& parseContext, TPpContext& ppContext, - TInputScanner& fullInput, bool versionWillBeError, - TSymbolTable&, TIntermediate& intermediate, - EShOptimizationLevel optLevel, EShMessages messages) +struct DoFullParse { + bool operator()(TParseContextBase& parseContext, TPpContext& ppContext, TInputScanner& fullInput, + bool versionWillBeError, TSymbolTable&, TIntermediate& intermediate, EShOptimizationLevel optLevel, + EShMessages messages) { bool success = true; // Parse the full shader. - if (! parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError)) + if (!parseContext.parseShaderStrings(ppContext, fullInput, versionWillBeError)) success = false; if (success && intermediate.getTreeRoot()) { if (optLevel == EShOptNoGeneration) - parseContext.infoSink.info.message(EPrefixNone, "No errors. No code generation or linking was requested."); + parseContext.infoSink.info.message(EPrefixNone, + "No errors. No code generation or linking was requested."); else success = intermediate.postProcess(intermediate.getTreeRoot(), parseContext.getLanguage()); - } else if (! success) { + } else if (!success) { parseContext.infoSink.info.prefix(EPrefixError); parseContext.infoSink.info << parseContext.getNumErrors() << " compilation errors. No code generated.\n\n"; } @@ -1238,30 +1302,21 @@ struct DoFullParse{ // // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string // is not an officially supported or fully working path. -bool PreprocessDeferred( - TCompiler* compiler, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const char* const stringNames[], - const char* preamble, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int defaultVersion, // use 100 for ES environment, 110 for desktop - EProfile defaultProfile, - bool forceDefaultVersionAndProfile, - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages, // warnings/errors/AST; things to print out - TShader::Includer& includer, - TIntermediate& intermediate, // returned tree, etc. - std::string* outputString) +bool PreprocessDeferred(TCompiler* compiler, const char* const shaderStrings[], const int numStrings, + const int* inputLengths, const char* const stringNames[], const char* preamble, + const EShOptimizationLevel optLevel, const TBuiltInResource* resources, + int defaultVersion, // use 100 for ES environment, 110 for desktop + EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, // give errors for use of deprecated features + EShMessages messages, // warnings/errors/AST; things to print out + TShader::Includer& includer, + TIntermediate& intermediate, // returned tree, etc. + std::string* outputString) { DoPreprocessing parser(outputString); - return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, - preamble, optLevel, resources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, - forwardCompatible, messages, intermediate, parser, - false, includer); + return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, preamble, optLevel, + resources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, + messages, intermediate, parser, false, includer); } #endif @@ -1276,34 +1331,24 @@ bool PreprocessDeferred( // return: the tree and other information is filled into the intermediate argument, // and true is returned by the function for success. // -bool CompileDeferred( - TCompiler* compiler, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const char* const stringNames[], - const char* preamble, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int defaultVersion, // use 100 for ES environment, 110 for desktop - EProfile defaultProfile, - bool forceDefaultVersionAndProfile, - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages, // warnings/errors/AST; things to print out - TIntermediate& intermediate,// returned tree, etc. - TShader::Includer& includer, - const std::string sourceEntryPointName = "", - TEnvironment* environment = nullptr) +bool CompileDeferred(TCompiler* compiler, const char* const shaderStrings[], const int numStrings, + const int* inputLengths, const char* const stringNames[], const char* preamble, + const EShOptimizationLevel optLevel, const TBuiltInResource* resources, + int defaultVersion, // use 100 for ES environment, 110 for desktop + EProfile defaultProfile, bool forceDefaultVersionAndProfile, + bool forwardCompatible, // give errors for use of deprecated features + EShMessages messages, // warnings/errors/AST; things to print out + TIntermediate& intermediate, // returned tree, etc. + TShader::Includer& includer, const std::string sourceEntryPointName = "", + TEnvironment* environment = nullptr) { DoFullParse parser; - return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, - preamble, optLevel, resources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, - forwardCompatible, messages, intermediate, parser, - true, includer, sourceEntryPointName, environment); + return ProcessDeferred(compiler, shaderStrings, numStrings, inputLengths, stringNames, preamble, optLevel, + resources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, + messages, intermediate, parser, true, includer, sourceEntryPointName, environment); } -} // end anonymous namespace for local functions +} // namespace // // ShInitialize() should be called exactly once per process, not per thread. @@ -1312,7 +1357,7 @@ int ShInitialize() { glslang::InitGlobalLock(); - if (! InitProcess()) + if (!InitProcess()) return 0; glslang::GetGlobalLock(); @@ -1390,7 +1435,7 @@ int ShFinalize() assert(NumberOfClients >= 0); bool finalize = NumberOfClients == 0; glslang::ReleaseGlobalLock(); - if (! finalize) + if (!finalize) return 1; for (int version = 0; version < VersionCount; ++version) { @@ -1440,18 +1485,12 @@ int ShFinalize() // Return: The return value is really boolean, indicating // success (1) or failure (0). // -int ShCompile( - const ShHandle handle, - const char* const shaderStrings[], - const int numStrings, - const int* inputLengths, - const EShOptimizationLevel optLevel, - const TBuiltInResource* resources, - int /*debugOptions*/, - int defaultVersion, // use 100 for ES environment, 110 for desktop - bool forwardCompatible, // give errors for use of deprecated features - EShMessages messages // warnings/errors/AST; things to print out - ) +int ShCompile(const ShHandle handle, const char* const shaderStrings[], const int numStrings, const int* inputLengths, + const EShOptimizationLevel optLevel, const TBuiltInResource* resources, int /*debugOptions*/, + int defaultVersion, // use 100 for ES environment, 110 for desktop + bool forwardCompatible, // give errors for use of deprecated features + EShMessages messages // warnings/errors/AST; things to print out +) { // Map the generic handle to the C++ object if (handle == 0) @@ -1469,9 +1508,9 @@ int ShCompile( TIntermediate intermediate(compiler->getLanguage()); TShader::ForbidIncluder includer; - bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, - "", optLevel, resources, defaultVersion, ENoProfile, false, - forwardCompatible, messages, intermediate, includer); + bool success = + CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, nullptr, "", optLevel, resources, + defaultVersion, ENoProfile, false, forwardCompatible, messages, intermediate, includer); // // Call the machine dependent compiler @@ -1494,10 +1533,7 @@ int ShCompile( // Return: The return value of is really boolean, indicating // success or failure. // -int ShLinkExt( - const ShHandle linkHandle, - const ShHandle compHandles[], - const int numHandles) +int ShLinkExt(const ShHandle linkHandle, const ShHandle compHandles[], const int numHandles) { if (linkHandle == 0 || numHandles == 0) return 0; @@ -1530,7 +1566,7 @@ int ShLinkExt( for (int i = 0; i < numHandles; ++i) { if (cObjects[i]->getAsCompiler()) { - if (! cObjects[i]->getAsCompiler()->linkable()) { + if (!cObjects[i]->getAsCompiler()->linkable()) { linker->infoSink.info.message(EPrefixError, "Not all shaders have valid object code."); return 0; } @@ -1637,7 +1673,7 @@ int ShSetFixedAttributeBindings(const ShHandle handle, const ShBindingTable* tab // // Some attribute locations are off-limits to the linker... // -int ShExcludeAttributes(const ShHandle handle, int *attributes, int count) +int ShExcludeAttributes(const ShHandle handle, int* attributes, int count) { if (handle == 0) return 0; @@ -1664,7 +1700,7 @@ int ShGetUniformLocation(const ShHandle handle, const char* name) return -1; TShHandleBase* base = reinterpret_cast(handle); - TUniformMap* uniformMap= base->getAsUniformMap(); + TUniformMap* uniformMap = base->getAsUniformMap(); if (uniformMap == 0) return -1; @@ -1684,44 +1720,44 @@ int ShGetUniformLocation(const ShHandle handle, const char* name) namespace glslang { -#include "../Include/revision.h" +Version GetVersion() +{ + Version version; + version.major = GLSLANG_VERSION_MAJOR; + version.minor = GLSLANG_VERSION_MINOR; + version.patch = GLSLANG_VERSION_PATCH; + version.flavor = GLSLANG_VERSION_FLAVOR; + return version; +} #define QUOTE(s) #s #define STR(n) QUOTE(n) const char* GetEsslVersionString() { - return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL); + return "OpenGL ES GLSL 3.20 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR( + GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR; } const char* GetGlslVersionString() { - return "4.60 glslang Khronos. " STR(GLSLANG_MINOR_VERSION) "." STR(GLSLANG_PATCH_LEVEL); + return "4.60 glslang Khronos. " STR(GLSLANG_VERSION_MAJOR) "." STR(GLSLANG_VERSION_MINOR) "." STR( + GLSLANG_VERSION_PATCH) GLSLANG_VERSION_FLAVOR; } -int GetKhronosToolId() -{ - return 8; -} +int GetKhronosToolId() { return 8; } -bool InitializeProcess() -{ - return ShInitialize() != 0; -} +bool InitializeProcess() { return ShInitialize() != 0; } -void FinalizeProcess() -{ - ShFinalize(); -} +void FinalizeProcess() { ShFinalize(); } class TDeferredCompiler : public TCompiler { public: - TDeferredCompiler(EShLanguage s, TInfoSink& i) : TCompiler(s, i) { } + TDeferredCompiler(EShLanguage s, TInfoSink& i) : TCompiler(s, i) {} virtual bool compile(TIntermNode*, int = 0, EProfile = ENoProfile) { return true; } }; -TShader::TShader(EShLanguage s) - : stage(s), lengths(nullptr), stringNames(nullptr), preamble("") +TShader::TShader(EShLanguage s) : stage(s), lengths(nullptr), stringNames(nullptr), preamble("") { pool = new TPoolAllocator; infoSink = new TInfoSink; @@ -1758,8 +1794,7 @@ void TShader::setStringsWithLengths(const char* const* s, const int* l, int n) lengths = l; } -void TShader::setStringsWithLengthsAndNames( - const char* const* s, const int* l, const char* const* names, int n) +void TShader::setStringsWithLengthsAndNames(const char* const* s, const int* l, const char* const* names, int n) { strings = s; numStrings = n; @@ -1767,35 +1802,25 @@ void TShader::setStringsWithLengthsAndNames( stringNames = names; } -void TShader::setEntryPoint(const char* entryPoint) -{ - intermediate->setEntryPointName(entryPoint); -} +void TShader::setEntryPoint(const char* entryPoint) { intermediate->setEntryPointName(entryPoint); } -void TShader::setSourceEntryPoint(const char* name) -{ - sourceEntryPointName = name; -} +void TShader::setSourceEntryPoint(const char* name) { sourceEntryPointName = name; } // Log initial settings and transforms. // See comment for class TProcesses. -void TShader::addProcesses(const std::vector& p) -{ - intermediate->addProcesses(p); -} +void TShader::addProcesses(const std::vector& p) { intermediate->addProcesses(p); } -void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); } -void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); } +void TShader::setInvertY(bool invert) { intermediate->setInvertY(invert); } +void TShader::setNanMinMaxClamp(bool useNonNan) { intermediate->setNanMinMaxClamp(useNonNan); } #ifndef GLSLANG_WEB // Set binding base for given resource type -void TShader::setShiftBinding(TResourceType res, unsigned int base) { - intermediate->setShiftBinding(res, base); -} +void TShader::setShiftBinding(TResourceType res, unsigned int base) { intermediate->setShiftBinding(res, base); } // Set binding base for given resource type for a given binding set. -void TShader::setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set) { +void TShader::setShiftBindingForSet(TResourceType res, unsigned int base, unsigned int set) +{ intermediate->setShiftBindingForSet(res, base, set); } @@ -1804,38 +1829,38 @@ void TShader::setShiftSamplerBinding(unsigned int base) { setShiftBinding(EResSa // Set binding base for texture types (SRV) void TShader::setShiftTextureBinding(unsigned int base) { setShiftBinding(EResTexture, base); } // Set binding base for image types -void TShader::setShiftImageBinding(unsigned int base) { setShiftBinding(EResImage, base); } +void TShader::setShiftImageBinding(unsigned int base) { setShiftBinding(EResImage, base); } // Set binding base for uniform buffer objects (CBV) -void TShader::setShiftUboBinding(unsigned int base) { setShiftBinding(EResUbo, base); } +void TShader::setShiftUboBinding(unsigned int base) { setShiftBinding(EResUbo, base); } // Synonym for setShiftUboBinding, to match HLSL language. void TShader::setShiftCbufferBinding(unsigned int base) { setShiftBinding(EResUbo, base); } // Set binding base for UAV (unordered access view) -void TShader::setShiftUavBinding(unsigned int base) { setShiftBinding(EResUav, base); } +void TShader::setShiftUavBinding(unsigned int base) { setShiftBinding(EResUav, base); } // Set binding base for SSBOs -void TShader::setShiftSsboBinding(unsigned int base) { setShiftBinding(EResSsbo, base); } +void TShader::setShiftSsboBinding(unsigned int base) { setShiftBinding(EResSsbo, base); } // Enables binding automapping using TIoMapper -void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); } +void TShader::setAutoMapBindings(bool map) { intermediate->setAutoMapBindings(map); } // Enables position.Y output negation in vertex shader // Fragile: currently within one stage: simple auto-assignment of location -void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); } +void TShader::setAutoMapLocations(bool map) { intermediate->setAutoMapLocations(map); } void TShader::addUniformLocationOverride(const char* name, int loc) { intermediate->addUniformLocationOverride(name, loc); } -void TShader::setUniformLocationBase(int base) +void TShader::setUniformLocationBase(int base) { intermediate->setUniformLocationBase(base); } +void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); } +void TShader::setResourceSetBinding(const std::vector& base) { intermediate->setResourceSetBinding(base); } +void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { - intermediate->setUniformLocationBase(base); + intermediate->setTextureSamplerTransformMode(mode); } -void TShader::setNoStorageFormat(bool useUnknownFormat) { intermediate->setNoStorageFormat(useUnknownFormat); } -void TShader::setResourceSetBinding(const std::vector& base) { intermediate->setResourceSetBinding(base); } -void TShader::setTextureSamplerTransformMode(EShTextureSamplerTransformMode mode) { intermediate->setTextureSamplerTransformMode(mode); } #endif #ifdef ENABLE_HLSL // See comment above TDefaultHlslIoMapper in iomapper.cpp: -void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } -void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } +void TShader::setHlslIoMapping(bool hlslIoMap) { intermediate->setHlslIoMapping(hlslIoMap); } +void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlattenUniformArrays(flatten); } #endif // @@ -1843,21 +1868,20 @@ void TShader::setFlattenUniformArrays(bool flatten) { intermediate->setFlatt // // Returns true for success. // -bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages messages, Includer& includer) +bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, + bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages messages, + Includer& includer) { - if (! InitThread()) + if (!InitThread()) return false; SetThreadPoolAllocator(pool); - if (! preamble) + if (!preamble) preamble = ""; - return CompileDeferred(compiler, strings, numStrings, lengths, stringNames, - preamble, EShOptNone, builtInResources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, - forwardCompatible, messages, *intermediate, includer, sourceEntryPointName, - &environment); + return CompileDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, EShOptNone, builtInResources, + defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, messages, + *intermediate, includer, sourceEntryPointName, &environment); } #ifndef GLSLANG_WEB @@ -1866,42 +1890,33 @@ bool TShader::parse(const TBuiltInResource* builtInResources, int defaultVersion // // NOTE: Doing just preprocessing to obtain a correct preprocessed shader string // is not an officially supported or fully working path. -bool TShader::preprocess(const TBuiltInResource* builtInResources, - int defaultVersion, EProfile defaultProfile, - bool forceDefaultVersionAndProfile, - bool forwardCompatible, EShMessages message, - std::string* output_string, - Includer& includer) +bool TShader::preprocess(const TBuiltInResource* builtInResources, int defaultVersion, EProfile defaultProfile, + bool forceDefaultVersionAndProfile, bool forwardCompatible, EShMessages message, + std::string* output_string, Includer& includer) { - if (! InitThread()) + if (!InitThread()) return false; SetThreadPoolAllocator(pool); - if (! preamble) + if (!preamble) preamble = ""; - return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, - EShOptNone, builtInResources, defaultVersion, - defaultProfile, forceDefaultVersionAndProfile, + return PreprocessDeferred(compiler, strings, numStrings, lengths, stringNames, preamble, EShOptNone, + builtInResources, defaultVersion, defaultProfile, forceDefaultVersionAndProfile, forwardCompatible, message, includer, *intermediate, output_string); } #endif -const char* TShader::getInfoLog() -{ - return infoSink->info.c_str(); -} +const char* TShader::getInfoLog() { return infoSink->info.c_str(); } -const char* TShader::getInfoDebugLog() -{ - return infoSink->debug.c_str(); -} +const char* TShader::getInfoDebugLog() { return infoSink->debug.c_str(); } -TProgram::TProgram() : +TProgram::TProgram() + : #ifndef GLSLANG_WEB - reflection(0), + reflection(0), #endif - linked(false) + linked(false) { pool = new TPoolAllocator; infoSink = new TInfoSink; @@ -1942,13 +1957,13 @@ bool TProgram::link(EShMessages messages) SetThreadPoolAllocator(pool); for (int s = 0; s < EShLangCount; ++s) { - if (! linkStage((EShLanguage)s, messages)) + if (!linkStage((EShLanguage)s, messages)) error = true; } // TODO: Link: cross-stage error checking - return ! error; + return !error; } // @@ -1983,14 +1998,12 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) // Be efficient for the common single compilation unit per stage case, // reusing it's TIntermediate instead of merging into a new one. // - TIntermediate *firstIntermediate = stages[stage].front()->intermediate; + TIntermediate* firstIntermediate = stages[stage].front()->intermediate; if (stages[stage].size() == 1) intermediate[stage] = firstIntermediate; else { - intermediate[stage] = new TIntermediate(stage, - firstIntermediate->getVersion(), - firstIntermediate->getProfile()); - + intermediate[stage] = + new TIntermediate(stage, firstIntermediate->getVersion(), firstIntermediate->getProfile()); // The new TIntermediate must use the same origin as the original TIntermediates. // Otherwise linking will fail due to different coordinate systems. @@ -2021,15 +2034,9 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) return intermediate[stage]->getNumErrors() == 0; } -const char* TProgram::getInfoLog() -{ - return infoSink->info.c_str(); -} +const char* TProgram::getInfoLog() { return infoSink->info.c_str(); } -const char* TProgram::getInfoDebugLog() -{ - return infoSink->debug.c_str(); -} +const char* TProgram::getInfoDebugLog() { return infoSink->debug.c_str(); } #ifndef GLSLANG_WEB @@ -2039,7 +2046,7 @@ const char* TProgram::getInfoDebugLog() bool TProgram::buildReflection(int opts) { - if (! linked || reflection != nullptr) + if (!linked || reflection != nullptr) return false; int firstStage = EShLangVertex, lastStage = EShLangFragment; @@ -2061,7 +2068,7 @@ bool TProgram::buildReflection(int opts) for (int s = 0; s < EShLangCount; ++s) { if (intermediate[s]) { - if (! reflection->addStage((EShLanguage)s, *intermediate[s])) + if (!reflection->addStage((EShLanguage)s, *intermediate[s])) return false; } } @@ -2069,33 +2076,39 @@ bool TProgram::buildReflection(int opts) return true; } -unsigned TProgram::getLocalSize(int dim) const { return reflection->getLocalSize(dim); } -int TProgram::getReflectionIndex(const char* name) const { return reflection->getIndex(name); } +unsigned TProgram::getLocalSize(int dim) const { return reflection->getLocalSize(dim); } +int TProgram::getReflectionIndex(const char* name) const { return reflection->getIndex(name); } int TProgram::getReflectionPipeIOIndex(const char* name, const bool inOrOut) const - { return reflection->getPipeIOIndex(name, inOrOut); } - -int TProgram::getNumUniformVariables() const { return reflection->getNumUniforms(); } -const TObjectReflection& TProgram::getUniform(int index) const { return reflection->getUniform(index); } -int TProgram::getNumUniformBlocks() const { return reflection->getNumUniformBlocks(); } -const TObjectReflection& TProgram::getUniformBlock(int index) const { return reflection->getUniformBlock(index); } -int TProgram::getNumPipeInputs() const { return reflection->getNumPipeInputs(); } -const TObjectReflection& TProgram::getPipeInput(int index) const { return reflection->getPipeInput(index); } -int TProgram::getNumPipeOutputs() const { return reflection->getNumPipeOutputs(); } -const TObjectReflection& TProgram::getPipeOutput(int index) const { return reflection->getPipeOutput(index); } -int TProgram::getNumBufferVariables() const { return reflection->getNumBufferVariables(); } +{ + return reflection->getPipeIOIndex(name, inOrOut); +} + +int TProgram::getNumUniformVariables() const { return reflection->getNumUniforms(); } +const TObjectReflection& TProgram::getUniform(int index) const { return reflection->getUniform(index); } +int TProgram::getNumUniformBlocks() const { return reflection->getNumUniformBlocks(); } +const TObjectReflection& TProgram::getUniformBlock(int index) const { return reflection->getUniformBlock(index); } +int TProgram::getNumPipeInputs() const { return reflection->getNumPipeInputs(); } +const TObjectReflection& TProgram::getPipeInput(int index) const { return reflection->getPipeInput(index); } +int TProgram::getNumPipeOutputs() const { return reflection->getNumPipeOutputs(); } +const TObjectReflection& TProgram::getPipeOutput(int index) const { return reflection->getPipeOutput(index); } +int TProgram::getNumBufferVariables() const { return reflection->getNumBufferVariables(); } const TObjectReflection& TProgram::getBufferVariable(int index) const { return reflection->getBufferVariable(index); } -int TProgram::getNumBufferBlocks() const { return reflection->getNumStorageBuffers(); } -const TObjectReflection& TProgram::getBufferBlock(int index) const { return reflection->getStorageBufferBlock(index); } -int TProgram::getNumAtomicCounters() const { return reflection->getNumAtomicCounters(); } -const TObjectReflection& TProgram::getAtomicCounter(int index) const { return reflection->getAtomicCounter(index); } -void TProgram::dumpReflection() { if (reflection != nullptr) reflection->dump(); } +int TProgram::getNumBufferBlocks() const { return reflection->getNumStorageBuffers(); } +const TObjectReflection& TProgram::getBufferBlock(int index) const { return reflection->getStorageBufferBlock(index); } +int TProgram::getNumAtomicCounters() const { return reflection->getNumAtomicCounters(); } +const TObjectReflection& TProgram::getAtomicCounter(int index) const { return reflection->getAtomicCounter(index); } +void TProgram::dumpReflection() +{ + if (reflection != nullptr) + reflection->dump(); +} // // I/O mapping implementation. // bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper) { - if (! linked) + if (!linked) return false; TIoMapper* ioMapper = nullptr; TIoMapper defaultIOMapper; @@ -2105,7 +2118,7 @@ bool TProgram::mapIO(TIoMapResolver* pResolver, TIoMapper* pIoMapper) ioMapper = pIoMapper; for (int s = 0; s < EShLangCount; ++s) { if (intermediate[s]) { - if (! ioMapper->addStage((EShLanguage)s, *intermediate[s], *infoSink, pResolver)) + if (!ioMapper->addStage((EShLanguage)s, *intermediate[s], *infoSink, pResolver)) return false; } } diff --git a/glslang/Public/ShaderLang.h b/glslang/Public/ShaderLang.h index d51749b3e8..1f5ff55a40 100644 --- a/glslang/Public/ShaderLang.h +++ b/glslang/Public/ShaderLang.h @@ -65,11 +65,6 @@ extern "C" { #endif -// This should always increase, as some paths to do not consume -// a more major number. -// It should increment by one when new functionality is added. -#define GLSLANG_MINOR_VERSION 15 - // // Call before doing any other compiler/linker operations. // @@ -390,6 +385,14 @@ class TInfoSink; namespace glslang { +struct Version { + int major; + int minor; + int patch; + const char* flavor; +}; + +Version GetVersion(); const char* GetEsslVersionString(); const char* GetGlslVersionString(); int GetKhronosToolId(); diff --git a/make-revision b/make-revision deleted file mode 100755 index a89ff08772..0000000000 --- a/make-revision +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -( -echo "// This header is generated by the make-revision script." -echo -echo \#define GLSLANG_PATCH_LEVEL `git log --oneline | wc -l` -) > glslang/Include/revision.h