yum-mirror/glslang
git clone https://git.yummers.dev/yum-mirror/glslang
0971d794
main
News
-
The HLSL front-end is deprecated as of April 2026 and will be removed at the next major version of glslang. See issue #4210 for rationale and migration guidance.
-
The --shift-texture-binding[s] option no longer affects combined samplers. The new --shift-combined-sampler-binding[s] option should be used to control combined sampler bindings independently from separate textures. The old behavior can be achieved by setting both options to the same value.
-
The spirv-remap utility from glslang has been ported to the SPIRV-Tools repository as a new optimization pass called canonicalize-ids, available in spirv-opt. See spirv-opt --help for usage details.
-
Building glslang as a DLL or shared library is now possible and supported.
Glslang Components and Status
There are several components:
Reference Validator and GLSL/ESSL -> AST Front End
An OpenGL GLSL and OpenGL|ES GLSL (ESSL) front-end for reference validation and translation of GLSL/ESSL into an internal abstract syntax tree (AST).
Status: Virtually complete, with results carrying similar weight as the specifications.
HLSL -> AST Front End
An HLSL front-end for translation of an approximation of HLSL to glslang's AST form.
Status: Deprecated as of April 2026. The HLSL front-end will be removed at the next major version of glslang, with at least 18 months of notice from this announcement.
Bug reports for the HLSL front-end will no longer be accepted. Security issues will be assessed on a case-by-case basis. Projects that require continued HLSL support should maintain a fork of glslang at the tag corresponding to the deprecation announcement.
See issue #4210 for the rationale and migration guidance.
AST -> SPIR-V Back End
Translates glslang's AST to the Khronos-specified SPIR-V intermediate language.
Status: Virtually complete.
Reflector
An API for getting reflection information from the AST, reflection types/variables/etc. from the HLL source (not the SPIR-V).
Status: There is a large amount of functionality present, but no specification/goal to measure completeness against. It is accurate for the input HLL and AST, but only approximate for what would later be emitted for SPIR-V.
Standalone Wrapper
glslang is command-line tool for accessing the functionality above.
Status: Complete.
Tasks waiting to be done are documented as GitHub issues.
Other References
Also see the Khronos landing page for glslang as a reference front end:
https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/
The above page, while not kept up to date, includes additional information regarding glslang as a reference validator.
How to Use Glslang
Execution of Standalone Wrapper
To use the standalone binary form, execute glslang, and it will print
a usage statement. Basic operation is to give it a file containing a shader,
and it will print out warnings/errors and optionally an AST.
The applied stage-specific rules are based on the file extension:
.vertfor a vertex shader.tescfor a tessellation control shader.tesefor a tessellation evaluation shader.geomfor a geometry shader.fragfor a fragment shader.compfor a compute shader
For ray tracing pipeline shaders:
.rgenfor a ray generation shader.rintfor a ray intersection shader.rahitfor a ray any-hit shader.rchitfor a ray closest-hit shader.rmissfor a ray miss shader.rcallfor a callable shader
There is also a non-shader extension:
.conffor a configuration file of limits, see usage statement for example
Building (CMake)
Instead of building manually, you can also download the binaries for your platform directly from the main-tot release on GitHub. Those binaries are automatically uploaded by the buildbots after successful testing and they always reflect the current top of the tree of the main branch.
Dependencies
- A C++17 compiler. (For MSVS: use 2019 or later.)
- CMake: for generating compilation targets.
- make: Linux, ninja is an alternative, if configured.
- Python 3.x: for executing SPIRV-Tools scripts. (Optional if not using SPIRV-Tools and the 'External' subdirectory does not exist.)
- bison: optional, but needed when changing the grammar (glslang.y).
- googletest: optional, but should use if making any changes to glslang.
Build steps
The following steps assume a Bash shell. On Windows, that could be the Git Bash shell or some other shell of your choosing.
1) Check-Out this project
cd < parent of where you want glslang to be> git clone https://github.com/KhronosGroup/glslang.git
2) Check-Out External Projects
./update_glslang_sources.py
3) Configure
Assume the source directory is $SOURCE_DIR and the build directory is $BUILD_DIR.
CMake will create the $BUILD_DIR for the user if it doesn't exist.
First change your working directory:
cd $ SOURCE_DIR
For building on Linux:
cmake -B $ BUILD_DIR -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX= " $( pwd ) /install" # "Release" (for CMAKE_BUILD_TYPE) could also be "Debug" or "RelWithDebInfo"
For building on Android:
cmake -B $ BUILD_DIR -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX= " $( pwd ) /install" -DANDROID_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Release -DANDROID_STL=c++_static -DANDROID_PLATFORM=android-24 -DCMAKE_SYSTEM_NAME=Android -DANDROID_TOOLCHAIN=clang -DANDROID_ARM_MODE=arm -DCMAKE_MAKE_PROGRAM= $ ANDROID_NDK_HOME /prebuilt/linux-x86_64/bin/make -DCMAKE_TOOLCHAIN_FILE= $ ANDROID_NDK_HOME /build/cmake/android.toolchain.cmake # If on Windows will be -DCMAKE_MAKE_PROGRAM=%ANDROID_NDK_HOME%\prebuilt\windows-x86_64\bin\make.exe # -G is needed for building on Windows # -DANDROID_ABI can also be armeabi-v7a for 32 bit
For building on Windows:
cmake -B $ BUILD_DIR -DCMAKE_INSTALL_PREFIX= " $( pwd ) /install" # The CMAKE_INSTALL_PREFIX part is for testing (explained later).
Also, consider using git config --global core.fileMode false (or with --local) on Windows
to prevent the addition of execution permission on files.
4) Build and Install
# for Linux: make -j4 install# for Windows: cmake --build .--config Release--target install# "Release" (for --config) could also be "Debug", "MinSizeRel", or "RelWithDebInfo"
If using MSVC, after running CMake to configure, use the
Configuration Manager to check the INSTALL project.
Building (GN)
glslang can also be built with the GN build system.
1) Install depot_tools
Download depot_tools.zip,
extract to a directory, and add this directory to your PATH.
2) Synchronize dependencies and generate build files
This only needs to be done once after updating glslang.
With the current directory set to your glslang checkout, type:
./update_glslang_sources.py gclient sync--gclientfile=standalone.gclient gn gen out/Default
3) Build
With the current directory set to your glslang checkout, type:
cd out/Defaultninja
If you need to change the GLSL grammar
The grammar in glslang/MachineIndependent/glslang.y has to be recompiled with
bison if it changes, the output files are committed to the repo to avoid every
developer needing to have bison configured to compile the project when grammar
changes are quite infrequent. For windows you can get binaries from
GnuWin32.
The command to rebuild is:
bison --defines=MachineIndependent/glslang_tab.cpp.h -t MachineIndependent/glslang.y-o MachineIndependent/glslang_tab.cpp
The above command is also available in the bash script in updateGrammar,
when executed from the glslang subdirectory of the glslang repository.
If you need to update the NonSemantic instruction headers
SPIRV/NonSemanticShaderDebugInfo.h and SPIRV/NonSemanticDebugPrintf.h are
local copies of the canonical headers from SPIRV-Headers. They are kept here
because the SPIRV-Headers include path is not unconditionally available in all
glslang build configurations (it is only present when ENABLE_OPT is on).
When SPIRV-Headers publishes a new version of either header, copy the updated file from
External/spirv-tools/external/spirv-headers/include/spirv/unified1/
over the corresponding file in SPIRV/. After copying, verify that the build
still compiles and update the golden test output if instruction names or opcode
numbers changed.
Building to WASM for the Web and Node
Building a standalone JS/WASM library for the Web and Node
Use the steps in Build Steps, with the following notes/exceptions:
emsdkneeds to be present in your executable search path, PATH for Bash-like environments:- Wrap cmake call:
emcmake cmake - Set
-DENABLE_OPT=OFF. - Set
-DENABLE_HLSL=OFFif HLSL is not needed. - For a standalone JS/WASM library, turn on
-DENABLE_GLSLANG_JS=ON. - To get a fully minimized build, make sure to use
brotlito compress the .js and .wasm files - Note that by default, Emscripten allocates a very small stack size, which may cause stack overflows when compiling large shaders. Use the STACK_SIZE compiler setting to increase the stack size.
Example:
emcmake cmake-DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_JS=ON \-DENABLE_HLSL=OFF -DENABLE_OPT=OFF ..
Building glslang - Using vcpkg
You can download and install glslang using the vcpkg dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install glslang
The glslang port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.
Testing
Right now, there are two test harnesses existing in glslang: one is Google
Test, one is the runtests script. The former
runs unit tests and single-shader single-threaded integration tests, while
the latter runs multiple-shader linking tests and multi-threaded tests.
Tests may erroneously fail or pass if using ALLOW_EXTERNAL_SPIRV_TOOLS with
any commit other than the one specified in known_good.json.
Running tests
The runtests script requires compiled binaries to be
installed into $BUILD_DIR/install. Please make sure you have supplied the
correct configuration to CMake (using -DCMAKE_INSTALL_PREFIX) when building;
otherwise, you may want to modify the path in the runtests script.
Running Google Test-backed tests:
cd $ BUILD_DIR # for Linux: ctest # for Windows: ctest -C {Debug| Release | RelWithDebInfo | MinSizeRel} # or, run the test binary directly # (which gives more fine-grained control like filtering): < dir-to-glslangtests-in-build-dir> /glslangtests
Running runtests script-backed tests:
cd $ SOURCE_DIR /Test&& ./runtests
If some tests fail with validation errors, there may be a mismatch between the
version of spirv-val on the system and the version of glslang. In this
case, it is necessary to run update_glslang_sources.py. See "Check-Out
External Projects" above for more details.
Contributing tests
Test results should always be included with a pull request that modifies functionality.
If you are writing unit tests, please use the Google Test framework and
place the tests under the gtests/ directory.
Integration tests are placed in the Test/ directory. It contains test input
and a subdirectory baseResults/ that contains the expected results of the
tests. Both the tests and baseResults/ are under source-code control.
Google Test runs those integration tests by reading the test input, compiling
them, and then compare against the expected results in baseResults/. The
integration tests to run via Google Test is registered in various
gtests/*.FromFile.cpp source files. glslangtests provides a command-line
option --update-mode, which, if supplied, will overwrite the golden files
under the baseResults/ directory with real output from that invocation.
For more information, please check gtests/ directory's
README.
For the runtests script, it will generate current results in the
localResults/ directory and diff them against the baseResults/.
When you want to update the tracked test results, they need to be
copied from localResults/ to baseResults/. This can be done by
the bump shell script.
You can add your own private list of tests, not tracked publicly, by using
localtestlist to list non-tracked tests. This is automatically read
by runtests and included in the diff and bump process.
Programmatic Interfaces
Another piece of software can programmatically translate shaders to an AST using one of two different interfaces:
- A new C++ class-oriented interface, or
- The original C functional interface
The main() in StandAlone/StandAlone.cpp shows examples using both styles.
C++ Class Interface (new, preferred)
This interface is in roughly the last 1/3 of ShaderLang.h. It is in the
glslang namespace and contains the following, here with suggested calls
for generating SPIR-V:
const char * GetEsslVersionString ();const char * GetGlslVersionString ();bool InitializeProcess ();void FinalizeProcess ();class TShader setStrings (...);setEnvInput (EShSourceHlsl orEShSourceGlsl ,stage ,EShClientVulkan orEShClientOpenGL ,100 );setEnvClient (EShClientVulkan orEShClientOpenGL ,EShTargetVulkan_1_0 orEShTargetVulkan_1_1 orEShTargetOpenGL_450 );setEnvTarget (EShTargetSpv ,EShTargetSpv_1_0 orEShTargetSpv_1_3 );bool parse (...);const char * getInfoLog ();class TProgram void addShader (...);bool link (...);const char * getInfoLog ();Reflection queries
For just validating (not generating code), substitute these calls:
setEnvInput (EShSourceHlsl orEShSourceGlsl ,stage ,EShClientNone ,0 );setEnvClient (EShClientNone ,0 );setEnvTarget (EShTargetNone ,0 );
See ShaderLang.h and the usage of it in StandAlone/StandAlone.cpp for more
details. There is a block comment giving more detail above the calls for
setEnvInput, setEnvClient, and setEnvTarget.
C Functional Interface (original)
This interface is in roughly the first 2/3 of ShaderLang.h, and referred to
as the Sh*() interface, as all the entry points start Sh.
The Sh*() interface takes a "compiler" call-back object, which it calls after
building call back that is passed the AST and can then execute a back end on it.
The following is a simplified resulting run-time call stack:
ShCompile (shader ,compiler )-> compiler (AST )-> < back end >
In practice, ShCompile() takes shader strings, default version, and
warning/error and other options for controlling compilation.
C Functional Interface (new)
This interface is located glslang_c_interface.h and exposes functionality similar to the C++ interface. The following snippet is a complete example showing how to compile GLSL into SPIR-V 1.5 for Vulkan 1.2.
#include <glslang/Include/glslang_c_interface.h> // Required for use of glslang_default_resource #include <glslang/Public/resource_limits_c.h> typedef struct SpirVBinary {uint32_t * words ;// SPIR-V words int size ;// number of words in SPIR-V binary }SpirVBinary ;SpirVBinary compileShaderToSPIRV_Vulkan (glslang_stage_t stage ,const char * shaderSource ,const char * fileName ) {const glslang_input_t input = { .language = GLSLANG_SOURCE_GLSL , .stage = stage , .client = GLSLANG_CLIENT_VULKAN , .client_version = GLSLANG_TARGET_VULKAN_1_2 , .target_language = GLSLANG_TARGET_SPV , .target_language_version = GLSLANG_TARGET_SPV_1_5 , .code = shaderSource , .default_version = 100 , .default_profile = GLSLANG_NO_PROFILE , .force_default_version_and_profile = false, .forward_compatible = false, .messages = GLSLANG_MSG_DEFAULT_BIT , .resource = glslang_default_resource (), };glslang_shader_t * shader = glslang_shader_create (& input );SpirVBinary bin = { .words = NULL , .size = 0 , };if (!glslang_shader_preprocess (shader ,& input )) {printf ("GLSL preprocessing failed %s\n" ,fileName );printf ("%s\n" ,glslang_shader_get_info_log (shader ));printf ("%s\n" ,glslang_shader_get_info_debug_log (shader ));printf ("%s\n" ,input .code );glslang_shader_delete (shader );return bin ; }if (!glslang_shader_parse (shader ,& input )) {printf ("GLSL parsing failed %s\n" ,fileName );printf ("%s\n" ,glslang_shader_get_info_log (shader ));printf ("%s\n" ,glslang_shader_get_info_debug_log (shader ));printf ("%s\n" ,glslang_shader_get_preprocessed_code (shader ));glslang_shader_delete (shader );return bin ; }glslang_program_t * program = glslang_program_create ();glslang_program_add_shader (program ,shader );if (!glslang_program_link (program ,GLSLANG_MSG_SPV_RULES_BIT |GLSLANG_MSG_VULKAN_RULES_BIT )) {printf ("GLSL linking failed %s\n" ,fileName );printf ("%s\n" ,glslang_program_get_info_log (program ));printf ("%s\n" ,glslang_program_get_info_debug_log (program ));glslang_program_delete (program );glslang_shader_delete (shader );return bin ; }glslang_program_SPIRV_generate (program ,stage );bin .size = glslang_program_SPIRV_get_size (program );bin .words = malloc (bin .size * sizeof (uint32_t ));glslang_program_SPIRV_get (program ,bin .words );const char * spirv_messages = glslang_program_SPIRV_get_messages (program );if (spirv_messages )printf ("(%s) %s\b" ,fileName ,spirv_messages );glslang_program_delete (program );glslang_shader_delete (shader );return bin ; }
Basic Internal Operation
-
Initial lexical analysis is done by the preprocessor in
MachineIndependent/Preprocessor, and then refined by a GLSL scanner inMachineIndependent/Scan.cpp. There is currently no use of flex. -
Code is parsed using bison on
MachineIndependent/glslang.ywith the aid of a symbol table and an AST. The symbol table is not passed on to the back-end; the intermediate representation stands on its own. The tree is built by the grammar productions, many of which are offloaded intoParseHelper.cpp, and byIntermediate.cpp. -
The intermediate representation is very high-level, and represented as an in-memory tree. This serves to lose no information from the original program, and to have efficient transfer of the result from parsing to the back-end. In the AST, constants are propagated and folded, and a very small amount of dead code is eliminated.
To aid linking and reflection, the last top-level branch in the AST lists all global symbols.
-
The primary algorithm of the back-end compiler is to traverse the tree (high-level intermediate representation), and create an internal object code representation. There is an example of how to do this in
MachineIndependent/intermOut.cpp. -
Reduction of the tree to a linear byte-code style low-level intermediate representation is likely a good way to generate fully optimized code.
-
There is currently some dead old-style linker-type code still lying around.
-
Memory pool: parsing uses types derived from C++
stdtypes, using a custom allocator that puts them in a memory pool. This makes allocation of individual container/contents just few cycles and deallocation free. This pool is popped after the AST is made and processed.The use is simple: if you are going to call
new, there are three cases:-
the object comes from the pool (its base class has the macro
POOL_ALLOCATOR_NEW_DELETEin it) and you do not have to calldelete -
it is a
TString, in which case callNewPoolTString(), which gets it from the pool, and there is no correspondingdelete -
the object does not come from the pool, and you have to do normal C++ memory management of what you
new
-
-
Features can be protected by version/extension/stage/profile: See the comment in
glslang/MachineIndependent/Versions.cpp.
1 2 3[](https://securityscorecards.dev/viewer/?uri=github.com/KhronosGroup/glslang) 4 5# News 6 71. The HLSL front-end is deprecated as of April 2026 and will be removed at the next major version of glslang. See [issue #4210](https://github.com/KhronosGroup/glslang/issues/4210) for rationale and migration guidance. 8 92. The --shift-texture-binding\[s\] option no longer affects combined samplers. The new --shift-combined-sampler-binding\[s\] option should be used to control combined sampler bindings independently from separate textures. The old behavior can be achieved by setting both options to the same value. 10 113. The spirv-remap utility from glslang has been ported to the SPIRV-Tools repository as a new optimization pass called canonicalize-ids, available in spirv-opt. See spirv-opt --help for usage details. 12 134. Building glslang as a DLL or shared library is now possible and supported. 14 15# Glslang Components and Status 16 17There are several components: 18 19### Reference Validator and GLSL/ESSL -> AST Front End 20 21An OpenGL GLSL and OpenGL|ES GLSL (ESSL) front-end for reference validation and translation of GLSL/ESSL into an internal abstract syntax tree (AST). 22 23**Status**: Virtually complete, with results carrying similar weight as the specifications. 24 25### HLSL -> AST Front End 26 27An HLSL front-end for translation of an approximation of HLSL to glslang's AST form. 28 29**Status**: Deprecated as of April 2026. The HLSL front-end will be removed at the next major version of glslang, with at least 18 months of notice from this announcement. 30 31Bug reports for the HLSL front-end will no longer be accepted. Security issues will be assessed on a case-by-case basis. Projects that require continued HLSL support should maintain a fork of glslang at the tag corresponding to the deprecation announcement. 32 33See [issue #4210](https://github.com/KhronosGroup/glslang/issues/4210) for the rationale and migration guidance. 34 35### AST -> SPIR-V Back End 36 37Translates glslang's AST to the Khronos-specified SPIR-V intermediate language. 38 39**Status**: Virtually complete. 40 41### Reflector 42 43An API for getting reflection information from the AST, reflection types/variables/etc. from the HLL source (not the SPIR-V). 44 45**Status**: There is a large amount of functionality present, but no specification/goal to measure completeness against. It is accurate for the input HLL and AST, but only approximate for what would later be emitted for SPIR-V. 46 47### Standalone Wrapper 48 49`glslang` is command-line tool for accessing the functionality above. 50 51Status: Complete. 52 53Tasks waiting to be done are documented as GitHub issues. 54 55## Other References 56 57Also see the Khronos landing page for glslang as a reference front end: 58 59https://www.khronos.org/opengles/sdk/tools/Reference-Compiler/ 60 61The above page, while not kept up to date, includes additional information regarding glslang as a reference validator. 62 63# How to Use Glslang 64 65## Execution of Standalone Wrapper 66 67To use the standalone binary form, execute `glslang`, and it will print 68a usage statement. Basic operation is to give it a file containing a shader, 69and it will print out warnings/errors and optionally an AST. 70 71The applied stage-specific rules are based on the file extension: 72* `.vert` for a vertex shader 73* `.tesc` for a tessellation control shader 74* `.tese` for a tessellation evaluation shader 75* `.geom` for a geometry shader 76* `.frag` for a fragment shader 77* `.comp` for a compute shader 78 79For ray tracing pipeline shaders: 80* `.rgen` for a ray generation shader 81* `.rint` for a ray intersection shader 82* `.rahit` for a ray any-hit shader 83* `.rchit` for a ray closest-hit shader 84* `.rmiss` for a ray miss shader 85* `.rcall` for a callable shader 86 87There is also a non-shader extension: 88* `.conf` for a configuration file of limits, see usage statement for example 89 90## Building (CMake) 91 92Instead of building manually, you can also download the binaries for your 93platform directly from the [main-tot release][main-tot-release] on GitHub. 94Those binaries are automatically uploaded by the buildbots after successful 95testing and they always reflect the current top of the tree of the main 96branch. 97 98### Dependencies 99 100* A C++17 compiler. 101(For MSVS: use 2019 or later.) 102* [CMake][cmake]: for generating compilation targets. 103* make: _Linux_, ninja is an alternative, if configured. 104* [Python 3.x][python]: for executing SPIRV-Tools scripts. (Optional if not using SPIRV-Tools and the 'External' subdirectory does not exist.) 105* [bison][bison]: _optional_, but needed when changing the grammar (glslang.y). 106* [googletest][googletest]: _optional_, but should use if making any changes to glslang. 107 108### Build steps 109 110The following steps assume a Bash shell. On Windows, that could be the Git Bash 111shell or some other shell of your choosing. 112 113#### 1) Check-Out this project 114 115``` bash 116cd < parent of where you want glslang to be > 117git clone https://github.com/KhronosGroup/glslang.git 118``` 119 120#### 2) Check-Out External Projects 121 122``` bash 123./update_glslang_sources.py 124``` 125 126#### 3) Configure 127 128Assume the source directory is `$SOURCE_DIR` and the build directory is `$BUILD_DIR`. 129CMake will create the `$BUILD_DIR` for the user if it doesn't exist. 130 131First change your working directory: 132``` bash 133cd $ SOURCE_DIR 134``` 135 136For building on Linux: 137 138``` bash 139cmake -B $ BUILD_DIR -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX= " $( pwd ) /install" 140# "Release" (for CMAKE_BUILD_TYPE) could also be "Debug" or "RelWithDebInfo" 141``` 142 143For building on Android: 144``` bash 145cmake -B $ BUILD_DIR -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX= " $( pwd ) /install" -DANDROID_ABI=arm64-v8a -DCMAKE_BUILD_TYPE=Release -DANDROID_STL=c++_static -DANDROID_PLATFORM=android-24 -DCMAKE_SYSTEM_NAME=Android -DANDROID_TOOLCHAIN=clang -DANDROID_ARM_MODE=arm -DCMAKE_MAKE_PROGRAM= $ ANDROID_NDK_HOME /prebuilt/linux-x86_64/bin/make -DCMAKE_TOOLCHAIN_FILE= $ ANDROID_NDK_HOME /build/cmake/android.toolchain.cmake 146# If on Windows will be -DCMAKE_MAKE_PROGRAM=%ANDROID_NDK_HOME%\prebuilt\windows-x86_64\bin\make.exe 147# -G is needed for building on Windows 148# -DANDROID_ABI can also be armeabi-v7a for 32 bit 149``` 150 151For building on Windows: 152 153``` bash 154cmake -B $ BUILD_DIR -DCMAKE_INSTALL_PREFIX= " $( pwd ) /install" 155# The CMAKE_INSTALL_PREFIX part is for testing (explained later). 156``` 157 158Also, consider using `git config --global core.fileMode false` (or with `--local`) on Windows 159to prevent the addition of execution permission on files. 160 161#### 4) Build and Install 162 163``` bash 164# for Linux: 165make -j4 install 166 167# for Windows: 168cmake --build . --config Release --target install 169# "Release" (for --config) could also be "Debug", "MinSizeRel", or "RelWithDebInfo" 170``` 171 172If using MSVC, after running CMake to configure, use the 173Configuration Manager to check the `INSTALL` project. 174 175### Building (GN) 176 177glslang can also be built with the [GN build system](https://gn.googlesource.com/gn/). 178 179#### 1) Install `depot_tools` 180 181Download [depot_tools.zip](https://storage.googleapis.com/chrome-infra/depot_tools.zip), 182extract to a directory, and add this directory to your `PATH`. 183 184#### 2) Synchronize dependencies and generate build files 185 186This only needs to be done once after updating `glslang`. 187 188With the current directory set to your `glslang` checkout, type: 189 190``` bash 191./update_glslang_sources.py 192gclient sync --gclientfile=standalone.gclient 193gn gen out/Default 194``` 195 196#### 3) Build 197 198With the current directory set to your `glslang` checkout, type: 199 200``` bash 201cd out/Default 202ninja 203``` 204 205### If you need to change the GLSL grammar 206 207The grammar in `glslang/MachineIndependent/glslang.y` has to be recompiled with 208bison if it changes, the output files are committed to the repo to avoid every 209developer needing to have bison configured to compile the project when grammar 210changes are quite infrequent. For windows you can get binaries from 211[GnuWin32][bison-gnu-win32]. 212 213The command to rebuild is: 214 215``` bash 216bison --defines=MachineIndependent/glslang_tab.cpp.h 217-t MachineIndependent/glslang.y 218-o MachineIndependent/glslang_tab.cpp 219``` 220 221The above command is also available in the bash script in `updateGrammar`, 222when executed from the glslang subdirectory of the glslang repository. 223 224### If you need to update the NonSemantic instruction headers 225 226`SPIRV/NonSemanticShaderDebugInfo.h` and `SPIRV/NonSemanticDebugPrintf.h` are 227local copies of the canonical headers from SPIRV-Headers. They are kept here 228because the SPIRV-Headers include path is not unconditionally available in all 229glslang build configurations (it is only present when `ENABLE_OPT` is on). 230 231When SPIRV-Headers publishes a new version of either header, copy the updated 232file from 233 234``` 235External/spirv-tools/external/spirv-headers/include/spirv/unified1/ 236``` 237 238over the corresponding file in `SPIRV/`. After copying, verify that the build 239still compiles and update the golden test output if instruction names or opcode 240numbers changed. 241 242### Building to WASM for the Web and Node 243### Building a standalone JS/WASM library for the Web and Node 244 245Use the steps in [Build Steps](#build-steps), with the following notes/exceptions: 246* `emsdk` needs to be present in your executable search path, *PATH* for 247Bash-like environments: 248+ [Instructions located here](https://emscripten.org/docs/getting_started/downloads.html#sdk-download-and-install) 249* Wrap cmake call: `emcmake cmake` 250* Set `-DENABLE_OPT=OFF`. 251* Set `-DENABLE_HLSL=OFF` if HLSL is not needed. 252* For a standalone JS/WASM library, turn on `-DENABLE_GLSLANG_JS=ON`. 253* To get a fully minimized build, make sure to use `brotli` to compress the .js 254and .wasm files 255* Note that by default, Emscripten allocates a very small stack size, which may 256cause stack overflows when compiling large shaders. Use the 257[STACK_SIZE](https://emscripten.org/docs/tools_reference/settings_reference.html?highlight=environment#stack-size) 258compiler setting to increase the stack size. 259 260Example: 261 262``` sh 263emcmake cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_JS=ON \ 264-DENABLE_HLSL=OFF -DENABLE_OPT=OFF .. 265``` 266 267## Building glslang - Using vcpkg 268 269You can download and install glslang using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: 270 271git clone https://github.com/Microsoft/vcpkg.git 272cd vcpkg 273./bootstrap-vcpkg.sh 274./vcpkg integrate install 275./vcpkg install glslang 276 277The glslang port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. 278 279## Testing 280 281Right now, there are two test harnesses existing in glslang: one is [Google 282Test](gtests/), one is the [`runtests` script](Test/runtests). The former 283runs unit tests and single-shader single-threaded integration tests, while 284the latter runs multiple-shader linking tests and multi-threaded tests. 285 286Tests may erroneously fail or pass if using `ALLOW_EXTERNAL_SPIRV_TOOLS` with 287any commit other than the one specified in `known_good.json`. 288 289### Running tests 290 291The [`runtests` script](Test/runtests) requires compiled binaries to be 292installed into `$BUILD_DIR/install`. Please make sure you have supplied the 293correct configuration to CMake (using `-DCMAKE_INSTALL_PREFIX`) when building; 294otherwise, you may want to modify the path in the `runtests` script. 295 296Running Google Test-backed tests: 297 298``` bash 299cd $ BUILD_DIR 300 301# for Linux: 302ctest 303 304# for Windows: 305ctest -C {Debug | Release | RelWithDebInfo | MinSizeRel} 306 307# or, run the test binary directly 308# (which gives more fine-grained control like filtering): 309<dir-to-glslangtests-in-build-dir > /glslangtests 310``` 311 312Running `runtests` script-backed tests: 313 314``` bash 315cd $ SOURCE_DIR /Test && ./runtests 316``` 317 318If some tests fail with validation errors, there may be a mismatch between the 319version of `spirv-val` on the system and the version of glslang. In this 320case, it is necessary to run `update_glslang_sources.py`. See "Check-Out 321External Projects" above for more details. 322 323### Contributing tests 324 325Test results should always be included with a pull request that modifies 326functionality. 327 328If you are writing unit tests, please use the Google Test framework and 329place the tests under the `gtests/` directory. 330 331Integration tests are placed in the `Test/` directory. It contains test input 332and a subdirectory `baseResults/` that contains the expected results of the 333tests. Both the tests and `baseResults/` are under source-code control. 334 335Google Test runs those integration tests by reading the test input, compiling 336them, and then compare against the expected results in `baseResults/`. The 337integration tests to run via Google Test is registered in various 338`gtests/*.FromFile.cpp` source files. `glslangtests` provides a command-line 339option `--update-mode`, which, if supplied, will overwrite the golden files 340under the `baseResults/` directory with real output from that invocation. 341For more information, please check `gtests/` directory's 342[README](gtests/README.md). 343 344For the `runtests` script, it will generate current results in the 345`localResults/` directory and `diff` them against the `baseResults/`. 346When you want to update the tracked test results, they need to be 347copied from `localResults/` to `baseResults/`. This can be done by 348the `bump` shell script. 349 350You can add your own private list of tests, not tracked publicly, by using 351`localtestlist` to list non-tracked tests. This is automatically read 352by `runtests` and included in the `diff` and `bump` process. 353 354## Programmatic Interfaces 355 356Another piece of software can programmatically translate shaders to an AST 357using one of two different interfaces: 358* A new C++ class-oriented interface, or 359* The original C functional interface 360 361The `main()` in `StandAlone/StandAlone.cpp` shows examples using both styles. 362 363### C++ Class Interface (new, preferred) 364 365This interface is in roughly the last 1/3 of `ShaderLang.h`. It is in the 366glslang namespace and contains the following, here with suggested calls 367for generating SPIR-V: 368 369``` cxx 370const char* GetEsslVersionString(); 371const char* GetGlslVersionString(); 372bool InitializeProcess(); 373void FinalizeProcess(); 374 375class TShader 376setStrings(...); 377setEnvInput(EShSourceHlsl or EShSourceGlsl, stage, EShClientVulkan or EShClientOpenGL, 100); 378setEnvClient(EShClientVulkan or EShClientOpenGL, EShTargetVulkan_1_0 or EShTargetVulkan_1_1 or EShTargetOpenGL_450); 379setEnvTarget(EShTargetSpv, EShTargetSpv_1_0 or EShTargetSpv_1_3); 380bool parse(...); 381const char* getInfoLog(); 382 383class TProgram 384void addShader(...); 385bool link(...); 386const char* getInfoLog(); 387Reflection queries 388``` 389 390For just validating (not generating code), substitute these calls: 391 392``` cxx 393setEnvInput(EShSourceHlsl or EShSourceGlsl, stage, EShClientNone, 0); 394setEnvClient(EShClientNone, 0); 395setEnvTarget(EShTargetNone, 0); 396``` 397 398See `ShaderLang.h` and the usage of it in `StandAlone/StandAlone.cpp` for more 399details. There is a block comment giving more detail above the calls for 400`setEnvInput, setEnvClient, and setEnvTarget`. 401 402### C Functional Interface (original) 403 404This interface is in roughly the first 2/3 of `ShaderLang.h`, and referred to 405as the `Sh*()` interface, as all the entry points start `Sh`. 406 407The `Sh*()` interface takes a "compiler" call-back object, which it calls after 408building call back that is passed the AST and can then execute a back end on it. 409 410The following is a simplified resulting run-time call stack: 411 412``` c 413ShCompile( shader , compiler ) -> compiler ( AST ) -> < back end > 414``` 415 416In practice, `ShCompile()` takes shader strings, default version, and 417warning/error and other options for controlling compilation. 418 419### C Functional Interface (new) 420 421This interface is located `glslang_c_interface.h` and exposes functionality similar to the C++ interface. The following snippet is a complete example showing how to compile GLSL into SPIR-V 1.5 for Vulkan 1.2. 422 423``` c 424#include <glslang/Include/glslang_c_interface.h> 425 426// Required for use of glslang_default_resource 427#include <glslang/Public/resource_limits_c.h> 428 429typedef struct SpirVBinary { 430uint32_t * words ; // SPIR-V words 431int size ; // number of words in SPIR-V binary 432} SpirVBinary ; 433 434SpirVBinary compileShaderToSPIRV_Vulkan ( glslang_stage_t stage , const char * shaderSource , const char * fileName ) { 435const glslang_input_t input = { 436. language = GLSLANG_SOURCE_GLSL , 437. stage = stage , 438. client = GLSLANG_CLIENT_VULKAN , 439. client_version = GLSLANG_TARGET_VULKAN_1_2 , 440. target_language = GLSLANG_TARGET_SPV , 441. target_language_version = GLSLANG_TARGET_SPV_1_5 , 442. code = shaderSource , 443. default_version = 100 , 444. default_profile = GLSLANG_NO_PROFILE , 445. force_default_version_and_profile = false, 446. forward_compatible = false, 447. messages = GLSLANG_MSG_DEFAULT_BIT , 448. resource = glslang_default_resource (), 449}; 450 451glslang_shader_t * shader = glslang_shader_create ( & input ); 452 453SpirVBinary bin = { 454. words = NULL , 455. size = 0 , 456}; 457if (! glslang_shader_preprocess ( shader , & input )) { 458printf ( "GLSL preprocessing failed %s\n" , fileName ); 459printf ( "%s\n" , glslang_shader_get_info_log ( shader )); 460printf ( "%s\n" , glslang_shader_get_info_debug_log ( shader )); 461printf ( "%s\n" , input . code ); 462glslang_shader_delete ( shader ); 463return bin ; 464} 465 466if (! glslang_shader_parse ( shader , & input )) { 467printf ( "GLSL parsing failed %s\n" , fileName ); 468printf ( "%s\n" , glslang_shader_get_info_log ( shader )); 469printf ( "%s\n" , glslang_shader_get_info_debug_log ( shader )); 470printf ( "%s\n" , glslang_shader_get_preprocessed_code ( shader )); 471glslang_shader_delete ( shader ); 472return bin ; 473} 474 475glslang_program_t * program = glslang_program_create (); 476glslang_program_add_shader ( program , shader ); 477 478if (! glslang_program_link ( program , GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT )) { 479printf ( "GLSL linking failed %s\n" , fileName ); 480printf ( "%s\n" , glslang_program_get_info_log ( program )); 481printf ( "%s\n" , glslang_program_get_info_debug_log ( program )); 482glslang_program_delete ( program ); 483glslang_shader_delete ( shader ); 484return bin ; 485} 486 487glslang_program_SPIRV_generate ( program , stage ); 488 489bin . size = glslang_program_SPIRV_get_size ( program ); 490bin . words = malloc ( bin . size * sizeof ( uint32_t )); 491glslang_program_SPIRV_get ( program , bin . words ); 492 493const char * spirv_messages = glslang_program_SPIRV_get_messages ( program ); 494if ( spirv_messages ) 495printf ( "(%s) %s\b" , fileName , spirv_messages ); 496 497glslang_program_delete ( program ); 498glslang_shader_delete ( shader ); 499 500return bin ; 501} 502``` 503 504## Basic Internal Operation 505 506* Initial lexical analysis is done by the preprocessor in 507`MachineIndependent/Preprocessor`, and then refined by a GLSL scanner 508in `MachineIndependent/Scan.cpp`. There is currently no use of flex. 509 510* Code is parsed using bison on `MachineIndependent/glslang.y` with the 511aid of a symbol table and an AST. The symbol table is not passed on to 512the back-end; the intermediate representation stands on its own. 513The tree is built by the grammar productions, many of which are 514offloaded into `ParseHelper.cpp`, and by `Intermediate.cpp`. 515 516* The intermediate representation is very high-level, and represented 517as an in-memory tree. This serves to lose no information from the 518original program, and to have efficient transfer of the result from 519parsing to the back-end. In the AST, constants are propagated and 520folded, and a very small amount of dead code is eliminated. 521 522To aid linking and reflection, the last top-level branch in the AST 523lists all global symbols. 524 525* The primary algorithm of the back-end compiler is to traverse the 526tree (high-level intermediate representation), and create an internal 527object code representation. There is an example of how to do this 528in `MachineIndependent/intermOut.cpp`. 529 530* Reduction of the tree to a linear byte-code style low-level intermediate 531representation is likely a good way to generate fully optimized code. 532 533* There is currently some dead old-style linker-type code still lying around. 534 535* Memory pool: parsing uses types derived from C++ `std` types, using a 536custom allocator that puts them in a memory pool. This makes allocation 537of individual container/contents just few cycles and deallocation free. 538This pool is popped after the AST is made and processed. 539 540The use is simple: if you are going to call `new`, there are three cases: 541 542- the object comes from the pool (its base class has the macro 543`POOL_ALLOCATOR_NEW_DELETE` in it) and you do not have to call `delete` 544 545- it is a `TString`, in which case call `NewPoolTString()`, which gets 546it from the pool, and there is no corresponding `delete` 547 548- the object does not come from the pool, and you have to do normal 549C++ memory management of what you `new` 550 551* Features can be protected by version/extension/stage/profile: 552See the comment in `glslang/MachineIndependent/Versions.cpp`. 553 554[cmake] : https://cmake.org/ 555[python] : https://www.python.org/ 556[bison] : https://www.gnu.org/software/bison/ 557[googletest] : https://github.com/google/googletest 558[bison-gnu-win32] : http://gnuwin32.sourceforge.net/packages/bison.htm 559[main-tot-release] : https://github.com/KhronosGroup/glslang/releases/tag/main-tot