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