Compile shader code into Spir-V binary.

    This function uses shaderc to compile your glsl or hlsl code into Spir-V
    code. You can refer to the shaderc documentation.

    Args:
        raw (bytes): glsl or hlsl code (bytes format, not str)
        stage (str): Pipeline stage in ['vert', 'tesc', 'tese', 'geom',
                     'frag', 'comp']
        filepath (str): Absolute path of the file (needed for #include)
        language (str): 'glsl' or 'hlsl'
        optimization (str): 'zero' (no optimization) or 'size' (reduce size)
        suppress_warnings (bool): True to suppress warnings
        warnings_as_errors (bool): Turn warnings into errors

    Returns:
        bytes: Compiled Spir-V binary.

    Raises:
        CompilationError: If compilation fails.

def compile_into_spirv(raw, stage, filepath, language="glsl",
                       optimization='size', suppress_warnings=False,
                       warnings_as_errors=False):
    """Compile shader code into Spir-V binary.

    This function uses shaderc to compile your glsl or hlsl code into Spir-V
    code. You can refer to the shaderc documentation.

    Args:
        raw (bytes): glsl or hlsl code (bytes format, not str)
        stage (str): Pipeline stage in ['vert', 'tesc', 'tese', 'geom',
                     'frag', 'comp']
        filepath (str): Absolute path of the file (needed for #include)
        language (str): 'glsl' or 'hlsl'
        optimization (str): 'zero' (no optimization) or 'size' (reduce size)
        suppress_warnings (bool): True to suppress warnings
        warnings_as_errors (bool): Turn warnings into errors

    Returns:
        bytes: Compiled Spir-V binary.

    Raises:
        CompilationError: If compilation fails.
    """
    # extract parameters
    stage = stages_mapping[stage]
    lang = languages_mapping[language]
    opt = opt_mapping[optimization]

    # initialize options
    options = lib.shaderc_compile_options_initialize()
    lib.shaderc_compile_options_set_source_language(options, lang)
    lib.shaderc_compile_options_set_optimization_level(options, opt)
    lib.shaderc_compile_options_set_target_env(
        options, lib.shaderc_target_env_vulkan, 0)
    lib.shaderc_compile_options_set_auto_bind_uniforms(options, False)
    lib.shaderc_compile_options_set_include_callbacks(
        options, lib.resolve_callback, lib.release_callback, ffi.NULL)

    if suppress_warnings:
        lib.shaderc_compile_options_set_suppress_warnings(options)
    if warnings_as_errors:
        lib.shaderc_compile_options_set_warnings_as_errors(options)

    # initialize compiler
    compiler = lib.shaderc_compiler_initialize()

    # compile
    result = lib.shaderc_compile_into_spv(compiler, raw, len(raw), stage,
                                          str.encode(filepath), b"main",
                                          options)

    # extract result
    status = lib.shaderc_result_get_compilation_status(result)
    if status != lib.shaderc_compilation_status_success:
        msg = _get_log(result)
        lib.shaderc_compile_options_release(options)
        lib.shaderc_result_release(result)
        lib.shaderc_compiler_release(compiler)
        raise CompilationError(msg)

    length = lib.shaderc_result_get_length(result)
    output_pointer = lib.shaderc_result_get_bytes(result)

    tmp = bytearray(length)
    ffi.memmove(tmp, output_pointer, length)
    spirv = bytes(tmp)

    # release resources
    lib.shaderc_compile_options_release(options)
    lib.shaderc_result_release(result)
    lib.shaderc_compiler_release(compiler)

    return spirv