yum-mirror/glslang

git clone https://git.yummers.dev/yum-mirror/glslang

Diego NovilloInitial support for NonSemantic.Shader.DebugInfo 101 (#4220)0971d794

main
21.1 KiB559 linesraw

Continuous Integration Continuous Deployment OpenSSF Scorecard

News

  1. 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.

  2. 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.

  3. 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.

  4. 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:

  • .vert for a vertex shader
  • .tesc for a tessellation control shader
  • .tese for a tessellation evaluation shader
  • .geom for a geometry shader
  • .frag for a fragment shader
  • .comp for a compute shader

For ray tracing pipeline shaders:

  • .rgen for a ray generation shader
  • .rint for a ray intersection shader
  • .rahit for a ray any-hit shader
  • .rchit for a ray closest-hit shader
  • .rmiss for a ray miss shader
  • .rcall for a callable shader

There is also a non-shader extension:

  • .conf for 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/Default
ninja

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:

  • emsdk needs 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=OFF if 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 brotli to 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 or EShSourceGlsl, stage,  EShClientVulkan or EShClientOpenGL, 100);
    setEnvClient(EShClientVulkan or EShClientOpenGL, EShTargetVulkan_1_0 or EShTargetVulkan_1_1 or EShTargetOpenGL_450);
    setEnvTarget(EShTargetSpv, EShTargetSpv_1_0 or EShTargetSpv_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 or EShSourceGlsl, 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 in MachineIndependent/Scan.cpp. There is currently no use of flex.

  • Code is parsed using bison on MachineIndependent/glslang.y with 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 into ParseHelper.cpp, and by Intermediate.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++ std types, 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_DELETE in it) and you do not have to call delete

    • it is a TString, in which case call NewPoolTString(), which gets it from the pool, and there is no corresponding delete

    • 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![Continuous Integration](https://github.com/KhronosGroup/glslang/actions/workflows/continuous_integration.yml/badge.svg)
2![Continuous Deployment](https://github.com/KhronosGroup/glslang/actions/workflows/continuous_deployment.yml/badge.svg)
3[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/KhronosGroup/glslang/badge)](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
247  Bash-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
254  and .wasm files
255* Note that by default, Emscripten allocates a very small stack size, which may
256  cause stack overflows when compiling large shaders. Use the
257  [STACK_SIZE](https://emscripten.org/docs/tools_reference/settings_reference.html?highlight=environment#stack-size)
258  compiler 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
271    git clone https://github.com/Microsoft/vcpkg.git
272    cd 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
376    setStrings(...);
377    setEnvInput(EShSourceHlsl or EShSourceGlsl, stage,  EShClientVulkan or EShClientOpenGL, 100);
378    setEnvClient(EShClientVulkan or EShClientOpenGL, EShTargetVulkan_1_0 or EShTargetVulkan_1_1 or EShTargetOpenGL_450);
379    setEnvTarget(EShTargetSpv, EShTargetSpv_1_0 or EShTargetSpv_1_3);
380    bool parse(...);
381    const char* getInfoLog();
382
383class TProgram
384    void addShader(...);
385    bool link(...);
386    const char* getInfoLog();
387    Reflection queries
388```
389
390For just validating (not generating code), substitute these calls:
391
392```cxx
393    setEnvInput(EShSourceHlsl or EShSourceGlsl, stage,  EShClientNone, 0);
394    setEnvClient(EShClientNone, 0);
395    setEnvTarget(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 {
430    uint32_t *words; // SPIR-V words
431    int size; // number of words in SPIR-V binary
432} SpirVBinary;
433
434SpirVBinary compileShaderToSPIRV_Vulkan(glslang_stage_t stage, const char* shaderSource, const char* fileName) {
435    const 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
451    glslang_shader_t* shader = glslang_shader_create(&input);
452
453    SpirVBinary bin = {
454        .words = NULL,
455        .size = 0,
456    };
457    if (!glslang_shader_preprocess(shader, &input))	{
458        printf("GLSL preprocessing failed %s\n", fileName);
459        printf("%s\n", glslang_shader_get_info_log(shader));
460        printf("%s\n", glslang_shader_get_info_debug_log(shader));
461        printf("%s\n", input.code);
462        glslang_shader_delete(shader);
463        return bin;
464    }
465
466    if (!glslang_shader_parse(shader, &input)) {
467        printf("GLSL parsing failed %s\n", fileName);
468        printf("%s\n", glslang_shader_get_info_log(shader));
469        printf("%s\n", glslang_shader_get_info_debug_log(shader));
470        printf("%s\n", glslang_shader_get_preprocessed_code(shader));
471        glslang_shader_delete(shader);
472        return bin;
473    }
474
475    glslang_program_t* program = glslang_program_create();
476    glslang_program_add_shader(program, shader);
477
478    if (!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT)) {
479        printf("GLSL linking failed %s\n", fileName);
480        printf("%s\n", glslang_program_get_info_log(program));
481        printf("%s\n", glslang_program_get_info_debug_log(program));
482        glslang_program_delete(program);
483        glslang_shader_delete(shader);
484        return bin;
485    }
486
487    glslang_program_SPIRV_generate(program, stage);
488
489    bin.size = glslang_program_SPIRV_get_size(program);
490    bin.words = malloc(bin.size * sizeof(uint32_t));
491    glslang_program_SPIRV_get(program, bin.words);
492
493    const char* spirv_messages = glslang_program_SPIRV_get_messages(program);
494    if (spirv_messages)
495        printf("(%s) %s\b", fileName, spirv_messages);
496
497    glslang_program_delete(program);
498    glslang_shader_delete(shader);
499
500    return 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
508  in `MachineIndependent/Scan.cpp`.  There is currently no use of flex.
509
510* Code is parsed using bison on `MachineIndependent/glslang.y` with the
511  aid of a symbol table and an AST.  The symbol table is not passed on to
512  the back-end; the intermediate representation stands on its own.
513  The tree is built by the grammar productions, many of which are
514  offloaded into `ParseHelper.cpp`, and by `Intermediate.cpp`.
515
516* The intermediate representation is very high-level, and represented
517  as an in-memory tree.   This serves to lose no information from the
518  original program, and to have efficient transfer of the result from
519  parsing to the back-end.  In the AST, constants are propagated and
520  folded, and a very small amount of dead code is eliminated.
521
522  To aid linking and reflection, the last top-level branch in the AST
523  lists all global symbols.
524
525* The primary algorithm of the back-end compiler is to traverse the
526  tree (high-level intermediate representation), and create an internal
527  object code representation.  There is an example of how to do this
528  in `MachineIndependent/intermOut.cpp`.
529
530* Reduction of the tree to a linear byte-code style low-level intermediate
531  representation 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
536  custom allocator that puts them in a memory pool.  This makes allocation
537  of individual container/contents just few cycles and deallocation free.
538  This pool is popped after the AST is made and processed.
539
540  The 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
546    it 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
549    C++ memory management of what you `new`
550
551* Features can be protected by version/extension/stage/profile:
552  See 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