glslang

repository·main·Indexed 25 days ago

https://github.com/khronosgroup/glslang

A reference compiler and validator for GLSL and ESSL that translates high-level shading languages to an internal AST and SPIR-V intermediate language. It provides a standalone CLI tool, a preferred C++ class interface via ShaderLang.h, and C functional interfaces for cross-language bindings. Supports building via CMake for Linux, Windows, Android, and WASM/JS via Emscripten.

Tokens
2.5K
Snippets
4
Records
11
Agent score
36%

What's inside glslang

  1. Build glslang using CMake (Linux, Windows, Android)

    main

    You can build glslang from source using CMake. Ensure you have a C++17 compiler, CMake, and make (or ninja) installed. Python 3.x is required if using SPIRV-Tools.

    Prerequisites

    1. Clone the repository.
    2. Run ./update_glslang_sources.py to check out external projects.

    Build Steps

    Linux:

    cmake -B $BUILD_DIR -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$(pwd)/install"
    make -j4 install

    Windows:

    cmake -B $BUILD_DIR -DCMAKE_INSTALL_PREFIX="$(pwd)/install"
    cmake --build . --config Release --target install

    Android: Requires the Android NDK. Use the -DANDROID_TOOLCHAIN=clang and appropriate -DANDROID_ABI flags.

    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
    cmake -B $BUILD_DIR -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$(pwd)/install"
    make -j4 install
  2. Install glslang via vcpkg

    main

    You can use the vcpkg dependency manager to install glslang easily.

    git clone https://github.com/Microsoft/vcpkg.git
    cd vcpkg
    ./bootstrap-vcpkg.sh
    ./vcpkg integrate install
    ./vcpkg install glslang
    git clone https://github.com/Microsoft/vcpkg.git
    cd vcpkg
    ./bootstrap-vcpkg.sh
    ./vcpkg integrate install
    ./vcpkg install glslang
  3. Run glslang tests

    main
    To execute the glslang test suite, ensure that Google Test is checked out in the External directory before building. Once the build is complete, you can run the tests using either the ctest command or by executing the gtests/glslangtests binary directly from your build directory.
  4. Build glslang for Web and Node (WASM/JS)

    main

    To build a standalone JS/WASM library for web or Node.js environments, use the Emscripten SDK (emsdk).

    Requirements:

    • emsdk must be in your PATH.
    • Set -DENABLE_GLSLANG_JS=ON for a standalone JS/WASM library.
    • Set -DENABLE_HLSL=OFF and -DENABLE_OPT=OFF to reduce size.
    • Use emcmake cmake to wrap the CMake call.
    • Note: You may need to increase the STACK_SIZE via Emscripten settings to prevent stack overflows when compiling large shaders.

    Example Build Command:

    emcmake cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_GLSLANG_JS=ON -DENABLE_HLSL=OFF -DENABLE_OPT=OFF ..
  5. Run glslang tests

    main

    glslang uses two test harnesses: Google Test (for unit and single-threaded integration tests) and the runtests script (for multi-shader linking and multi-threaded tests).

    Running Google Test-backed tests

    Requires a compiled build directory. On Linux, use ctest. On Windows, specify the configuration (e.g., ctest -C Debug). You can also run the glslangtests binary directly for fine-grained control.

    Running runtests script-backed tests

    This script requires compiled binaries to be installed into $BUILD_DIR/install. Ensure you set -DCMAKE_INSTALL_PREFIX during the CMake build process.

    Troubleshooting Test Failures

    If tests fail with validation errors, there may be a mismatch between your system's spirv-val and the glslang version. Run update_glslang_sources.py to resolve this.

  6. Use the new C Functional Interface

    main

    The glslang_c_interface.h provides a C-compatible interface similar to the C++ class interface. This is useful for cross-language bindings.

    To compile GLSL to SPIR-V 1.5 for Vulkan 1.2, you must populate a glslang_input_t struct, create a shader via glslang_shader_create, preprocess, parse, and then link using a glslang_program_t object.

    #include <glslang/Include/glslang_c_interface.h>
    #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)) {
            // Handle error
            glslang_shader_delete(shader);
            return bin;
        }
    
        if (!glslang_shader_parse(shader, &input)) {
            // Handle error
            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)) {
            // Handle error
            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);
    
        glslang_program_delete(program);
        glslang_shader_delete(shader);
    
        return bin;
    }
  7. Use the C Functional Interface (Original)

    main
    The original C functional interface (the Sh*() interface) is located in the first 2/3 of ShaderLang.h. It uses a callback-based mechanism where a 'compiler' callback is passed the AST after building. The typical runtime call stack is: ShCompile(shader, compiler) -> compiler(AST) -> <back end>.
  8. Use the C++ Class Interface (Preferred)

    main

    The new, preferred C++ interface is located in ShaderLang.h within the glslang namespace. It uses a class-oriented approach with TShader and TProgram objects to translate shaders to an AST or generate SPIR-V.

    Key Workflow for SPIR-V Generation:

    1. Call InitializeProcess().
    2. Use TShader::setStrings() to provide source code.
    3. Configure environment via setEnvInput, setEnvClient, and setEnvTarget.
    4. Call TShader::parse().
    5. Use TProgram::addShader() and TProgram::link() to link the shader stages.
    6. Call FinalizeProcess() when finished.

    For Validation Only: To validate without generating code, set the environment parameters to EShClientNone and EShTargetNone with 0 as the version/target.

  9. Rebuild GLSL grammar with Bison

    main

    If you have modified the GLSL grammar in glslang/MachineIndependent/glslang.y, you must recompile it using bison to update the generated files.

    Command:

    bison --defines=MachineIndependent/glslang_tab.cpp.h -t MachineIndependent/glslang.y -o MachineIndependent/glslang_tab.cpp
    bison --defines=MachineIndependent/glslang_tab.cpp.h -t MachineIndependent/glslang.y -o MachineIndependent/glslang_tab.cpp
  10. Use the glslang standalone wrapper CLI

    main

    The glslang command-line tool provides access to the validator, front-end, and back-end components. To use it, execute the glslang binary and provide a shader file. The tool determines the shader stage based on the file extension.

    Shader Stage Extensions:

    • Vertex: .vert
    • Tessellation Control: .tesc
    • Tessellation Evaluation: .tese
    • Geometry: .geom
    • Fragment: .frag
    • Compute: .comp

    Ray Tracing Extensions:

    • Ray Generation: .rgen
    • Ray Intersection: .rint
    • Ray Any-Hit: .rahit
    • Ray Closest-Hit: .rchit
    • Ray Miss: .rmiss
    • Callable: .rcall

    Configuration:

    • .conf: Used for configuration files of limits.
  11. Update golden files using --update-mode

    main
    The gtests/glslangtests binary includes an --update-mode command line option. When this flag is provided, the test runner will overwrite the existing golden files in the Test/baseResults/ directory with the actual output generated during the current invocation. This is useful for updating expected outputs after changes to the compiler.