#if defined(SOKOL_IMPL) && !defined(SOKOL_GL_IMPL)
#define SOKOL_GL_IMPL
#endif
#ifndef SOKOL_GL_INCLUDED
/*
    sokol_gl.h -- OpenGL 1.x style rendering on top of sokol_gfx.h

    Project URL: https://github.com/floooh/sokol

    Do this:
        #define SOKOL_IMPL or
        #define SOKOL_GL_IMPL
    before you include this file in *one* C or C++ file to create the
    implementation.

    The following defines are used by the implementation to select the
    platform-specific embedded shader code (these are the same defines as
    used by sokol_gfx.h and sokol_app.h):

    SOKOL_GLCORE33
    SOKOL_GLES3
    SOKOL_D3D11
    SOKOL_METAL
    SOKOL_WGPU

    ...optionally provide the following macros to override defaults:

    SOKOL_ASSERT(c)     - your own assert macro (default: assert(c))
    SOKOL_GL_API_DECL   - public function declaration prefix (default: extern)
    SOKOL_API_DECL      - same as SOKOL_GL_API_DECL
    SOKOL_API_IMPL      - public function implementation prefix (default: -)
    SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))

    If sokol_gl.h is compiled as a DLL, define the following before
    including the declaration or implementation:

    SOKOL_DLL

    On Windows, SOKOL_DLL will define SOKOL_GL_API_DECL as __declspec(dllexport)
    or __declspec(dllimport) as needed.

    Include the following headers before including sokol_gl.h:

        sokol_gfx.h

    Matrix functions have been taken from MESA and Regal.

    FEATURE OVERVIEW:
    =================
    sokol_gl.h implements a subset of the OpenGLES 1.x feature set useful for
    when you just want to quickly render a bunch of triangles or
    lines without having to mess with buffers and shaders.

    The current feature set is mostly useful for debug visualizations
    and simple UI-style 2D rendering:

    What's implemented:
        - vertex components:
            - position (x, y, z)
            - 2D texture coords (u, v)
            - color (r, g, b, a)
        - primitive types:
            - triangle list and strip
            - line list and strip
            - quad list (TODO: quad strips)
            - point list
        - one texture layer (no multi-texturing)
        - viewport and scissor-rect with selectable origin (top-left or bottom-left)
        - all GL 1.x matrix stack functions, and additionally equivalent
          functions for gluPerspective and gluLookat

    Notable GLES 1.x features that are *NOT* implemented:
        - vertex lighting (this is the most likely GL feature that might be added later)
        - vertex arrays (although providing whole chunks of vertex data at once
          might be a useful feature for a later version)
        - texture coordinate generation
        - line width
        - all pixel store functions
        - no ALPHA_TEST
        - no clear functions (clearing is handled by the sokol-gfx render pass)
        - fog

    Notable differences to GL:
        - No "enum soup" for render states etc, instead there's a
          'pipeline stack', this is similar to GL's matrix stack,
          but for pipeline-state-objects. The pipeline object at
          the top of the pipeline stack defines the active set of render states
        - All angles are in radians, not degrees (note the sgl_rad() and
          sgl_deg() conversion functions)
        - No enable/disable state for scissor test, this is always enabled

    STEP BY STEP:
    =============
    --- To initialize sokol-gl, call:

            sgl_setup(const sgl_desc_t* desc)

        NOTE that sgl_setup() must be called *after* initializing sokol-gfx
        (via sg_setup). This is because sgl_setup() needs to create
        sokol-gfx resource objects.

        If you're intending to render to the default pass, and also don't
        want to tweak memory usage, and don't want any logging output you can
        just keep sgl_desc_t zero-initialized:

            sgl_setup(&(sgl_desc_t*){ 0 });

        In this case, sokol-gl will create internal sg_pipeline objects that
        are compatible with the sokol-app default framebuffer.

        I would recommend to at least install a logging callback so that
        you'll see any warnings and errors. The easiest way is through
        sokol_log.h:

            #include "sokol_log.h"

            sgl_setup(&(sgl_desc_t){
                .logger.func = slog_func.
            });

        If you want to render into a framebuffer with different pixel-format
        and MSAA attributes you need to provide the matching attributes in the
        sgl_setup() call:

            sgl_setup(&(sgl_desc_t*){
                .color_format = SG_PIXELFORMAT_...,
                .depth_format = SG_PIXELFORMAT_...,
                .sample_count = ...,
            });

        To reduce memory usage, or if you need to create more then the default number of
        contexts, pipelines, vertices or draw commands, set the following sgl_desc_t
        members:

            .context_pool_size      (default: 4)
            .pipeline_pool_size     (default: 64)
            .max_vertices       (default: 64k)
            .max_commands       (default: 16k)

        Finally you can change the face winding for front-facing triangles
        and quads:

            .face_winding    - default is SG_FACEWINDING_CCW

        The default winding for front faces is counter-clock-wise. This is
        the same as OpenGL's default, but different from sokol-gfx.

    --- Optionally create additional context objects if you want to render into
        multiple sokol-gfx render passes (or generally if you want to
        use multiple independent sokol-gl "state buckets")

            sgl_context ctx = sgl_make_context(const sgl_context_desc_t* desc)

        For details on rendering with sokol-gl contexts, search below for
        WORKING WITH CONTEXTS.

    --- Optionally create pipeline-state-objects if you need render state
        that differs from sokol-gl's default state:

            sgl_pipeline pip = sgl_make_pipeline(const sg_pipeline_desc* desc)

        ...this creates a pipeline object that's compatible with the currently
        active context, alternatively call:

            sgl_pipeline_pip = sgl_context_make_pipeline(sgl_context ctx, const sg_pipeline_desc* desc)

        ...to create a pipeline object that's compatible with an explicitly
        provided context.

        The similarity with sokol_gfx.h's sg_pipeline type and sg_make_pipeline()
        function is intended. sgl_make_pipeline() also takes a standard
        sokol-gfx sg_pipeline_desc object to describe the render state, but
        without:
            - shader
            - vertex layout
            - color- and depth-pixel-formats
            - primitive type (lines, triangles, ...)
            - MSAA sample count
        Those will be filled in by sgl_make_pipeline(). Note that each
        call to sgl_make_pipeline() needs to create several sokol-gfx
        pipeline objects (one for each primitive type).

        'depth.write_enabled' will be forced to 'false' if the context this
        pipeline object is intended for has its depth pixel format set to
        SG_PIXELFORMAT_NONE (which means the framebuffer this context is used
        with doesn't have a depth-stencil surface).

    --- if you need to destroy sgl_pipeline objects before sgl_shutdown():

            sgl_destroy_pipeline(sgl_pipeline pip)

    --- After sgl_setup() you can call any of the sokol-gl functions anywhere
        in a frame, *except* sgl_draw(). The 'vanilla' functions
        will only change internal sokol-gl state, and not call any sokol-gfx
        functions.

    --- Unlike OpenGL, sokol-gl has a function to reset internal state to
        a known default. This is useful at the start of a sequence of
        rendering operations:

            void sgl_defaults(void)

        This will set the following default state:

            - current texture coordinate to u=0.0f, v=0.0f
            - current color to white (rgba all 1.0f)
            - current point size to 1.0f
            - unbind the current texture and texturing will be disabled
            - *all* matrices will be set to identity (also the projection matrix)
            - the default render state will be set by loading the 'default pipeline'
              into the top of the pipeline stack

        The current matrix- and pipeline-stack-depths will not be changed by
        sgl_defaults().

    --- change the currently active renderstate through the
        pipeline-stack functions, this works similar to the
        traditional GL matrix stack:

            ...load the default pipeline state on the top of the pipeline stack:

                sgl_load_default_pipeline()

            ...load a specific pipeline on the top of the pipeline stack:

                sgl_load_pipeline(sgl_pipeline pip)

            ...push and pop the pipeline stack:
                sgl_push_pipeline()
                sgl_pop_pipeline()

    --- control texturing with:

            sgl_enable_texture()
            sgl_disable_texture()
            sgl_texture(sg_image img, sg_sampler smp)

        NOTE: the img and smp handles can be invalid (SG_INVALID_ID), in this
        case, sokol-gl will fall back to the internal default (white) texture
        and sampler.

    --- set the current viewport and scissor rect with:

            sgl_viewport(int x, int y, int w, int h, bool origin_top_left)
            sgl_scissor_rect(int x, int y, int w, int h, bool origin_top_left)

        ...or call these alternatives which take float arguments (this might allow
        to avoid casting between float and integer in more strongly typed languages
        when floating point pixel coordinates are used):

            sgl_viewportf(float x, float y, float w, float h, bool origin_top_left)
            sgl_scissor_rectf(float x, float y, float w, float h, bool origin_top_left)

        ...these calls add a new command to the internal command queue, so
        that the viewport or scissor rect are set at the right time relative
        to other sokol-gl calls.

    --- adjust the transform matrices, matrix manipulation works just like
        the OpenGL matrix stack:

        ...set the current matrix mode:

            sgl_matrix_mode_modelview()
            sgl_matrix_mode_projection()
            sgl_matrix_mode_texture()

        ...load the identity matrix into the current matrix:

            sgl_load_identity()

        ...translate, rotate and scale the current matrix:

            sgl_translate(float x, float y, float z)
            sgl_rotate(float angle_rad, float x, float y, float z)
            sgl_scale(float x, float y, float z)

        NOTE that all angles in sokol-gl are in radians, not in degree.
        Convert between radians and degree with the helper functions:

            float sgl_rad(float deg)        - degrees to radians
            float sgl_deg(float rad)        - radians to degrees

        ...directly load the current matrix from a float[16] array:

            sgl_load_matrix(const float m[16])
            sgl_load_transpose_matrix(const float m[16])

        ...directly multiply the current matrix from a float[16] array:

            sgl_mult_matrix(const float m[16])
            sgl_mult_transpose_matrix(const float m[16])

        The memory layout of those float[16] arrays is the same as in OpenGL.

        ...more matrix functions:

            sgl_frustum(float left, float right, float bottom, float top, float near, float far)
            sgl_ortho(float left, float right, float bottom, float top, float near, float far)
            sgl_perspective(float fov_y, float aspect, float near, float far)
            sgl_lookat(float eye_x, float eye_y, float eye_z, float center_x, float center_y, float center_z, float up_x, float up_y, float up_z)

        These functions work the same as glFrustum(), glOrtho(), gluPerspective()
        and gluLookAt().

        ...and finally to push / pop the current matrix stack:

            sgl_push_matrix(void)
            sgl_pop_matrix(void)

        Again, these work the same as glPushMatrix() and glPopMatrix().

    --- perform primitive rendering:

        ...set the current texture coordinate and color 'registers' with or
        point size with:

            sgl_t2f(float u, float v)   - set current texture coordinate
            sgl_c*(...)                 - set current color
            sgl_point_size(float size)  - set current point size

        There are several functions for setting the color (as float values,
        unsigned byte values, packed as unsigned 32-bit integer, with
        and without alpha).

        NOTE that these are the only functions that can be called both inside
        sgl_begin_*() / sgl_end() and outside.

        Also NOTE that point size is currently hardwired to 1.0f if the D3D11
        backend is used.

        ...start a primitive vertex sequence with:

            sgl_begin_points()
            sgl_begin_lines()
            sgl_begin_line_strip()
            sgl_begin_triangles()
            sgl_begin_triangle_strip()
            sgl_begin_quads()

        ...after sgl_begin_*() specify vertices:

            sgl_v*(...)
            sgl_v*_t*(...)
            sgl_v*_c*(...)
            sgl_v*_t*_c*(...)

        These functions write a new vertex to sokol-gl's internal vertex buffer,
        optionally with texture-coords and color. If the texture coordinate
        and/or color is missing, it will be taken from the current texture-coord
        and color 'register'.

        ...finally, after specifying vertices, call:

            sgl_end()

        This will record a new draw command in sokol-gl's internal command
        list, or it will extend the previous draw command if no relevant
        state has changed since the last sgl_begin/end pair.

    --- inside a sokol-gfx rendering pass, call the sgl_draw() function
        to render the currently active context:

            sgl_draw()

        ...or alternatively call:

            sgl_context_draw(ctx)

        ...to render an explicitly provided context.

        This will render everything that has been recorded in the context since
        the last call to sgl_draw() through sokol-gfx, and will 'rewind' the internal
        vertex-, uniform- and command-buffers.

    --- each sokol-gl context tracks an internal error code, to query the
        current error code for the currently active context call:

            sgl_error_t sgl_error()

        ...alternatively with an explicit context argument:

            sgl_error_t sgl_context_error(ctx);

        ...which can return the following error codes:

        SGL_NO_ERROR                - all OK, no error occurred since last sgl_draw()
        SGL_ERROR_VERTICES_FULL     - internal vertex buffer is full (checked in sgl_end())
        SGL_ERROR_UNIFORMS_FULL     - the internal uniforms buffer is full (checked in sgl_end())
        SGL_ERROR_COMMANDS_FULL     - the internal command buffer is full (checked in sgl_end())
        SGL_ERROR_STACK_OVERFLOW    - matrix- or pipeline-stack overflow
        SGL_ERROR_STACK_UNDERFLOW   - matrix- or pipeline-stack underflow
        SGL_ERROR_NO_CONTEXT        - the active context no longer exists

        ...if sokol-gl is in an error-state, sgl_draw() will skip any rendering,
        and reset the error code to SGL_NO_ERROR.

    RENDER LAYERS
    =============
    Render layers allow to split sokol-gl rendering into separate draw-command
    groups which can then be rendered separately in a sokol-gfx draw pass. This
    allows to mix/interleave sokol-gl rendering with other render operations.

    Layered rendering is controlled through two functions:

        sgl_layer(int layer_id)
        sgl_draw_layer(int layer_id)

    (and the context-variant sgl_draw_layer(): sgl_context_draw_layer()

    The sgl_layer() function sets the 'current layer', any sokol-gl calls
    which internally record draw commands will also store the current layer
    in the draw command, and later in a sokol-gfx render pass, a call
    to sgl_draw_layer() will only render the draw commands that have
    a matching layer.

    The default layer is '0', this is active after sokol-gl setup, and
    is also restored at the start of a new frame (but *not* by calling
    sgl_defaults()).

    NOTE that calling sgl_draw() is equivalent with sgl_draw_layer(0)
    (in general you should either use either use sgl_draw() or
    sgl_draw_layer() in an application, but not both).

    WORKING WITH CONTEXTS:
    ======================
    If you want to render to more than one sokol-gfx render pass you need to
    work with additional sokol-gl context objects (one context object for
    each offscreen rendering pass, in addition to the implicitly created
    'default context'.

    All sokol-gl state is tracked per context, and there is always a "current
    context" (with the notable exception that the currently set context is
    destroyed, more on that later).

    Using multiple contexts can also be useful if you only render in
    a single pass, but want to maintain multiple independent "state buckets".

    To create new context object, call:

        sgl_context ctx = sgl_make_context(&(sgl_context_desc){
            .max_vertices = ...,        // default: 64k
            .max_commands = ...,        // default: 16k
            .color_format = ...,
            .depth_format = ...,
            .sample_count = ...,
        });

    The color_format, depth_format and sample_count items must be compatible
    with the render pass the sgl_draw() or sgL_context_draw() function
    will be called in.

    Creating a context does *not* make the context current. To do this, call:

        sgl_set_context(ctx);

    The currently active context will implicitely be used by most sokol-gl functions
    which don't take an explicit context handle as argument.

    To switch back to the default context, pass the global constant SGL_DEFAULT_CONTEXT:

        sgl_set_context(SGL_DEFAULT_CONTEXT);

    ...or alternatively use the function sgl_default_context() instead of the
    global constant:

        sgl_set_context(sgl_default_context());

    To get the currently active context, call:

        sgl_context cur_ctx = sgl_get_context();

    The following functions exist in two variants, one which use the currently
    active context (set with sgl_set_context()), and another version which
    takes an explicit context handle instead:

        sgl_make_pipeline() vs sgl_context_make_pipeline()
        sgl_error() vs sgl_context_error();
        sgl_draw() vs sgl_context_draw();

    Except for using the currently active context versus a provided context
    handle, the two variants are exactlyidentical, e.g. the following
    code sequences do the same thing:

        sgl_set_context(ctx);
        sgl_pipeline pip = sgl_make_pipeline(...);
        sgl_error_t err = sgl_error();
        sgl_draw();

        vs

        sgl_pipeline pip = sgl_context_make_pipeline(ctx, ...);
        sgl_error_t err = sgl_context_error(ctx);
        sgl_context_draw(ctx);

    Destroying the currently active context is a 'soft error'. All following
    calls which require a currently active context will silently fail,
    and sgl_error() will return SGL_ERROR_NO_CONTEXT.

    UNDER THE HOOD:
    ===============
    sokol_gl.h works by recording vertex data and rendering commands into
    memory buffers, and then drawing the recorded commands via sokol_gfx.h

    The only functions which call into sokol_gfx.h are:
        - sgl_setup()
        - sgl_shutdown()
        - sgl_draw() (and variants)

    sgl_setup() must be called after initializing sokol-gfx.
    sgl_shutdown() must be called before shutting down sokol-gfx.
    sgl_draw() must be called once per frame inside a sokol-gfx render pass.

    All other sokol-gl function can be called anywhere in a frame, since
    they just record data into memory buffers owned by sokol-gl.

    What happens in:

        sgl_setup():
            Unique resources shared by all contexts are created:
                - a shader object (using embedded shader source or byte code)
                - an 8x8 white default texture
            The default context is created, which involves:
                - 3 memory buffers are created, one for vertex data,
                  one for uniform data, and one for commands
                - a dynamic vertex buffer is created
                - the default sgl_pipeline object is created, which involves
                  creating 5 sg_pipeline objects

            One vertex is 24 bytes:
                - float3 position
                - float2 texture coords
                - uint32_t color

            One uniform block is 128 bytes:
                - mat4 model-view-projection matrix
                - mat4 texture matrix

            One draw command is ca. 24 bytes for the actual
            command code plus command arguments.

            Each sgl_end() consumes one command, and one uniform block
            (only when the matrices have changed).
            The required size for one sgl_begin/end pair is (at most):

                (152 + 24 * num_verts) bytes

        sgl_shutdown():
            - all sokol-gfx resources (buffer, shader, default-texture and
              all pipeline objects) are destroyed
            - the 3 memory buffers are freed

        sgl_draw() (and variants)
            - copy all recorded vertex data into the dynamic sokol-gfx buffer
              via a call to sg_update_buffer()
            - for each recorded command:
                - if the layer number stored in the command doesn't match
                  the layer that's to be rendered, skip to the next
                  command
                - if it's a viewport command, call sg_apply_viewport()
                - if it's a scissor-rect command, call sg_apply_scissor_rect()
                - if it's a draw command:
                    - depending on what has changed since the last draw command,
                      call sg_apply_pipeline(), sg_apply_bindings() and
                      sg_apply_uniforms()
                    - finally call sg_draw()

    All other functions only modify the internally tracked state, add
    data to the vertex, uniform and command buffers, or manipulate
    the matrix stack.

    ON DRAW COMMAND MERGING
    =======================
    Not every call to sgl_end() will automatically record a new draw command.
    If possible, the previous draw command will simply be extended,
    resulting in fewer actual draw calls later in sgl_draw().

    A draw command will be merged with the previous command if "no relevant
    state has changed" since the last sgl_end(), meaning:

    - no calls to sgl_viewport() and sgl_scissor_rect()
    - the primitive type hasn't changed
    - the primitive type isn't a 'strip type' (no line or triangle strip)
    - the pipeline state object hasn't changed
    - the current layer hasn't changed
    - none of the matrices has changed
    - none of the texture state has changed

    Merging a draw command simply means that the number of vertices
    to render in the previous draw command will be incremented by the
    number of vertices in the new draw command.

    MEMORY ALLOCATION OVERRIDE
    ==========================
    You can override the memory allocation functions at initialization time
    like this:

        void* my_alloc(size_t size, void* user_data) {
            return malloc(size);
        }

        void my_free(void* ptr, void* user_data) {
            free(ptr);
        }

        ...
            sgl_setup(&(sgl_desc_t){
                // ...
                .allocator = {
                    .alloc_fn = my_alloc,
                    .free_fn = my_free,
                    .user_data = ...;
                }
            });
        ...

    If no overrides are provided, malloc and free will be used.


    ERROR REPORTING AND LOGGING
    ===========================
    To get any logging information at all you need to provide a logging callback in the setup call,
    the easiest way is to use sokol_log.h:

        #include "sokol_log.h"

        sgl_setup(&(sgl_desc_t){
            // ...
            .logger.func = slog_func
        });

    To override logging with your own callback, first write a logging function like this:

        void my_log(const char* tag,                // e.g. 'sgl'
                    uint32_t log_level,             // 0=panic, 1=error, 2=warn, 3=info
                    uint32_t log_item_id,           // SGL_LOGITEM_*
                    const char* message_or_null,    // a message string, may be nullptr in release mode
                    uint32_t line_nr,               // line number in sokol_gl.h
                    const char* filename_or_null,   // source filename, may be nullptr in release mode
                    void* user_data)
        {
            ...
        }

    ...and then setup sokol-gl like this:

        sgl_setup(&(sgl_desc_t){
            .logger = {
                .func = my_log,
                .user_data = my_user_data,
            }
        });

    The provided logging function must be reentrant (e.g. be callable from
    different threads).

    If you don't want to provide your own custom logger it is highly recommended to use
    the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
    errors.


    LICENSE
    =======
    zlib/libpng license

    Copyright (c) 2018 Andre Weissflog

    This software is provided 'as-is', without any express or implied warranty.
    In no event will the authors be held liable for any damages arising from the
    use of this software.

    Permission is granted to anyone to use this software for any purpose,
    including commercial applications, and to alter it and redistribute it
    freely, subject to the following restrictions:

        1. The origin of this software must not be misrepresented; you must not
        claim that you wrote the original software. If you use this software in a
        product, an acknowledgment in the product documentation would be
        appreciated but is not required.

        2. Altered source versions must be plainly marked as such, and must not
        be misrepresented as being the original software.

        3. This notice may not be removed or altered from any source
        distribution.
*/
#define SOKOL_GL_INCLUDED (1)
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h> // size_t, offsetof

#if !defined(SOKOL_GFX_INCLUDED)
#error "Please include sokol_gfx.h before sokol_gl.h"
#endif

#if defined(SOKOL_API_DECL) && !defined(SOKOL_GL_API_DECL)
#define SOKOL_GL_API_DECL SOKOL_API_DECL
#endif
#ifndef SOKOL_GL_API_DECL
#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_GL_IMPL)
#define SOKOL_GL_API_DECL __declspec(dllexport)
#elif defined(_WIN32) && defined(SOKOL_DLL)
#define SOKOL_GL_API_DECL __declspec(dllimport)
#else
#define SOKOL_GL_API_DECL extern
#endif
#endif

#ifdef __cplusplus
extern "C" {
#endif

/*
    sgl_log_item_t

    Log items are defined via X-Macros, and expanded to an
    enum 'sgl_log_item' - and in debug mode only - corresponding strings.

    Used as parameter in the logging callback.
*/
#define _SGL_LOG_ITEMS \
    _SGL_LOGITEM_XMACRO(OK, "Ok") \
    _SGL_LOGITEM_XMACRO(MALLOC_FAILED, "memory allocation failed") \
    _SGL_LOGITEM_XMACRO(MAKE_PIPELINE_FAILED, "sg_make_pipeline() failed") \
    _SGL_LOGITEM_XMACRO(PIPELINE_POOL_EXHAUSTED, "pipeline pool exhausted (use sgl_desc_t.pipeline_pool_size to adjust)") \
    _SGL_LOGITEM_XMACRO(ADD_COMMIT_LISTENER_FAILED, "sg_add_commit_listener() failed") \
    _SGL_LOGITEM_XMACRO(CONTEXT_POOL_EXHAUSTED, "context pool exhausted (use sgl_desc_t.context_pool_size to adjust)") \
    _SGL_LOGITEM_XMACRO(CANNOT_DESTROY_DEFAULT_CONTEXT, "cannot destroy default context") \

#define _SGL_LOGITEM_XMACRO(item,msg) SGL_LOGITEM_##item,
typedef enum sgl_log_item_t {
    _SGL_LOG_ITEMS
} sgl_log_item_t;
#undef _SGL_LOGITEM_XMACRO

/*
    sgl_logger_t

    Used in sgl_desc_t to provide a custom logging and error reporting
    callback to sokol-gl.
*/
typedef struct sgl_logger_t {
    void (*func)(
        const char* tag,                // always "sgl"
        uint32_t log_level,             // 0=panic, 1=error, 2=warning, 3=info
        uint32_t log_item_id,           // SGL_LOGITEM_*
        const char* message_or_null,    // a message string, may be nullptr in release mode
        uint32_t line_nr,               // line number in sokol_gl.h
        const char* filename_or_null,   // source filename, may be nullptr in release mode
        void* user_data);
    void* user_data;
} sgl_logger_t;

/* sokol_gl pipeline handle (created with sgl_make_pipeline()) */
typedef struct sgl_pipeline { uint32_t id; } sgl_pipeline;

/* a context handle (created with sgl_make_context()) */
typedef struct sgl_context { uint32_t id; } sgl_context;

/*
    sgl_error_t

    Errors are reset each frame after calling sgl_draw(),
    get the last error code with sgl_error()
*/
typedef enum sgl_error_t {
    SGL_NO_ERROR = 0,
    SGL_ERROR_VERTICES_FULL,
    SGL_ERROR_UNIFORMS_FULL,
    SGL_ERROR_COMMANDS_FULL,
    SGL_ERROR_STACK_OVERFLOW,
    SGL_ERROR_STACK_UNDERFLOW,
    SGL_ERROR_NO_CONTEXT,
} sgl_error_t;

/*
    sgl_context_desc_t

    Describes the initialization parameters of a rendering context.
    Creating additional contexts is useful if you want to render
    in separate sokol-gfx passes.
*/
typedef struct sgl_context_desc_t {
    int max_vertices;       // default: 64k
    int max_commands;       // default: 16k
    sg_pixel_format color_format;
    sg_pixel_format depth_format;
    int sample_count;
} sgl_context_desc_t;

/*
    sgl_allocator_t

    Used in sgl_desc_t to provide custom memory-alloc and -free functions
    to sokol_gl.h. If memory management should be overridden, both the
    alloc and free function must be provided (e.g. it's not valid to
    override one function but not the other).
*/
typedef struct sgl_allocator_t {
    void* (*alloc_fn)(size_t size, void* user_data);
    void (*free_fn)(void* ptr, void* user_data);
    void* user_data;
} sgl_allocator_t;

typedef struct sgl_desc_t {
    int max_vertices;               // default: 64k
    int max_commands;               // default: 16k
    int context_pool_size;          // max number of contexts (including default context), default: 4
    int pipeline_pool_size;         // size of internal pipeline pool, default: 64
    sg_pixel_format color_format;
    sg_pixel_format depth_format;
    int sample_count;
    sg_face_winding face_winding;   // default: SG_FACEWINDING_CCW
    sgl_allocator_t allocator;      // optional memory allocation overrides (default: malloc/free)
    sgl_logger_t logger;            // optional log function override (default: NO LOGGING)
} sgl_desc_t;

/* the default context handle */
static const sgl_context SGL_DEFAULT_CONTEXT = { 0x00010001 };

/* setup/shutdown/misc */
SOKOL_GL_API_DECL void sgl_setup(const sgl_desc_t* desc);
SOKOL_GL_API_DECL void sgl_shutdown(void);
SOKOL_GL_API_DECL float sgl_rad(float deg);
SOKOL_GL_API_DECL float sgl_deg(float rad);
SOKOL_GL_API_DECL sgl_error_t sgl_error(void);
SOKOL_GL_API_DECL sgl_error_t sgl_context_error(sgl_context ctx);

/* context functions */
SOKOL_GL_API_DECL sgl_context sgl_make_context(const sgl_context_desc_t* desc);
SOKOL_GL_API_DECL void sgl_destroy_context(sgl_context ctx);
SOKOL_GL_API_DECL void sgl_set_context(sgl_context ctx);
SOKOL_GL_API_DECL sgl_context sgl_get_context(void);
SOKOL_GL_API_DECL sgl_context sgl_default_context(void);

/* draw recorded commands (call inside a sokol-gfx render pass) */
SOKOL_GL_API_DECL void sgl_draw();
SOKOL_GL_API_DECL void sgl_context_draw(sgl_context ctx);
SOKOL_GL_API_DECL void sgl_draw_layer(int layer_id);
SOKOL_GL_API_DECL void sgl_context_draw_layer(sgl_context ctx, int layer_id);

/* create and destroy pipeline objects */
SOKOL_GL_API_DECL sgl_pipeline sgl_make_pipeline(const sg_pipeline_desc* desc);
SOKOL_GL_API_DECL sgl_pipeline sgl_context_make_pipeline(sgl_context ctx, const sg_pipeline_desc* desc);
SOKOL_GL_API_DECL void sgl_destroy_pipeline(sgl_pipeline pip);

/* render state functions */
SOKOL_GL_API_DECL void sgl_defaults(void);
SOKOL_GL_API_DECL void sgl_viewport(int x, int y, int w, int h, bool origin_top_left);
SOKOL_GL_API_DECL void sgl_viewportf(float x, float y, float w, float h, bool origin_top_left);
SOKOL_GL_API_DECL void sgl_scissor_rect(int x, int y, int w, int h, bool origin_top_left);
SOKOL_GL_API_DECL void sgl_scissor_rectf(float x, float y, float w, float h, bool origin_top_left);
SOKOL_GL_API_DECL void sgl_enable_texture(void);
SOKOL_GL_API_DECL void sgl_disable_texture(void);
SOKOL_GL_API_DECL void sgl_texture(sg_image img, sg_sampler smp);
SOKOL_GL_API_DECL void sgl_layer(int layer_id);

/* pipeline stack functions */
SOKOL_GL_API_DECL void sgl_load_default_pipeline(void);
SOKOL_GL_API_DECL void sgl_load_pipeline(sgl_pipeline pip);
SOKOL_GL_API_DECL void sgl_push_pipeline(void);
SOKOL_GL_API_DECL void sgl_pop_pipeline(void);

/* matrix stack functions */
SOKOL_GL_API_DECL void sgl_matrix_mode_modelview(void);
SOKOL_GL_API_DECL void sgl_matrix_mode_projection(void);
SOKOL_GL_API_DECL void sgl_matrix_mode_texture(void);
SOKOL_GL_API_DECL void sgl_load_identity(void);
SOKOL_GL_API_DECL void sgl_load_matrix(const float m[16]);
SOKOL_GL_API_DECL void sgl_load_transpose_matrix(const float m[16]);
SOKOL_GL_API_DECL void sgl_mult_matrix(const float m[16]);
SOKOL_GL_API_DECL void sgl_mult_transpose_matrix(const float m[16]);
SOKOL_GL_API_DECL void sgl_rotate(float angle_rad, float x, float y, float z);
SOKOL_GL_API_DECL void sgl_scale(float x, float y, float z);
SOKOL_GL_API_DECL void sgl_translate(float x, float y, float z);
SOKOL_GL_API_DECL void sgl_frustum(float l, float r, float b, float t, float n, float f);
SOKOL_GL_API_DECL void sgl_ortho(float l, float r, float b, float t, float n, float f);
SOKOL_GL_API_DECL void sgl_perspective(float fov_y, float aspect, float z_near, float z_far);
SOKOL_GL_API_DECL void sgl_lookat(float eye_x, float eye_y, float eye_z, float center_x, float center_y, float center_z, float up_x, float up_y, float up_z);
SOKOL_GL_API_DECL void sgl_push_matrix(void);
SOKOL_GL_API_DECL void sgl_pop_matrix(void);

/* these functions only set the internal 'current texcoord / color / point size' (valid inside or outside begin/end) */
SOKOL_GL_API_DECL void sgl_t2f(float u, float v);
SOKOL_GL_API_DECL void sgl_c3f(float r, float g, float b);
SOKOL_GL_API_DECL void sgl_c4f(float r, float g, float b, float a);
SOKOL_GL_API_DECL void sgl_c3b(uint8_t r, uint8_t g, uint8_t b);
SOKOL_GL_API_DECL void sgl_c4b(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
SOKOL_GL_API_DECL void sgl_c1i(uint32_t rgba);
SOKOL_GL_API_DECL void sgl_point_size(float s);

/* define primitives, each begin/end is one draw command */
SOKOL_GL_API_DECL void sgl_begin_points(void);
SOKOL_GL_API_DECL void sgl_begin_lines(void);
SOKOL_GL_API_DECL void sgl_begin_line_strip(void);
SOKOL_GL_API_DECL void sgl_begin_triangles(void);
SOKOL_GL_API_DECL void sgl_begin_triangle_strip(void);
SOKOL_GL_API_DECL void sgl_begin_quads(void);
SOKOL_GL_API_DECL void sgl_v2f(float x, float y);
SOKOL_GL_API_DECL void sgl_v3f(float x, float y, float z);
SOKOL_GL_API_DECL void sgl_v2f_t2f(float x, float y, float u, float v);
SOKOL_GL_API_DECL void sgl_v3f_t2f(float x, float y, float z, float u, float v);
SOKOL_GL_API_DECL void sgl_v2f_c3f(float x, float y, float r, float g, float b);
SOKOL_GL_API_DECL void sgl_v2f_c3b(float x, float y, uint8_t r, uint8_t g, uint8_t b);
SOKOL_GL_API_DECL void sgl_v2f_c4f(float x, float y, float r, float g, float b, float a);
SOKOL_GL_API_DECL void sgl_v2f_c4b(float x, float y, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
SOKOL_GL_API_DECL void sgl_v2f_c1i(float x, float y, uint32_t rgba);
SOKOL_GL_API_DECL void sgl_v3f_c3f(float x, float y, float z, float r, float g, float b);
SOKOL_GL_API_DECL void sgl_v3f_c3b(float x, float y, float z, uint8_t r, uint8_t g, uint8_t b);
SOKOL_GL_API_DECL void sgl_v3f_c4f(float x, float y, float z, float r, float g, float b, float a);
SOKOL_GL_API_DECL void sgl_v3f_c4b(float x, float y, float z, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
SOKOL_GL_API_DECL void sgl_v3f_c1i(float x, float y, float z, uint32_t rgba);
SOKOL_GL_API_DECL void sgl_v2f_t2f_c3f(float x, float y, float u, float v, float r, float g, float b);
SOKOL_GL_API_DECL void sgl_v2f_t2f_c3b(float x, float y, float u, float v, uint8_t r, uint8_t g, uint8_t b);
SOKOL_GL_API_DECL void sgl_v2f_t2f_c4f(float x, float y, float u, float v, float r, float g, float b, float a);
SOKOL_GL_API_DECL void sgl_v2f_t2f_c4b(float x, float y, float u, float v, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
SOKOL_GL_API_DECL void sgl_v2f_t2f_c1i(float x, float y, float u, float v, uint32_t rgba);
SOKOL_GL_API_DECL void sgl_v3f_t2f_c3f(float x, float y, float z, float u, float v, float r, float g, float b);
SOKOL_GL_API_DECL void sgl_v3f_t2f_c3b(float x, float y, float z, float u, float v, uint8_t r, uint8_t g, uint8_t b);
SOKOL_GL_API_DECL void sgl_v3f_t2f_c4f(float x, float y, float z, float u, float v, float r, float g, float b, float a);
SOKOL_GL_API_DECL void sgl_v3f_t2f_c4b(float x, float y, float z, float u, float v, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
SOKOL_GL_API_DECL void sgl_v3f_t2f_c1i(float x, float y, float z, float u, float v, uint32_t rgba);
SOKOL_GL_API_DECL void sgl_end(void);

#ifdef __cplusplus
} /* extern "C" */

/* reference-based equivalents for C++ */
inline void sgl_setup(const sgl_desc_t& desc) { return sgl_setup(&desc); }
inline sgl_context sgl_make_context(const sgl_context_desc_t& desc) { return sgl_make_context(&desc); }
inline sgl_pipeline sgl_make_pipeline(const sg_pipeline_desc& desc) { return sgl_make_pipeline(&desc); }
inline sgl_pipeline sgl_context_make_pipeline(sgl_context ctx, const sg_pipeline_desc& desc) { return sgl_context_make_pipeline(ctx, &desc); }
#endif
#endif /* SOKOL_GL_INCLUDED */

// ██ ███    ███ ██████  ██      ███████ ███    ███ ███████ ███    ██ ████████  █████  ████████ ██  ██████  ███    ██
// ██ ████  ████ ██   ██ ██      ██      ████  ████ ██      ████   ██    ██    ██   ██    ██    ██ ██    ██ ████   ██
// ██ ██ ████ ██ ██████  ██      █████   ██ ████ ██ █████   ██ ██  ██    ██    ███████    ██    ██ ██    ██ ██ ██  ██
// ██ ██  ██  ██ ██      ██      ██      ██  ██  ██ ██      ██  ██ ██    ██    ██   ██    ██    ██ ██    ██ ██  ██ ██
// ██ ██      ██ ██      ███████ ███████ ██      ██ ███████ ██   ████    ██    ██   ██    ██    ██  ██████  ██   ████
//
// >>implementation
#ifdef SOKOL_GL_IMPL
#define SOKOL_GL_IMPL_INCLUDED (1)

#if defined(SOKOL_MALLOC) || defined(SOKOL_CALLOC) || defined(SOKOL_FREE)
#error "SOKOL_MALLOC/CALLOC/FREE macros are no longer supported, please use sgl_desc_t.allocator to override memory allocation functions"
#endif

#include <stdlib.h> // malloc/free
#include <string.h> // memset
#include <math.h>   // M_PI, sqrtf, sinf, cosf

#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif

#ifndef SOKOL_API_IMPL
    #define SOKOL_API_IMPL
#endif
#ifndef SOKOL_DEBUG
    #ifndef NDEBUG
        #define SOKOL_DEBUG
    #endif
#endif
#ifndef SOKOL_ASSERT
    #include <assert.h>
    #define SOKOL_ASSERT(c) assert(c)
#endif

#define _sgl_def(val, def) (((val) == 0) ? (def) : (val))
#define _SGL_INIT_COOKIE (0xABCDABCD)

/*
    Embedded source code compiled with:

    sokol-shdc -i sgl.glsl -o sgl.h -l glsl330:glsl300es:hlsl4:metal_macos:metal_ios:metal_sim:wgpu -b

    (not that for Metal and D3D11 byte code, sokol-shdc must be run
    on macOS and Windows)

    @vs vs
    uniform vs_params {
        mat4 mvp;
        mat4 tm;
    };
    in vec4 position;
    in vec2 texcoord0;
    in vec4 color0;
    in float psize;
    out vec4 uv;
    out vec4 color;
    void main() {
        gl_Position = mvp * position;
        #ifndef SOKOL_WGSL
        gl_PointSize = psize;
        #endif
        uv = tm * vec4(texcoord0, 0.0, 1.0);
        color = color0;
    }
    @end

    @fs fs
    uniform texture2D tex;
    uniform sampler smp;
    in vec4 uv;
    in vec4 color;
    out vec4 frag_color;
    void main() {
        frag_color = texture(sampler2D(tex, smp), uv.xy) * color;
    }
    @end

    @program sgl vs fs
*/

#if defined(SOKOL_GLCORE33)
static const char _sgl_vs_source_glsl330[478] = {
    0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x33,0x30,0x0a,0x0a,0x75,0x6e,
    0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x73,0x5f,0x70,0x61,
    0x72,0x61,0x6d,0x73,0x5b,0x38,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,
    0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x69,0x6e,
    0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,
    0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,
    0x3d,0x20,0x33,0x29,0x20,0x69,0x6e,0x20,0x66,0x6c,0x6f,0x61,0x74,0x20,0x70,0x73,
    0x69,0x7a,0x65,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x75,0x76,
    0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,
    0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x32,0x20,0x74,
    0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,
    0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,
    0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x32,0x29,0x20,0x69,
    0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x0a,
    0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,
    0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,
    0x6d,0x61,0x74,0x34,0x28,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x30,
    0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x31,0x5d,0x2c,
    0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,0x2c,0x20,0x76,
    0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x20,0x2a,0x20,0x70,
    0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,
    0x50,0x6f,0x69,0x6e,0x74,0x53,0x69,0x7a,0x65,0x20,0x3d,0x20,0x70,0x73,0x69,0x7a,
    0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,
    0x28,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,0x2c,0x20,0x76,
    0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x35,0x5d,0x2c,0x20,0x76,0x73,0x5f,
    0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,
    0x72,0x61,0x6d,0x73,0x5b,0x37,0x5d,0x29,0x20,0x2a,0x20,0x76,0x65,0x63,0x34,0x28,
    0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,
    0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,
    0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
};
static const char _sgl_fs_source_glsl330[180] = {
    0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x33,0x30,0x0a,0x0a,0x75,0x6e,
    0x69,0x66,0x6f,0x72,0x6d,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x32,0x44,0x20,
    0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x3b,0x0a,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,
    0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,
    0x75,0x74,0x20,0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,
    0x6f,0x72,0x3b,0x0a,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x75,0x76,0x3b,0x0a,
    0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,
    0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,
    0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x74,
    0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x2c,0x20,
    0x75,0x76,0x2e,0x78,0x79,0x29,0x20,0x2a,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,
    0x7d,0x0a,0x0a,0x00,
};
#elif defined(SOKOL_GLES3)
static const char _sgl_vs_source_glsl300es[481] = {
    0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
    0x0a,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x76,0x65,0x63,0x34,0x20,0x76,0x73,
    0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x38,0x5d,0x3b,0x0a,0x6c,0x61,0x79,0x6f,
    0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x30,0x29,
    0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,
    0x6e,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,
    0x6f,0x6e,0x20,0x3d,0x20,0x33,0x29,0x20,0x69,0x6e,0x20,0x66,0x6c,0x6f,0x61,0x74,
    0x20,0x70,0x73,0x69,0x7a,0x65,0x3b,0x0a,0x6f,0x75,0x74,0x20,0x76,0x65,0x63,0x34,
    0x20,0x75,0x76,0x3b,0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,
    0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x31,0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,
    0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x3b,0x0a,0x6f,0x75,0x74,
    0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x6c,0x61,0x79,
    0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x32,
    0x29,0x20,0x69,0x6e,0x20,0x76,0x65,0x63,0x34,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,
    0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,0x69,0x6e,0x28,0x29,0x0a,0x7b,
    0x0a,0x20,0x20,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
    0x20,0x3d,0x20,0x6d,0x61,0x74,0x34,0x28,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
    0x73,0x5b,0x30,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,
    0x31,0x5d,0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x32,0x5d,
    0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x33,0x5d,0x29,0x20,
    0x2a,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,0x20,0x20,
    0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74,0x53,0x69,0x7a,0x65,0x20,0x3d,0x20,0x70,
    0x73,0x69,0x7a,0x65,0x3b,0x0a,0x20,0x20,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x6d,
    0x61,0x74,0x34,0x28,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x34,0x5d,
    0x2c,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x35,0x5d,0x2c,0x20,
    0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x36,0x5d,0x2c,0x20,0x76,0x73,
    0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x5b,0x37,0x5d,0x29,0x20,0x2a,0x20,0x76,0x65,
    0x63,0x34,0x28,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x2c,0x20,0x30,0x2e,
    0x30,0x2c,0x20,0x31,0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x63,0x6f,0x6c,
    0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,0x7d,0x0a,0x0a,
    0x00,
};
static const char _sgl_fs_source_glsl300es[253] = {
    0x23,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x33,0x30,0x30,0x20,0x65,0x73,0x0a,
    0x70,0x72,0x65,0x63,0x69,0x73,0x69,0x6f,0x6e,0x20,0x6d,0x65,0x64,0x69,0x75,0x6d,
    0x70,0x20,0x66,0x6c,0x6f,0x61,0x74,0x3b,0x0a,0x70,0x72,0x65,0x63,0x69,0x73,0x69,
    0x6f,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x69,0x6e,0x74,0x3b,0x0a,0x0a,0x75,
    0x6e,0x69,0x66,0x6f,0x72,0x6d,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x73,0x61,0x6d,
    0x70,0x6c,0x65,0x72,0x32,0x44,0x20,0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x3b,0x0a,
    0x0a,0x6c,0x61,0x79,0x6f,0x75,0x74,0x28,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,
    0x20,0x3d,0x20,0x30,0x29,0x20,0x6f,0x75,0x74,0x20,0x68,0x69,0x67,0x68,0x70,0x20,
    0x76,0x65,0x63,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x3b,
    0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x34,0x20,0x75,
    0x76,0x3b,0x0a,0x69,0x6e,0x20,0x68,0x69,0x67,0x68,0x70,0x20,0x76,0x65,0x63,0x34,
    0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x0a,0x76,0x6f,0x69,0x64,0x20,0x6d,0x61,
    0x69,0x6e,0x28,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,
    0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,
    0x74,0x65,0x78,0x5f,0x73,0x6d,0x70,0x2c,0x20,0x75,0x76,0x2e,0x78,0x79,0x29,0x20,
    0x2a,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
};
#elif defined(SOKOL_METAL)
static const uint8_t _sgl_vs_bytecode_metal_macos[3317] = {
    0x4d,0x54,0x4c,0x42,0x01,0x80,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0xf5,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
    0xe0,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,
    0x4e,0x41,0x4d,0x45,0x06,0x00,0x6d,0x61,0x69,0x6e,0x30,0x00,0x54,0x59,0x50,0x45,
    0x01,0x00,0x00,0x48,0x41,0x53,0x48,0x20,0x00,0x76,0x25,0x5f,0x37,0x22,0xd0,0x3f,
    0x64,0xef,0xff,0xc3,0x45,0x1a,0x3d,0xb7,0x5e,0x83,0x13,0x96,0xd3,0x09,0xec,0x53,
    0x25,0xd5,0x7e,0x0c,0xed,0xb9,0x58,0x34,0x02,0x4f,0x46,0x46,0x54,0x18,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x45,0x52,0x53,0x08,0x00,0x01,0x00,0x08,
    0x00,0x01,0x00,0x01,0x00,0x45,0x4e,0x44,0x54,0x40,0x00,0x00,0x00,0x56,0x41,0x54,
    0x54,0x2a,0x00,0x04,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x00,0x80,
    0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x00,0x01,0x80,0x63,0x6f,0x6c,0x6f,
    0x72,0x30,0x00,0x02,0x80,0x70,0x73,0x69,0x7a,0x65,0x00,0x03,0x80,0x56,0x41,0x54,
    0x59,0x06,0x00,0x04,0x00,0x06,0x04,0x06,0x03,0x45,0x4e,0x44,0x54,0x04,0x00,0x00,
    0x00,0x45,0x4e,0x44,0x54,0xde,0xc0,0x17,0x0b,0x00,0x00,0x00,0x00,0x14,0x00,0x00,
    0x00,0xc4,0x0b,0x00,0x00,0xff,0xff,0xff,0xff,0x42,0x43,0xc0,0xde,0x21,0x0c,0x00,
    0x00,0xee,0x02,0x00,0x00,0x0b,0x82,0x20,0x00,0x02,0x00,0x00,0x00,0x12,0x00,0x00,
    0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,0x39,0x92,0x01,0x84,
    0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,0x02,0x42,0x92,0x0b,
    0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,0x24,0x48,0x0a,0x90,
    0x21,0x23,0xc4,0x52,0x80,0x0c,0x19,0x21,0x72,0x24,0x07,0xc8,0x48,0x11,0x62,0xa8,
    0xa0,0xa8,0x40,0xc6,0xf0,0x01,0x00,0x00,0x00,0x51,0x18,0x00,0x00,0x81,0x00,0x00,
    0x00,0x1b,0xc8,0x25,0xf8,0xff,0xff,0xff,0xff,0x01,0x90,0x80,0x8a,0x18,0x87,0x77,
    0x90,0x07,0x79,0x28,0x87,0x71,0xa0,0x07,0x76,0xc8,0x87,0x36,0x90,0x87,0x77,0xa8,
    0x07,0x77,0x20,0x87,0x72,0x20,0x87,0x36,0x20,0x87,0x74,0xb0,0x87,0x74,0x20,0x87,
    0x72,0x68,0x83,0x79,0x88,0x07,0x79,0xa0,0x87,0x36,0x30,0x07,0x78,0x68,0x83,0x76,
    0x08,0x07,0x7a,0x40,0x07,0xc0,0x1c,0xc2,0x81,0x1d,0xe6,0xa1,0x1c,0x00,0x82,0x1c,
    0xd2,0x61,0x1e,0xc2,0x41,0x1c,0xd8,0xa1,0x1c,0xda,0x80,0x1e,0xc2,0x21,0x1d,0xd8,
    0xa1,0x0d,0xc6,0x21,0x1c,0xd8,0x81,0x1d,0xe6,0x01,0x30,0x87,0x70,0x60,0x87,0x79,
    0x28,0x07,0x80,0x60,0x87,0x72,0x98,0x87,0x79,0x68,0x03,0x78,0x90,0x87,0x72,0x18,
    0x87,0x74,0x98,0x87,0x72,0x68,0x03,0x73,0x80,0x87,0x76,0x08,0x07,0x72,0x00,0xcc,
    0x21,0x1c,0xd8,0x61,0x1e,0xca,0x01,0x20,0xdc,0xe1,0x1d,0xda,0xc0,0x1c,0xe4,0x21,
    0x1c,0xda,0xa1,0x1c,0xda,0x00,0x1e,0xde,0x21,0x1d,0xdc,0x81,0x1e,0xca,0x41,0x1e,
    0xda,0xa0,0x1c,0xd8,0x21,0x1d,0xda,0x01,0xa0,0x07,0x79,0xa8,0x87,0x72,0x00,0x06,
    0x77,0x78,0x87,0x36,0x30,0x07,0x79,0x08,0x87,0x76,0x28,0x87,0x36,0x80,0x87,0x77,
    0x48,0x07,0x77,0xa0,0x87,0x72,0x90,0x87,0x36,0x28,0x07,0x76,0x48,0x87,0x76,0x68,
    0x03,0x77,0x78,0x07,0x77,0x68,0x03,0x76,0x28,0x87,0x70,0x30,0x07,0x80,0x70,0x87,
    0x77,0x68,0x83,0x74,0x70,0x07,0x73,0x98,0x87,0x36,0x30,0x07,0x78,0x68,0x83,0x76,
    0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xdc,0xe1,0x1d,
    0xda,0x40,0x1d,0xea,0xa1,0x1d,0xe0,0xa1,0x0d,0xe8,0x21,0x1c,0xc4,0x81,0x1d,0xca,
    0x61,0x1e,0x00,0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x08,0x77,0x78,0x87,0x36,
    0x70,0x87,0x70,0x70,0x87,0x79,0x68,0x03,0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,
    0x07,0x74,0x00,0xe8,0x41,0x1e,0xea,0xa1,0x1c,0x00,0xc2,0x1d,0xde,0xa1,0x0d,0xe6,
    0x21,0x1d,0xce,0xc1,0x1d,0xca,0x81,0x1c,0xda,0x40,0x1f,0xca,0x41,0x1e,0xde,0x61,
    0x1e,0xda,0xc0,0x1c,0xe0,0xa1,0x0d,0xda,0x21,0x1c,0xe8,0x01,0x1d,0x00,0x7a,0x90,
    0x87,0x7a,0x28,0x07,0x80,0x70,0x87,0x77,0x68,0x03,0x7a,0x90,0x87,0x70,0x80,0x07,
    0x78,0x48,0x07,0x77,0x38,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,
    0x1e,0xea,0xa1,0x1c,0x00,0x62,0x1e,0xe8,0x21,0x1c,0xc6,0x61,0x1d,0xda,0x00,0x1e,
    0xe4,0xe1,0x1d,0xe8,0xa1,0x1c,0xc6,0x81,0x1e,0xde,0x41,0x1e,0xda,0x40,0x1c,0xea,
    0xc1,0x1c,0xcc,0xa1,0x1c,0xe4,0xa1,0x0d,0xe6,0x21,0x1d,0xf4,0xa1,0x1c,0x00,0x3c,
    0x00,0x88,0x7a,0x70,0x87,0x79,0x08,0x07,0x73,0x28,0x87,0x36,0x30,0x07,0x78,0x68,
    0x83,0x76,0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xea,
    0x61,0x1e,0xca,0xa1,0x0d,0xe6,0xe1,0x1d,0xcc,0x81,0x1e,0xda,0xc0,0x1c,0xd8,0xe1,
    0x1d,0xc2,0x81,0x1e,0x00,0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x36,0x18,0x42,
    0x01,0x2c,0x40,0x05,0x00,0x49,0x18,0x00,0x00,0x01,0x00,0x00,0x00,0x13,0x84,0x40,
    0x00,0x89,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x32,0x22,0x48,0x09,0x20,0x64,0x85,
    0x04,0x93,0x22,0xa4,0x84,0x04,0x93,0x22,0xe3,0x84,0xa1,0x90,0x14,0x12,0x4c,0x8a,
    0x8c,0x0b,0x84,0xa4,0x4c,0x10,0x44,0x33,0x00,0xc3,0x08,0x04,0x60,0x89,0x10,0x02,
    0x18,0x46,0x10,0x80,0x24,0x08,0x33,0x51,0xf3,0x40,0x0f,0xf2,0x50,0x0f,0xe3,0x40,
    0x0f,0x6e,0xd0,0x0e,0xe5,0x40,0x0f,0xe1,0xc0,0x0e,0x7a,0xa0,0x07,0xed,0x10,0x0e,
    0xf4,0x20,0x0f,0xe9,0x80,0x0f,0x28,0x20,0x07,0x49,0x53,0x44,0x09,0x93,0x5f,0x49,
    0xff,0x03,0x44,0x00,0x23,0x21,0xa1,0x94,0x41,0x04,0x43,0x28,0x86,0x08,0x23,0x80,
    0x43,0x68,0x20,0x60,0x8e,0x00,0x0c,0x52,0x60,0xcd,0x11,0x80,0xc2,0x20,0x42,0x20,
    0x0c,0x23,0x10,0xcb,0x08,0x00,0x00,0x00,0x00,0x13,0xb2,0x70,0x48,0x07,0x79,0xb0,
    0x03,0x3a,0x68,0x83,0x70,0x80,0x07,0x78,0x60,0x87,0x72,0x68,0x83,0x76,0x08,0x87,
    0x71,0x78,0x87,0x79,0xc0,0x87,0x38,0x80,0x03,0x37,0x88,0x83,0x38,0x70,0x03,0x38,
    0xd8,0x70,0x1b,0xe5,0xd0,0x06,0xf0,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,
    0xa0,0x07,0x76,0x40,0x07,0x6d,0x90,0x0e,0x71,0xa0,0x07,0x78,0xa0,0x07,0x78,0xd0,
    0x06,0xe9,0x80,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,0x71,0x60,0x07,
    0x7a,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x6d,0x90,0x0e,0x73,0x20,0x07,0x7a,
    0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x90,0x0e,0x76,0x40,0x07,0x7a,0x60,
    0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0e,0x73,0x20,0x07,0x7a,0x30,0x07,
    0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x60,0x0e,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,
    0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0f,0x71,0x60,0x07,0x7a,0x10,0x07,0x76,0xa0,
    0x07,0x71,0x60,0x07,0x6d,0x60,0x0f,0x72,0x40,0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,
    0x73,0x20,0x07,0x6d,0x60,0x0f,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,0x73,
    0x20,0x07,0x6d,0x60,0x0f,0x74,0x80,0x07,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,
    0x07,0x6d,0x60,0x0f,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,
    0x6d,0x60,0x0f,0x79,0x60,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,
    0x80,0x07,0x6d,0x60,0x0f,0x71,0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xa0,
    0x07,0x71,0x20,0x07,0x78,0xd0,0x06,0xf6,0x10,0x07,0x79,0x20,0x07,0x7a,0x20,0x07,
    0x75,0x60,0x07,0x7a,0x20,0x07,0x75,0x60,0x07,0x6d,0x60,0x0f,0x72,0x50,0x07,0x76,
    0xa0,0x07,0x72,0x50,0x07,0x76,0xa0,0x07,0x72,0x50,0x07,0x76,0xd0,0x06,0xf6,0x50,
    0x07,0x71,0x20,0x07,0x7a,0x50,0x07,0x71,0x20,0x07,0x7a,0x50,0x07,0x71,0x20,0x07,
    0x6d,0x60,0x0f,0x71,0x00,0x07,0x72,0x40,0x07,0x7a,0x10,0x07,0x70,0x20,0x07,0x74,
    0xa0,0x07,0x71,0x00,0x07,0x72,0x40,0x07,0x6d,0xe0,0x0e,0x78,0xa0,0x07,0x71,0x60,
    0x07,0x7a,0x30,0x07,0x72,0x30,0x84,0x49,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
    0xc8,0x02,0x01,0x00,0x00,0x0b,0x00,0x00,0x00,0x32,0x1e,0x98,0x10,0x19,0x11,0x4c,
    0x90,0x8c,0x09,0x26,0x47,0xc6,0x04,0x43,0x5a,0x25,0x30,0x02,0x50,0x04,0x05,0x18,
    0x50,0x08,0x65,0x50,0x80,0x02,0x05,0x51,0x20,0xd4,0x46,0x00,0x88,0x8d,0x25,0x34,
    0x01,0x00,0x00,0x00,0x00,0x79,0x18,0x00,0x00,0x02,0x01,0x00,0x00,0x1a,0x03,0x4c,
    0x10,0x97,0x29,0xa2,0x25,0x10,0xab,0x32,0xb9,0xb9,0xb4,0x37,0xb7,0x21,0xc6,0x32,
    0x28,0x00,0xb3,0x50,0xb9,0x1b,0x43,0x0b,0x93,0xfb,0x9a,0x4b,0xd3,0x2b,0x1b,0x62,
    0x2c,0x81,0x22,0x2c,0x05,0xe7,0x20,0x08,0x0e,0x8e,0xad,0x0c,0xa4,0xad,0x8c,0x2e,
    0x8c,0x0d,0xc4,0xae,0x4c,0x6e,0x2e,0xed,0xcd,0x0d,0x64,0x26,0x06,0x06,0x26,0xc6,
    0xc5,0xc6,0xe6,0x06,0x04,0xa5,0xad,0x8c,0x2e,0x8c,0xcd,0xac,0xac,0x65,0x26,0x06,
    0x06,0x26,0xc6,0xc5,0xc6,0xe6,0xc6,0x45,0x26,0x65,0x88,0xa0,0x10,0x43,0x8c,0x25,
    0x58,0x90,0x45,0x60,0xd1,0x54,0x46,0x17,0xc6,0x36,0x04,0x51,0x8e,0x25,0x58,0x82,
    0x45,0xe0,0x16,0x96,0x26,0xe7,0x32,0xf6,0xd6,0x06,0x97,0xc6,0x56,0xe6,0x42,0x56,
    0xe6,0xf6,0x26,0xd7,0x36,0xf7,0x45,0x96,0x36,0x17,0x26,0xc6,0x56,0x36,0x44,0x50,
    0x12,0x72,0x61,0x69,0x72,0x2e,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x2e,0x66,0x61,
    0x73,0x74,0x5f,0x6d,0x61,0x74,0x68,0x5f,0x65,0x6e,0x61,0x62,0x6c,0x65,0x43,0x04,
    0x65,0x61,0x19,0x84,0xa5,0xc9,0xb9,0x8c,0xbd,0xb5,0xc1,0xa5,0xb1,0x95,0xb9,0x98,
    0xc9,0x85,0xb5,0x95,0x89,0xd5,0x99,0x99,0x95,0xc9,0x7d,0x99,0x95,0xd1,0x8d,0xa1,
    0x7d,0x91,0xa5,0xcd,0x85,0x89,0xb1,0x95,0x0d,0x11,0x94,0x86,0x51,0x58,0x9a,0x9c,
    0x8b,0x5d,0x99,0x1c,0x5d,0x19,0xde,0xd7,0x5b,0x1d,0x1d,0x5c,0x1d,0x1d,0x97,0xba,
    0xb9,0x32,0x39,0x14,0xb6,0xb7,0x31,0x37,0x98,0x14,0x46,0x61,0x69,0x72,0x2e,0x61,
    0x72,0x67,0x5f,0x74,0x79,0x70,0x65,0x5f,0x6e,0x61,0x6d,0x65,0x34,0xcc,0xd8,0xde,
    0xc2,0xe8,0x68,0xc8,0x84,0xa5,0xc9,0xb9,0x84,0xc9,0x9d,0x7d,0xb9,0x85,0xb5,0x95,
    0x51,0xa8,0xb3,0x1b,0xc2,0x28,0x8f,0x02,0x29,0x91,0x22,0x29,0x93,0x42,0x71,0xa9,
    0x9b,0x2b,0x93,0x43,0x61,0x7b,0x1b,0x73,0x8b,0x49,0x61,0x31,0xf6,0xc6,0xf6,0x26,
    0x37,0x84,0x51,0x1e,0xc5,0x52,0x22,0x45,0x52,0x26,0xe5,0x22,0x13,0x96,0x26,0xe7,
    0x02,0xf7,0x36,0x97,0x46,0x97,0xf6,0xe6,0xc6,0xe5,0x8c,0xed,0x0b,0xea,0x6d,0x2e,
    0x8d,0x2e,0xed,0xcd,0x6d,0x88,0xa2,0x64,0x4a,0xa4,0x48,0xca,0xa4,0x68,0x74,0xc2,
    0xd2,0xe4,0x5c,0xe0,0xde,0xd2,0xdc,0xe8,0xbe,0xe6,0xd2,0xf4,0xca,0x58,0x98,0xb1,
    0xbd,0x85,0xd1,0x91,0x39,0x63,0xfb,0x82,0x7a,0x4b,0x73,0xa3,0x9b,0x4a,0xd3,0x2b,
    0x1b,0xa2,0x28,0x9c,0x12,0x29,0x9d,0x32,0x29,0xde,0x10,0x44,0xa9,0x14,0x4c,0xd9,
    0x94,0x8f,0x50,0x58,0x9a,0x9c,0x8b,0x5d,0x99,0x1c,0x5d,0x19,0xde,0x57,0x9a,0x1b,
    0x5c,0x1d,0x1d,0xa5,0xb0,0x34,0x39,0x17,0xb6,0xb7,0xb1,0x30,0xba,0xb4,0x37,0xb7,
    0xaf,0x34,0x37,0xb2,0x32,0x3c,0x7a,0x67,0x65,0x6e,0x65,0x72,0x61,0x74,0x65,0x64,
    0x28,0x5f,0x5f,0x61,0x69,0x72,0x5f,0x70,0x6c,0x61,0x63,0x65,0x68,0x6f,0x6c,0x64,
    0x65,0x72,0x5f,0x5f,0x29,0x44,0xe0,0xde,0xe6,0xd2,0xe8,0xd2,0xde,0xdc,0x86,0x50,
    0x8b,0xa0,0x84,0x81,0x22,0x06,0x8b,0xb0,0x04,0xca,0x18,0x28,0x91,0x22,0x29,0x93,
    0x42,0x06,0x34,0xcc,0xd8,0xde,0xc2,0xe8,0x64,0x98,0xd0,0x95,0xe1,0x8d,0xbd,0xbd,
    0xc9,0x91,0xc1,0x0c,0xa1,0x96,0x40,0x09,0x03,0x45,0x0c,0x96,0x60,0x09,0x94,0x31,
    0x50,0x22,0xc5,0x0c,0x94,0x49,0x39,0x03,0x1a,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x43,
    0xa8,0x65,0x50,0xc2,0x40,0x11,0x83,0x65,0x58,0x02,0x65,0x0c,0x94,0x48,0x91,0x94,
    0x49,0x49,0x03,0x16,0x70,0x73,0x69,0x7a,0x65,0x43,0xa8,0xc5,0x50,0xc2,0x40,0x11,
    0x83,0xc5,0x58,0x02,0x65,0x0c,0x94,0x48,0xe9,0x94,0x49,0x59,0x03,0x2a,0x61,0x69,
    0x72,0x2e,0x62,0x75,0x66,0x66,0x65,0x72,0x7c,0xc2,0xd2,0xe4,0x5c,0xc4,0xea,0xcc,
    0xcc,0xca,0xe4,0xbe,0xe6,0xd2,0xf4,0xca,0x88,0x84,0xa5,0xc9,0xb9,0xc8,0x95,0x85,
    0x91,0x91,0x0a,0x4b,0x93,0x73,0x99,0xa3,0x93,0xab,0x1b,0xa3,0xfb,0xa2,0xcb,0x83,
    0x2b,0xfb,0x4a,0x73,0x33,0x7b,0x23,0x62,0xc6,0xf6,0x16,0x46,0x47,0x83,0x47,0xc3,
    0xa1,0xcd,0x0e,0x8e,0x02,0x5d,0xdb,0x10,0x6a,0x11,0x16,0x62,0x11,0x94,0x38,0x50,
    0xe4,0x60,0x21,0x16,0x62,0x11,0x94,0x38,0x50,0xe6,0x80,0x51,0x58,0x9a,0x9c,0x4b,
    0x98,0xdc,0xd9,0x17,0x5d,0x1e,0x5c,0xd9,0xd7,0x5c,0x9a,0x5e,0x19,0xaf,0xb0,0x34,
    0x39,0x97,0x30,0xb9,0xb3,0x2f,0xba,0x3c,0xb8,0xb2,0xaf,0x30,0xb6,0xb4,0x33,0xb7,
    0xaf,0xb9,0x34,0xbd,0x32,0x26,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x1c,
    0xbe,0x62,0x72,0x86,0x90,0xc1,0x52,0x28,0x6d,0xa0,0xb8,0xc1,0x72,0x28,0x62,0xb0,
    0x08,0x4b,0xa0,0xbc,0x81,0x02,0x07,0x0a,0x1d,0x28,0x75,0xb0,0x1c,0x8a,0x1d,0x2c,
    0x89,0x12,0x29,0x77,0xa0,0x4c,0x0a,0x1e,0x0c,0x51,0x94,0x32,0x50,0xd0,0x40,0x51,
    0x03,0x85,0x0d,0x94,0x3c,0x18,0x62,0x24,0x80,0x02,0x06,0x8a,0x1e,0xf0,0x79,0x6b,
    0x73,0x4b,0x83,0x7b,0xa3,0x2b,0x73,0xa3,0x03,0x19,0x43,0x0b,0x93,0xe3,0x33,0x95,
    0xd6,0x06,0xc7,0x56,0x06,0x32,0xb4,0xb2,0x02,0x42,0x25,0x14,0x14,0x34,0x44,0x50,
    0xfa,0x60,0x88,0xa1,0xf0,0x81,0xe2,0x07,0x8d,0x32,0xc4,0x50,0xfe,0x40,0xf9,0x83,
    0x46,0x19,0x11,0xb1,0x03,0x3b,0xd8,0x43,0x3b,0xb8,0x41,0x3b,0xbc,0x03,0x39,0xd4,
    0x03,0x3b,0x94,0x83,0x1b,0x98,0x03,0x3b,0x84,0xc3,0x39,0xcc,0xc3,0x14,0x21,0x18,
    0x46,0x28,0xec,0xc0,0x0e,0xf6,0xd0,0x0e,0x6e,0x90,0x0e,0xe4,0x50,0x0e,0xee,0x40,
    0x0f,0x53,0x82,0x62,0xc4,0x12,0x0e,0xe9,0x20,0x0f,0x6e,0x60,0x0f,0xe5,0x20,0x0f,
    0xf3,0x90,0x0e,0xef,0xe0,0x0e,0x53,0x02,0x63,0x04,0x15,0x0e,0xe9,0x20,0x0f,0x6e,
    0xc0,0x0e,0xe1,0xe0,0x0e,0xe7,0x50,0x0f,0xe1,0x70,0x0e,0xe5,0xf0,0x0b,0xf6,0x50,
    0x0e,0xf2,0x30,0x0f,0xe9,0xf0,0x0e,0xee,0x30,0x25,0x40,0x46,0x4c,0xe1,0x90,0x0e,
    0xf2,0xe0,0x06,0xe3,0xf0,0x0e,0xed,0x00,0x0f,0xe9,0xc0,0x0e,0xe5,0xf0,0x0b,0xef,
    0x00,0x0f,0xf4,0x90,0x0e,0xef,0xe0,0x0e,0xf3,0x30,0x65,0x50,0x18,0x67,0x84,0x12,
    0x0e,0xe9,0x20,0x0f,0x6e,0x60,0x0f,0xe5,0x20,0x0f,0xf4,0x50,0x0e,0xf8,0x30,0x25,
    0xd8,0x03,0x00,0x00,0x00,0x79,0x18,0x00,0x00,0x7b,0x00,0x00,0x00,0x33,0x08,0x80,
    0x1c,0xc4,0xe1,0x1c,0x66,0x14,0x01,0x3d,0x88,0x43,0x38,0x84,0xc3,0x8c,0x42,0x80,
    0x07,0x79,0x78,0x07,0x73,0x98,0x71,0x0c,0xe6,0x00,0x0f,0xed,0x10,0x0e,0xf4,0x80,
    0x0e,0x33,0x0c,0x42,0x1e,0xc2,0xc1,0x1d,0xce,0xa1,0x1c,0x66,0x30,0x05,0x3d,0x88,
    0x43,0x38,0x84,0x83,0x1b,0xcc,0x03,0x3d,0xc8,0x43,0x3d,0x8c,0x03,0x3d,0xcc,0x78,
    0x8c,0x74,0x70,0x07,0x7b,0x08,0x07,0x79,0x48,0x87,0x70,0x70,0x07,0x7a,0x70,0x03,
    0x76,0x78,0x87,0x70,0x20,0x87,0x19,0xcc,0x11,0x0e,0xec,0x90,0x0e,0xe1,0x30,0x0f,
    0x6e,0x30,0x0f,0xe3,0xf0,0x0e,0xf0,0x50,0x0e,0x33,0x10,0xc4,0x1d,0xde,0x21,0x1c,
    0xd8,0x21,0x1d,0xc2,0x61,0x1e,0x66,0x30,0x89,0x3b,0xbc,0x83,0x3b,0xd0,0x43,0x39,
    0xb4,0x03,0x3c,0xbc,0x83,0x3c,0x84,0x03,0x3b,0xcc,0xf0,0x14,0x76,0x60,0x07,0x7b,
    0x68,0x07,0x37,0x68,0x87,0x72,0x68,0x07,0x37,0x80,0x87,0x70,0x90,0x87,0x70,0x60,
    0x07,0x76,0x28,0x07,0x76,0xf8,0x05,0x76,0x78,0x87,0x77,0x80,0x87,0x5f,0x08,0x87,
    0x71,0x18,0x87,0x72,0x98,0x87,0x79,0x98,0x81,0x2c,0xee,0xf0,0x0e,0xee,0xe0,0x0e,
    0xf5,0xc0,0x0e,0xec,0x30,0x03,0x62,0xc8,0xa1,0x1c,0xe4,0xa1,0x1c,0xcc,0xa1,0x1c,
    0xe4,0xa1,0x1c,0xdc,0x61,0x1c,0xca,0x21,0x1c,0xc4,0x81,0x1d,0xca,0x61,0x06,0xd6,
    0x90,0x43,0x39,0xc8,0x43,0x39,0x98,0x43,0x39,0xc8,0x43,0x39,0xb8,0xc3,0x38,0x94,
    0x43,0x38,0x88,0x03,0x3b,0x94,0xc3,0x2f,0xbc,0x83,0x3c,0xfc,0x82,0x3b,0xd4,0x03,
    0x3b,0xb0,0xc3,0x0c,0xc7,0x69,0x87,0x70,0x58,0x87,0x72,0x70,0x83,0x74,0x68,0x07,
    0x78,0x60,0x87,0x74,0x18,0x87,0x74,0xa0,0x87,0x19,0xce,0x53,0x0f,0xee,0x00,0x0f,
    0xf2,0x50,0x0e,0xe4,0x90,0x0e,0xe3,0x40,0x0f,0xe1,0x20,0x0e,0xec,0x50,0x0e,0x33,
    0x20,0x28,0x1d,0xdc,0xc1,0x1e,0xc2,0x41,0x1e,0xd2,0x21,0x1c,0xdc,0x81,0x1e,0xdc,
    0xe0,0x1c,0xe4,0xe1,0x1d,0xea,0x01,0x1e,0x66,0x18,0x51,0x38,0xb0,0x43,0x3a,0x9c,
    0x83,0x3b,0xcc,0x50,0x24,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x60,0x87,0x77,0x78,
    0x07,0x78,0x98,0x51,0x4c,0xf4,0x90,0x0f,0xf0,0x50,0x0e,0x33,0x1e,0x6a,0x1e,0xca,
    0x61,0x1c,0xe8,0x21,0x1d,0xde,0xc1,0x1d,0x7e,0x01,0x1e,0xe4,0xa1,0x1c,0xcc,0x21,
    0x1d,0xf0,0x61,0x06,0x54,0x85,0x83,0x38,0xcc,0xc3,0x3b,0xb0,0x43,0x3d,0xd0,0x43,
    0x39,0xfc,0xc2,0x3c,0xe4,0x43,0x3b,0x88,0xc3,0x3b,0xb0,0xc3,0x8c,0xc5,0x0a,0x87,
    0x79,0x98,0x87,0x77,0x18,0x87,0x74,0x08,0x07,0x7a,0x28,0x07,0x72,0x98,0x81,0x5c,
    0xe3,0x10,0x0e,0xec,0xc0,0x0e,0xe5,0x50,0x0e,0xf3,0x30,0x23,0xc1,0xd2,0x41,0x1e,
    0xe4,0xe1,0x17,0xd8,0xe1,0x1d,0xde,0x01,0x1e,0x66,0x50,0x59,0x38,0xa4,0x83,0x3c,
    0xb8,0x81,0x39,0xd4,0x83,0x3b,0x8c,0x03,0x3d,0xa4,0xc3,0x3b,0xb8,0xc3,0x2f,0x9c,
    0x83,0x3c,0xbc,0x43,0x3d,0xc0,0xc3,0x3c,0x00,0x71,0x20,0x00,0x00,0x02,0x00,0x00,
    0x00,0x06,0x50,0x30,0x00,0xd2,0xd0,0x00,0x00,0x61,0x20,0x00,0x00,0x3e,0x00,0x00,
    0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0xf4,0xc6,0x22,
    0x86,0x61,0x18,0xc6,0x22,0x04,0x41,0x10,0xc6,0x22,0x82,0x20,0x08,0xa8,0x95,0x40,
    0x19,0x14,0x01,0xbd,0x11,0x00,0x1a,0x33,0x00,0x24,0x66,0x00,0x28,0xcc,0x00,0x00,
    0x00,0xe3,0x15,0x4b,0x94,0x65,0x11,0x05,0x65,0x90,0x21,0x1a,0x0c,0x13,0x02,0xf9,
    0x8c,0x57,0x3c,0x55,0xd7,0x2d,0x14,0x94,0x41,0x86,0xea,0x70,0x4c,0x08,0xe4,0x63,
    0x41,0x01,0x9f,0xf1,0x0a,0x4a,0x13,0x03,0x31,0x70,0x28,0x28,0x83,0x0c,0x1a,0x43,
    0x99,0x10,0xc8,0xc7,0x8a,0x00,0x3e,0xe3,0x15,0xd9,0x77,0x06,0x67,0x40,0x51,0x50,
    0x06,0x19,0xbe,0x48,0x33,0x21,0x90,0x8f,0x15,0x01,0x7c,0xc6,0x2b,0x3c,0x32,0x68,
    0x03,0x36,0x20,0x03,0x0a,0xca,0x20,0xc3,0x18,0x60,0x99,0x09,0x81,0x7c,0xc6,0x2b,
    0xc4,0x00,0x0d,0xe2,0x00,0x0e,0x3c,0x0a,0xca,0x20,0xc3,0x19,0x70,0x61,0x60,0x42,
    0x20,0x1f,0x0b,0x0a,0xf8,0x8c,0x57,0x9c,0x41,0x1b,0xd8,0x41,0x1d,0x88,0x01,0x05,
    0xc5,0x86,0x00,0x3e,0xb3,0x0d,0x61,0x10,0x00,0xb3,0x0d,0x41,0x1b,0x04,0xb3,0x0d,
    0xc1,0x23,0xcc,0x36,0x04,0x6e,0x30,0x64,0x10,0x10,0x03,0x00,0x00,0x09,0x00,0x00,
    0x00,0x5b,0x86,0x20,0x00,0x85,0x2d,0x43,0x11,0x80,0xc2,0x96,0x41,0x09,0x40,0x61,
    0xcb,0xf0,0x04,0xa0,0xb0,0x65,0xa0,0x02,0x50,0xd8,0x32,0x60,0x01,0x28,0x6c,0x19,
    0xba,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,
};
static const uint8_t _sgl_fs_bytecode_metal_macos[2825] = {
    0x4d,0x54,0x4c,0x42,0x01,0x80,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x09,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x30,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,
    0x4e,0x41,0x4d,0x45,0x06,0x00,0x6d,0x61,0x69,0x6e,0x30,0x00,0x54,0x59,0x50,0x45,
    0x01,0x00,0x01,0x48,0x41,0x53,0x48,0x20,0x00,0xb9,0x65,0x80,0x88,0xa2,0xc8,0x18,
    0x8d,0x2a,0x38,0xc1,0x87,0xa4,0x7f,0x35,0x83,0x69,0xdc,0x8c,0xcb,0x7b,0x11,0x67,
    0x89,0xc7,0xf0,0x8a,0x99,0x36,0x06,0xc5,0x90,0x4f,0x46,0x46,0x54,0x18,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x45,0x52,0x53,0x08,0x00,0x01,0x00,0x08,
    0x00,0x01,0x00,0x01,0x00,0x45,0x4e,0x44,0x54,0x04,0x00,0x00,0x00,0x45,0x4e,0x44,
    0x54,0x04,0x00,0x00,0x00,0x45,0x4e,0x44,0x54,0xde,0xc0,0x17,0x0b,0x00,0x00,0x00,
    0x00,0x14,0x00,0x00,0x00,0x10,0x0a,0x00,0x00,0xff,0xff,0xff,0xff,0x42,0x43,0xc0,
    0xde,0x21,0x0c,0x00,0x00,0x81,0x02,0x00,0x00,0x0b,0x82,0x20,0x00,0x02,0x00,0x00,
    0x00,0x12,0x00,0x00,0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,
    0x39,0x92,0x01,0x84,0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,
    0x02,0x42,0x92,0x0b,0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,
    0x24,0x48,0x0a,0x90,0x21,0x23,0xc4,0x52,0x80,0x0c,0x19,0x21,0x72,0x24,0x07,0xc8,
    0x48,0x11,0x62,0xa8,0xa0,0xa8,0x40,0xc6,0xf0,0x01,0x00,0x00,0x00,0x51,0x18,0x00,
    0x00,0x89,0x00,0x00,0x00,0x1b,0xcc,0x25,0xf8,0xff,0xff,0xff,0xff,0x01,0x60,0x00,
    0x09,0xa8,0x88,0x71,0x78,0x07,0x79,0x90,0x87,0x72,0x18,0x07,0x7a,0x60,0x87,0x7c,
    0x68,0x03,0x79,0x78,0x87,0x7a,0x70,0x07,0x72,0x28,0x07,0x72,0x68,0x03,0x72,0x48,
    0x07,0x7b,0x48,0x07,0x72,0x28,0x87,0x36,0x98,0x87,0x78,0x90,0x07,0x7a,0x68,0x03,
    0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xcc,0x21,0x1c,0xd8,0x61,
    0x1e,0xca,0x01,0x20,0xc8,0x21,0x1d,0xe6,0x21,0x1c,0xc4,0x81,0x1d,0xca,0xa1,0x0d,
    0xe8,0x21,0x1c,0xd2,0x81,0x1d,0xda,0x60,0x1c,0xc2,0x81,0x1d,0xd8,0x61,0x1e,0x00,
    0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x08,0x76,0x28,0x87,0x79,0x98,0x87,0x36,
    0x80,0x07,0x79,0x28,0x87,0x71,0x48,0x87,0x79,0x28,0x87,0x36,0x30,0x07,0x78,0x68,
    0x87,0x70,0x20,0x07,0xc0,0x1c,0xc2,0x81,0x1d,0xe6,0xa1,0x1c,0x00,0xc2,0x1d,0xde,
    0xa1,0x0d,0xcc,0x41,0x1e,0xc2,0xa1,0x1d,0xca,0xa1,0x0d,0xe0,0xe1,0x1d,0xd2,0xc1,
    0x1d,0xe8,0xa1,0x1c,0xe4,0xa1,0x0d,0xca,0x81,0x1d,0xd2,0xa1,0x1d,0x00,0x7a,0x90,
    0x87,0x7a,0x28,0x07,0x60,0x70,0x87,0x77,0x68,0x03,0x73,0x90,0x87,0x70,0x68,0x87,
    0x72,0x68,0x03,0x78,0x78,0x87,0x74,0x70,0x07,0x7a,0x28,0x07,0x79,0x68,0x83,0x72,
    0x60,0x87,0x74,0x68,0x87,0x36,0x70,0x87,0x77,0x70,0x87,0x36,0x60,0x87,0x72,0x08,
    0x07,0x73,0x00,0x08,0x77,0x78,0x87,0x36,0x48,0x07,0x77,0x30,0x87,0x79,0x68,0x03,
    0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,0x1e,0xea,0xa1,
    0x1c,0x00,0xc2,0x1d,0xde,0xa1,0x0d,0xd4,0xa1,0x1e,0xda,0x01,0x1e,0xda,0x80,0x1e,
    0xc2,0x41,0x1c,0xd8,0xa1,0x1c,0xe6,0x01,0x30,0x87,0x70,0x60,0x87,0x79,0x28,0x07,
    0x80,0x70,0x87,0x77,0x68,0x03,0x77,0x08,0x07,0x77,0x98,0x87,0x36,0x30,0x07,0x78,
    0x68,0x83,0x76,0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,
    0xdc,0xe1,0x1d,0xda,0x60,0x1e,0xd2,0xe1,0x1c,0xdc,0xa1,0x1c,0xc8,0xa1,0x0d,0xf4,
    0xa1,0x1c,0xe4,0xe1,0x1d,0xe6,0xa1,0x0d,0xcc,0x01,0x1e,0xda,0xa0,0x1d,0xc2,0x81,
    0x1e,0xd0,0x01,0xa0,0x07,0x79,0xa8,0x87,0x72,0x00,0x08,0x77,0x78,0x87,0x36,0xa0,
    0x07,0x79,0x08,0x07,0x78,0x80,0x87,0x74,0x70,0x87,0x73,0x68,0x83,0x76,0x08,0x07,
    0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xe6,0x81,0x1e,0xc2,0x61,
    0x1c,0xd6,0xa1,0x0d,0xe0,0x41,0x1e,0xde,0x81,0x1e,0xca,0x61,0x1c,0xe8,0xe1,0x1d,
    0xe4,0xa1,0x0d,0xc4,0xa1,0x1e,0xcc,0xc1,0x1c,0xca,0x41,0x1e,0xda,0x60,0x1e,0xd2,
    0x41,0x1f,0xca,0x01,0xc0,0x03,0x80,0xa8,0x07,0x77,0x98,0x87,0x70,0x30,0x87,0x72,
    0x68,0x03,0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,0x1e,
    0xea,0xa1,0x1c,0x00,0xa2,0x1e,0xe6,0xa1,0x1c,0xda,0x60,0x1e,0xde,0xc1,0x1c,0xe8,
    0xa1,0x0d,0xcc,0x81,0x1d,0xde,0x21,0x1c,0xe8,0x01,0x30,0x87,0x70,0x60,0x87,0x79,
    0x28,0x07,0x60,0x83,0x21,0x0c,0xc0,0x02,0x54,0x1b,0x8c,0x81,0x00,0x16,0xa0,0xda,
    0x80,0x10,0xff,0xff,0xff,0xff,0x3f,0x00,0x0c,0x20,0x01,0xd5,0x06,0xa3,0x08,0x80,
    0x05,0xa8,0x36,0x18,0x86,0x00,0x2c,0x40,0x05,0x49,0x18,0x00,0x00,0x03,0x00,0x00,
    0x00,0x13,0x86,0x40,0x18,0x26,0x0c,0x44,0x61,0x00,0x00,0x00,0x00,0x89,0x20,0x00,
    0x00,0x1d,0x00,0x00,0x00,0x32,0x22,0x48,0x09,0x20,0x64,0x85,0x04,0x93,0x22,0xa4,
    0x84,0x04,0x93,0x22,0xe3,0x84,0xa1,0x90,0x14,0x12,0x4c,0x8a,0x8c,0x0b,0x84,0xa4,
    0x4c,0x10,0x48,0x33,0x00,0xc3,0x08,0x04,0x60,0x83,0x70,0x94,0x34,0x45,0x94,0x30,
    0xf9,0xff,0x44,0x5c,0x13,0x15,0x11,0xbf,0x3d,0xfc,0xd3,0x18,0x01,0x30,0x88,0x30,
    0x04,0x17,0x49,0x53,0x44,0x09,0x93,0xff,0x4b,0x00,0xf3,0x2c,0x44,0xf4,0x4f,0x63,
    0x04,0xc0,0x20,0x42,0x21,0x94,0x42,0x84,0x40,0x0c,0x9d,0x61,0x04,0x01,0x98,0x23,
    0x08,0xe6,0x08,0xc0,0x60,0x18,0x41,0x58,0x0a,0x12,0x88,0x49,0x8a,0x29,0x40,0x6d,
    0x20,0x20,0x05,0xd6,0x08,0x00,0x00,0x00,0x00,0x13,0xb2,0x70,0x48,0x07,0x79,0xb0,
    0x03,0x3a,0x68,0x83,0x70,0x80,0x07,0x78,0x60,0x87,0x72,0x68,0x83,0x76,0x08,0x87,
    0x71,0x78,0x87,0x79,0xc0,0x87,0x38,0x80,0x03,0x37,0x88,0x83,0x38,0x70,0x03,0x38,
    0xd8,0x70,0x1b,0xe5,0xd0,0x06,0xf0,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,
    0xa0,0x07,0x76,0x40,0x07,0x6d,0x90,0x0e,0x71,0xa0,0x07,0x78,0xa0,0x07,0x78,0xd0,
    0x06,0xe9,0x80,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,0x71,0x60,0x07,
    0x7a,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x6d,0x90,0x0e,0x73,0x20,0x07,0x7a,
    0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x90,0x0e,0x76,0x40,0x07,0x7a,0x60,
    0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0e,0x73,0x20,0x07,0x7a,0x30,0x07,
    0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x60,0x0e,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,
    0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0f,0x71,0x60,0x07,0x7a,0x10,0x07,0x76,0xa0,
    0x07,0x71,0x60,0x07,0x6d,0x60,0x0f,0x72,0x40,0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,
    0x73,0x20,0x07,0x6d,0x60,0x0f,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,0x73,
    0x20,0x07,0x6d,0x60,0x0f,0x74,0x80,0x07,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,
    0x07,0x6d,0x60,0x0f,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,
    0x6d,0x60,0x0f,0x79,0x60,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,
    0x80,0x07,0x6d,0x60,0x0f,0x71,0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xa0,
    0x07,0x71,0x20,0x07,0x78,0xd0,0x06,0xf6,0x10,0x07,0x79,0x20,0x07,0x7a,0x20,0x07,
    0x75,0x60,0x07,0x7a,0x20,0x07,0x75,0x60,0x07,0x6d,0x60,0x0f,0x72,0x50,0x07,0x76,
    0xa0,0x07,0x72,0x50,0x07,0x76,0xa0,0x07,0x72,0x50,0x07,0x76,0xd0,0x06,0xf6,0x50,
    0x07,0x71,0x20,0x07,0x7a,0x50,0x07,0x71,0x20,0x07,0x7a,0x50,0x07,0x71,0x20,0x07,
    0x6d,0x60,0x0f,0x71,0x00,0x07,0x72,0x40,0x07,0x7a,0x10,0x07,0x70,0x20,0x07,0x74,
    0xa0,0x07,0x71,0x00,0x07,0x72,0x40,0x07,0x6d,0xe0,0x0e,0x78,0xa0,0x07,0x71,0x60,
    0x07,0x7a,0x30,0x07,0x72,0x30,0x84,0x41,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,
    0x18,0xc2,0x38,0x40,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x64,0x81,0x00,0x00,0x00,
    0x00,0x08,0x00,0x00,0x00,0x32,0x1e,0x98,0x10,0x19,0x11,0x4c,0x90,0x8c,0x09,0x26,
    0x47,0xc6,0x04,0x43,0x5a,0x25,0x30,0x02,0x50,0x04,0x85,0x50,0x10,0x65,0x40,0x70,
    0x2c,0xa1,0x09,0x00,0x00,0x79,0x18,0x00,0x00,0xb7,0x00,0x00,0x00,0x1a,0x03,0x4c,
    0x10,0x97,0x29,0xa2,0x25,0x10,0xab,0x32,0xb9,0xb9,0xb4,0x37,0xb7,0x21,0xc6,0x42,
    0x3c,0x00,0x84,0x50,0xb9,0x1b,0x43,0x0b,0x93,0xfb,0x9a,0x4b,0xd3,0x2b,0x1b,0x62,
    0x2c,0xc2,0x23,0x2c,0x05,0xe7,0x20,0x08,0x0e,0x8e,0xad,0x0c,0xa4,0xad,0x8c,0x2e,
    0x8c,0x0d,0xc4,0xae,0x4c,0x6e,0x2e,0xed,0xcd,0x0d,0x64,0x26,0x06,0x06,0x26,0xc6,
    0xc5,0xc6,0xe6,0x06,0x04,0xa5,0xad,0x8c,0x2e,0x8c,0xcd,0xac,0xac,0x65,0x26,0x06,
    0x06,0x26,0xc6,0xc5,0xc6,0xe6,0xc6,0x45,0x26,0x65,0x88,0xf0,0x10,0x43,0x8c,0x45,
    0x58,0x8c,0x65,0x60,0xd1,0x54,0x46,0x17,0xc6,0x36,0x04,0x79,0x8e,0x45,0x58,0x84,
    0x65,0xe0,0x16,0x96,0x26,0xe7,0x32,0xf6,0xd6,0x06,0x97,0xc6,0x56,0xe6,0x42,0x56,
    0xe6,0xf6,0x26,0xd7,0x36,0xf7,0x45,0x96,0x36,0x17,0x26,0xc6,0x56,0x36,0x44,0x78,
    0x12,0x72,0x61,0x69,0x72,0x2e,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x2e,0x66,0x61,
    0x73,0x74,0x5f,0x6d,0x61,0x74,0x68,0x5f,0x65,0x6e,0x61,0x62,0x6c,0x65,0x43,0x84,
    0x67,0x61,0x19,0x84,0xa5,0xc9,0xb9,0x8c,0xbd,0xb5,0xc1,0xa5,0xb1,0x95,0xb9,0x98,
    0xc9,0x85,0xb5,0x95,0x89,0xd5,0x99,0x99,0x95,0xc9,0x7d,0x99,0x95,0xd1,0x8d,0xa1,
    0x7d,0x91,0xa5,0xcd,0x85,0x89,0xb1,0x95,0x0d,0x11,0x9e,0x86,0x51,0x58,0x9a,0x9c,
    0x8b,0x5c,0x99,0x1b,0x59,0x99,0xdc,0x17,0x5d,0x98,0xdc,0x59,0x19,0x1d,0xa3,0xb0,
    0x34,0x39,0x97,0x30,0xb9,0xb3,0x2f,0xba,0x3c,0xb8,0xb2,0x2f,0xb7,0xb0,0xb6,0x32,
    0x1a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x64,0xc2,0xd2,0xe4,0x5c,0xc2,0xe4,0xce,0xbe,
    0xdc,0xc2,0xda,0xca,0xa8,0x98,0xc9,0x85,0x9d,0x7d,0x8d,0xbd,0xb1,0xbd,0xc9,0x0d,
    0x61,0x9e,0x67,0x19,0x1e,0xe8,0x89,0x1e,0xe9,0x99,0x86,0x08,0x0f,0x45,0x29,0x2c,
    0x4d,0xce,0xc5,0x4c,0x2e,0xec,0xac,0xad,0xcc,0x8d,0xee,0x2b,0xcd,0x0d,0xae,0x8e,
    0x8e,0x4b,0xdd,0x5c,0x99,0x1c,0x0a,0xdb,0xdb,0x98,0x1b,0x4c,0x0a,0x95,0xb0,0x34,
    0x39,0x97,0xb1,0x32,0x37,0xba,0x32,0x39,0x3e,0x61,0x69,0x72,0x2e,0x70,0x65,0x72,
    0x73,0x70,0x65,0x63,0x74,0x69,0x76,0x65,0x14,0xea,0xec,0x86,0x48,0xcb,0xf0,0x58,
    0xcf,0xf5,0x60,0x4f,0xf6,0x40,0x4f,0xf4,0x48,0x8f,0xc6,0xa5,0x6e,0xae,0x4c,0x0e,
    0x85,0xed,0x6d,0xcc,0x2d,0x26,0x85,0xc5,0xd8,0x1b,0xdb,0x9b,0xdc,0x10,0x69,0x11,
    0x1e,0xeb,0xe1,0x1e,0xec,0xc9,0x1e,0xe8,0x89,0x1e,0xe9,0xe9,0xb8,0x84,0xa5,0xc9,
    0xb9,0xd0,0x95,0xe1,0xd1,0xd5,0xc9,0x95,0x51,0x0a,0x4b,0x93,0x73,0x61,0x7b,0x1b,
    0x0b,0xa3,0x4b,0x7b,0x73,0xfb,0x4a,0x73,0x23,0x2b,0xc3,0xa3,0x12,0x96,0x26,0xe7,
    0x32,0x17,0xd6,0x06,0xc7,0x56,0x46,0x8c,0xae,0x0c,0x8f,0xae,0x4e,0xae,0x4c,0x86,
    0x8c,0xc7,0x8c,0xed,0x2d,0x8c,0x8e,0x05,0x64,0x2e,0xac,0x0d,0x8e,0xad,0xcc,0x87,
    0x03,0x5d,0x19,0xde,0x10,0x6a,0x21,0x9e,0xef,0x01,0x83,0x65,0x58,0x84,0x27,0x0c,
    0x1e,0xe8,0x11,0x83,0x47,0x7a,0xc6,0x80,0x4b,0x58,0x9a,0x9c,0xcb,0x5c,0x58,0x1b,
    0x1c,0x5b,0x99,0x1c,0x8f,0xb9,0xb0,0x36,0x38,0xb6,0x32,0x39,0x0e,0x73,0x6d,0x70,
    0x43,0xa4,0xe5,0x78,0xca,0xe0,0x01,0x83,0x65,0x58,0x84,0x07,0x7a,0xcc,0xe0,0x91,
    0x9e,0x33,0x18,0x82,0x3c,0xdb,0xe3,0x3d,0x64,0xf0,0xa0,0xc1,0x10,0x03,0x01,0x9e,
    0xea,0x49,0x83,0x11,0x11,0x3b,0xb0,0x83,0x3d,0xb4,0x83,0x1b,0xb4,0xc3,0x3b,0x90,
    0x43,0x3d,0xb0,0x43,0x39,0xb8,0x81,0x39,0xb0,0x43,0x38,0x9c,0xc3,0x3c,0x4c,0x11,
    0x82,0x61,0x84,0xc2,0x0e,0xec,0x60,0x0f,0xed,0xe0,0x06,0xe9,0x40,0x0e,0xe5,0xe0,
    0x0e,0xf4,0x30,0x25,0x28,0x46,0x2c,0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xf6,0x50,0x0e,
    0xf2,0x30,0x0f,0xe9,0xf0,0x0e,0xee,0x30,0x25,0x30,0x46,0x50,0xe1,0x90,0x0e,0xf2,
    0xe0,0x06,0xec,0x10,0x0e,0xee,0x70,0x0e,0xf5,0x10,0x0e,0xe7,0x50,0x0e,0xbf,0x60,
    0x0f,0xe5,0x20,0x0f,0xf3,0x90,0x0e,0xef,0xe0,0x0e,0x53,0x02,0x64,0xc4,0x14,0x0e,
    0xe9,0x20,0x0f,0x6e,0x30,0x0e,0xef,0xd0,0x0e,0xf0,0x90,0x0e,0xec,0x50,0x0e,0xbf,
    0xf0,0x0e,0xf0,0x40,0x0f,0xe9,0xf0,0x0e,0xee,0x30,0x0f,0x53,0x06,0x85,0x71,0x46,
    0x30,0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xe6,0x20,0x0f,0xe1,0x70,0x0e,0xed,0x50,0x0e,
    0xee,0x40,0x0f,0x53,0x02,0x35,0x00,0x00,0x00,0x79,0x18,0x00,0x00,0x7b,0x00,0x00,
    0x00,0x33,0x08,0x80,0x1c,0xc4,0xe1,0x1c,0x66,0x14,0x01,0x3d,0x88,0x43,0x38,0x84,
    0xc3,0x8c,0x42,0x80,0x07,0x79,0x78,0x07,0x73,0x98,0x71,0x0c,0xe6,0x00,0x0f,0xed,
    0x10,0x0e,0xf4,0x80,0x0e,0x33,0x0c,0x42,0x1e,0xc2,0xc1,0x1d,0xce,0xa1,0x1c,0x66,
    0x30,0x05,0x3d,0x88,0x43,0x38,0x84,0x83,0x1b,0xcc,0x03,0x3d,0xc8,0x43,0x3d,0x8c,
    0x03,0x3d,0xcc,0x78,0x8c,0x74,0x70,0x07,0x7b,0x08,0x07,0x79,0x48,0x87,0x70,0x70,
    0x07,0x7a,0x70,0x03,0x76,0x78,0x87,0x70,0x20,0x87,0x19,0xcc,0x11,0x0e,0xec,0x90,
    0x0e,0xe1,0x30,0x0f,0x6e,0x30,0x0f,0xe3,0xf0,0x0e,0xf0,0x50,0x0e,0x33,0x10,0xc4,
    0x1d,0xde,0x21,0x1c,0xd8,0x21,0x1d,0xc2,0x61,0x1e,0x66,0x30,0x89,0x3b,0xbc,0x83,
    0x3b,0xd0,0x43,0x39,0xb4,0x03,0x3c,0xbc,0x83,0x3c,0x84,0x03,0x3b,0xcc,0xf0,0x14,
    0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x68,0x87,0x72,0x68,0x07,0x37,0x80,0x87,0x70,
    0x90,0x87,0x70,0x60,0x07,0x76,0x28,0x07,0x76,0xf8,0x05,0x76,0x78,0x87,0x77,0x80,
    0x87,0x5f,0x08,0x87,0x71,0x18,0x87,0x72,0x98,0x87,0x79,0x98,0x81,0x2c,0xee,0xf0,
    0x0e,0xee,0xe0,0x0e,0xf5,0xc0,0x0e,0xec,0x30,0x03,0x62,0xc8,0xa1,0x1c,0xe4,0xa1,
    0x1c,0xcc,0xa1,0x1c,0xe4,0xa1,0x1c,0xdc,0x61,0x1c,0xca,0x21,0x1c,0xc4,0x81,0x1d,
    0xca,0x61,0x06,0xd6,0x90,0x43,0x39,0xc8,0x43,0x39,0x98,0x43,0x39,0xc8,0x43,0x39,
    0xb8,0xc3,0x38,0x94,0x43,0x38,0x88,0x03,0x3b,0x94,0xc3,0x2f,0xbc,0x83,0x3c,0xfc,
    0x82,0x3b,0xd4,0x03,0x3b,0xb0,0xc3,0x0c,0xc7,0x69,0x87,0x70,0x58,0x87,0x72,0x70,
    0x83,0x74,0x68,0x07,0x78,0x60,0x87,0x74,0x18,0x87,0x74,0xa0,0x87,0x19,0xce,0x53,
    0x0f,0xee,0x00,0x0f,0xf2,0x50,0x0e,0xe4,0x90,0x0e,0xe3,0x40,0x0f,0xe1,0x20,0x0e,
    0xec,0x50,0x0e,0x33,0x20,0x28,0x1d,0xdc,0xc1,0x1e,0xc2,0x41,0x1e,0xd2,0x21,0x1c,
    0xdc,0x81,0x1e,0xdc,0xe0,0x1c,0xe4,0xe1,0x1d,0xea,0x01,0x1e,0x66,0x18,0x51,0x38,
    0xb0,0x43,0x3a,0x9c,0x83,0x3b,0xcc,0x50,0x24,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,
    0x60,0x87,0x77,0x78,0x07,0x78,0x98,0x51,0x4c,0xf4,0x90,0x0f,0xf0,0x50,0x0e,0x33,
    0x1e,0x6a,0x1e,0xca,0x61,0x1c,0xe8,0x21,0x1d,0xde,0xc1,0x1d,0x7e,0x01,0x1e,0xe4,
    0xa1,0x1c,0xcc,0x21,0x1d,0xf0,0x61,0x06,0x54,0x85,0x83,0x38,0xcc,0xc3,0x3b,0xb0,
    0x43,0x3d,0xd0,0x43,0x39,0xfc,0xc2,0x3c,0xe4,0x43,0x3b,0x88,0xc3,0x3b,0xb0,0xc3,
    0x8c,0xc5,0x0a,0x87,0x79,0x98,0x87,0x77,0x18,0x87,0x74,0x08,0x07,0x7a,0x28,0x07,
    0x72,0x98,0x81,0x5c,0xe3,0x10,0x0e,0xec,0xc0,0x0e,0xe5,0x50,0x0e,0xf3,0x30,0x23,
    0xc1,0xd2,0x41,0x1e,0xe4,0xe1,0x17,0xd8,0xe1,0x1d,0xde,0x01,0x1e,0x66,0x50,0x59,
    0x38,0xa4,0x83,0x3c,0xb8,0x81,0x39,0xd4,0x83,0x3b,0x8c,0x03,0x3d,0xa4,0xc3,0x3b,
    0xb8,0xc3,0x2f,0x9c,0x83,0x3c,0xbc,0x43,0x3d,0xc0,0xc3,0x3c,0x00,0x71,0x20,0x00,
    0x00,0x08,0x00,0x00,0x00,0x16,0xb0,0x01,0x48,0xe4,0x4b,0x00,0xf3,0x2c,0xc4,0x3f,
    0x11,0xd7,0x44,0x45,0xc4,0x6f,0x0f,0x7e,0x85,0x17,0xb7,0x6d,0x00,0x05,0x03,0x20,
    0x0d,0x0d,0x00,0x00,0x00,0x61,0x20,0x00,0x00,0x0f,0x00,0x00,0x00,0x13,0x04,0x41,
    0x2c,0x10,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0xc4,0x46,0x00,0xc6,0x12,0x80,0x80,
    0xd4,0x08,0x40,0x0d,0x90,0x98,0x01,0xa0,0x30,0x03,0x40,0x60,0x04,0x00,0x00,0x00,
    0x00,0x83,0x0c,0x8b,0x60,0x8c,0x18,0x28,0x42,0x40,0x29,0x49,0x50,0x20,0x86,0x60,
    0x01,0x23,0x9f,0xd9,0x06,0x23,0x00,0x32,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
static const uint8_t _sgl_vs_bytecode_metal_ios[3317] = {
    0x4d,0x54,0x4c,0x42,0x01,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0xf5,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x15,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
    0xe0,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,
    0x4e,0x41,0x4d,0x45,0x06,0x00,0x6d,0x61,0x69,0x6e,0x30,0x00,0x54,0x59,0x50,0x45,
    0x01,0x00,0x00,0x48,0x41,0x53,0x48,0x20,0x00,0x17,0x11,0x57,0x16,0x94,0x42,0x52,
    0xfb,0x1e,0xd0,0x32,0xfd,0x87,0x16,0xb0,0xa4,0xd0,0xc2,0x43,0xbe,0x93,0x8c,0xe0,
    0x2d,0x7a,0x5c,0x3e,0x06,0x4c,0x57,0xeb,0x4b,0x4f,0x46,0x46,0x54,0x18,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x45,0x52,0x53,0x08,0x00,0x01,0x00,0x08,
    0x00,0x01,0x00,0x01,0x00,0x45,0x4e,0x44,0x54,0x40,0x00,0x00,0x00,0x56,0x41,0x54,
    0x54,0x2a,0x00,0x04,0x00,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0x00,0x80,
    0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x00,0x01,0x80,0x63,0x6f,0x6c,0x6f,
    0x72,0x30,0x00,0x02,0x80,0x70,0x73,0x69,0x7a,0x65,0x00,0x03,0x80,0x56,0x41,0x54,
    0x59,0x06,0x00,0x04,0x00,0x06,0x04,0x06,0x03,0x45,0x4e,0x44,0x54,0x04,0x00,0x00,
    0x00,0x45,0x4e,0x44,0x54,0xde,0xc0,0x17,0x0b,0x00,0x00,0x00,0x00,0x14,0x00,0x00,
    0x00,0xc0,0x0b,0x00,0x00,0xff,0xff,0xff,0xff,0x42,0x43,0xc0,0xde,0x21,0x0c,0x00,
    0x00,0xed,0x02,0x00,0x00,0x0b,0x82,0x20,0x00,0x02,0x00,0x00,0x00,0x12,0x00,0x00,
    0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,0x39,0x92,0x01,0x84,
    0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,0x02,0x42,0x92,0x0b,
    0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,0x24,0x48,0x0a,0x90,
    0x21,0x23,0xc4,0x52,0x80,0x0c,0x19,0x21,0x72,0x24,0x07,0xc8,0x48,0x11,0x62,0xa8,
    0xa0,0xa8,0x40,0xc6,0xf0,0x01,0x00,0x00,0x00,0x51,0x18,0x00,0x00,0x82,0x00,0x00,
    0x00,0x1b,0xc8,0x25,0xf8,0xff,0xff,0xff,0xff,0x01,0x90,0x80,0x8a,0x18,0x87,0x77,
    0x90,0x07,0x79,0x28,0x87,0x71,0xa0,0x07,0x76,0xc8,0x87,0x36,0x90,0x87,0x77,0xa8,
    0x07,0x77,0x20,0x87,0x72,0x20,0x87,0x36,0x20,0x87,0x74,0xb0,0x87,0x74,0x20,0x87,
    0x72,0x68,0x83,0x79,0x88,0x07,0x79,0xa0,0x87,0x36,0x30,0x07,0x78,0x68,0x83,0x76,
    0x08,0x07,0x7a,0x40,0x07,0xc0,0x1c,0xc2,0x81,0x1d,0xe6,0xa1,0x1c,0x00,0x82,0x1c,
    0xd2,0x61,0x1e,0xc2,0x41,0x1c,0xd8,0xa1,0x1c,0xda,0x80,0x1e,0xc2,0x21,0x1d,0xd8,
    0xa1,0x0d,0xc6,0x21,0x1c,0xd8,0x81,0x1d,0xe6,0x01,0x30,0x87,0x70,0x60,0x87,0x79,
    0x28,0x07,0x80,0x60,0x87,0x72,0x98,0x87,0x79,0x68,0x03,0x78,0x90,0x87,0x72,0x18,
    0x87,0x74,0x98,0x87,0x72,0x68,0x03,0x73,0x80,0x87,0x76,0x08,0x07,0x72,0x00,0xcc,
    0x21,0x1c,0xd8,0x61,0x1e,0xca,0x01,0x20,0xdc,0xe1,0x1d,0xda,0xc0,0x1c,0xe4,0x21,
    0x1c,0xda,0xa1,0x1c,0xda,0x00,0x1e,0xde,0x21,0x1d,0xdc,0x81,0x1e,0xca,0x41,0x1e,
    0xda,0xa0,0x1c,0xd8,0x21,0x1d,0xda,0x01,0xa0,0x07,0x79,0xa8,0x87,0x72,0x00,0x06,
    0x77,0x78,0x87,0x36,0x30,0x07,0x79,0x08,0x87,0x76,0x28,0x87,0x36,0x80,0x87,0x77,
    0x48,0x07,0x77,0xa0,0x87,0x72,0x90,0x87,0x36,0x28,0x07,0x76,0x48,0x87,0x76,0x68,
    0x03,0x77,0x78,0x07,0x77,0x68,0x03,0x76,0x28,0x87,0x70,0x30,0x07,0x80,0x70,0x87,
    0x77,0x68,0x83,0x74,0x70,0x07,0x73,0x98,0x87,0x36,0x30,0x07,0x78,0x68,0x83,0x76,
    0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xdc,0xe1,0x1d,
    0xda,0x40,0x1d,0xea,0xa1,0x1d,0xe0,0xa1,0x0d,0xe8,0x21,0x1c,0xc4,0x81,0x1d,0xca,
    0x61,0x1e,0x00,0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x08,0x77,0x78,0x87,0x36,
    0x70,0x87,0x70,0x70,0x87,0x79,0x68,0x03,0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,
    0x07,0x74,0x00,0xe8,0x41,0x1e,0xea,0xa1,0x1c,0x00,0xc2,0x1d,0xde,0xa1,0x0d,0xe6,
    0x21,0x1d,0xce,0xc1,0x1d,0xca,0x81,0x1c,0xda,0x40,0x1f,0xca,0x41,0x1e,0xde,0x61,
    0x1e,0xda,0xc0,0x1c,0xe0,0xa1,0x0d,0xda,0x21,0x1c,0xe8,0x01,0x1d,0x00,0x7a,0x90,
    0x87,0x7a,0x28,0x07,0x80,0x70,0x87,0x77,0x68,0x03,0x7a,0x90,0x87,0x70,0x80,0x07,
    0x78,0x48,0x07,0x77,0x38,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,
    0x1e,0xea,0xa1,0x1c,0x00,0x62,0x1e,0xe8,0x21,0x1c,0xc6,0x61,0x1d,0xda,0x00,0x1e,
    0xe4,0xe1,0x1d,0xe8,0xa1,0x1c,0xc6,0x81,0x1e,0xde,0x41,0x1e,0xda,0x40,0x1c,0xea,
    0xc1,0x1c,0xcc,0xa1,0x1c,0xe4,0xa1,0x0d,0xe6,0x21,0x1d,0xf4,0xa1,0x1c,0x00,0x3c,
    0x00,0x88,0x7a,0x70,0x87,0x79,0x08,0x07,0x73,0x28,0x87,0x36,0x30,0x07,0x78,0x68,
    0x83,0x76,0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xea,
    0x61,0x1e,0xca,0xa1,0x0d,0xe6,0xe1,0x1d,0xcc,0x81,0x1e,0xda,0xc0,0x1c,0xd8,0xe1,
    0x1d,0xc2,0x81,0x1e,0x00,0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x36,0x20,0x42,
    0x01,0x24,0xc0,0x02,0x54,0x00,0x00,0x00,0x00,0x49,0x18,0x00,0x00,0x01,0x00,0x00,
    0x00,0x13,0x84,0x40,0x00,0x89,0x20,0x00,0x00,0x20,0x00,0x00,0x00,0x32,0x22,0x48,
    0x09,0x20,0x64,0x85,0x04,0x93,0x22,0xa4,0x84,0x04,0x93,0x22,0xe3,0x84,0xa1,0x90,
    0x14,0x12,0x4c,0x8a,0x8c,0x0b,0x84,0xa4,0x4c,0x10,0x44,0x33,0x00,0xc3,0x08,0x04,
    0x60,0x89,0x10,0x02,0x18,0x46,0x10,0x80,0x24,0x08,0x33,0x51,0xf3,0x40,0x0f,0xf2,
    0x50,0x0f,0xe3,0x40,0x0f,0x6e,0xd0,0x0e,0xe5,0x40,0x0f,0xe1,0xc0,0x0e,0x7a,0xa0,
    0x07,0xed,0x10,0x0e,0xf4,0x20,0x0f,0xe9,0x80,0x0f,0x28,0x20,0x07,0x49,0x53,0x44,
    0x09,0x93,0x5f,0x49,0xff,0x03,0x44,0x00,0x23,0x21,0xa1,0x94,0x41,0x04,0x43,0x28,
    0x86,0x08,0x23,0x80,0x43,0x68,0x20,0x60,0x8e,0x00,0x0c,0x52,0x60,0xcd,0x11,0x80,
    0xc2,0x20,0x42,0x20,0x0c,0x23,0x10,0xcb,0x08,0x00,0x00,0x00,0x00,0x13,0xa8,0x70,
    0x48,0x07,0x79,0xb0,0x03,0x3a,0x68,0x83,0x70,0x80,0x07,0x78,0x60,0x87,0x72,0x68,
    0x83,0x74,0x78,0x87,0x79,0xc8,0x03,0x37,0x80,0x03,0x37,0x80,0x83,0x0d,0xb7,0x51,
    0x0e,0x6d,0x00,0x0f,0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,
    0x74,0xd0,0x06,0xe9,0x10,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,0x78,
    0xa0,0x07,0x78,0xa0,0x07,0x78,0xd0,0x06,0xe9,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,
    0x07,0x7a,0x10,0x07,0x76,0xd0,0x06,0xe9,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,
    0x7a,0x30,0x07,0x72,0xd0,0x06,0xe9,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,
    0x60,0x07,0x74,0xd0,0x06,0xe6,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,
    0x07,0x72,0xd0,0x06,0xe6,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,
    0x74,0xd0,0x06,0xf6,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x7a,0x10,0x07,0x76,
    0xd0,0x06,0xf6,0x20,0x07,0x74,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xd0,
    0x06,0xf6,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xd0,0x06,
    0xf6,0x40,0x07,0x78,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xf6,
    0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xf6,0x90,
    0x07,0x76,0xa0,0x07,0x71,0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xd0,0x06,
    0xf6,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,
    0x80,0x07,0x6d,0x60,0x0f,0x71,0x90,0x07,0x72,0xa0,0x07,0x72,0x50,0x07,0x76,0xa0,
    0x07,0x72,0x50,0x07,0x76,0xd0,0x06,0xf6,0x20,0x07,0x75,0x60,0x07,0x7a,0x20,0x07,
    0x75,0x60,0x07,0x7a,0x20,0x07,0x75,0x60,0x07,0x6d,0x60,0x0f,0x75,0x10,0x07,0x72,
    0xa0,0x07,0x75,0x10,0x07,0x72,0xa0,0x07,0x75,0x10,0x07,0x72,0xd0,0x06,0xf6,0x10,
    0x07,0x70,0x20,0x07,0x74,0xa0,0x07,0x71,0x00,0x07,0x72,0x40,0x07,0x7a,0x10,0x07,
    0x70,0x20,0x07,0x74,0xd0,0x06,0xee,0x80,0x07,0x7a,0x10,0x07,0x76,0xa0,0x07,0x73,
    0x20,0x07,0x43,0x98,0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x2c,0x10,0x00,
    0x00,0x0b,0x00,0x00,0x00,0x32,0x1e,0x98,0x10,0x19,0x11,0x4c,0x90,0x8c,0x09,0x26,
    0x47,0xc6,0x04,0x43,0x5a,0x25,0x30,0x02,0x50,0x04,0x05,0x18,0x50,0x08,0x65,0x50,
    0x80,0x02,0x05,0x51,0x20,0xd4,0x46,0x00,0x88,0x8d,0x25,0x40,0x02,0x00,0x00,0x00,
    0x00,0x79,0x18,0x00,0x00,0x02,0x01,0x00,0x00,0x1a,0x03,0x4c,0x10,0x97,0x29,0xa2,
    0x25,0x10,0xab,0x32,0xb9,0xb9,0xb4,0x37,0xb7,0x21,0xc6,0x32,0x28,0x00,0xb3,0x50,
    0xb9,0x1b,0x43,0x0b,0x93,0xfb,0x9a,0x4b,0xd3,0x2b,0x1b,0x62,0x2c,0x81,0x22,0x2c,
    0x05,0xe7,0x20,0x08,0x0e,0x8e,0xad,0x0c,0xa4,0xad,0x8c,0x2e,0x8c,0x0d,0xc4,0xae,
    0x4c,0x6e,0x2e,0xed,0xcd,0x0d,0x64,0x26,0x06,0x06,0x26,0xc6,0xc5,0xc6,0xe6,0x06,
    0x04,0xa5,0xad,0x8c,0x2e,0x8c,0xcd,0xac,0xac,0x65,0x26,0x06,0x06,0x26,0xc6,0xc5,
    0xc6,0xe6,0xc6,0x45,0x26,0x65,0x88,0xa0,0x10,0x43,0x8c,0x25,0x58,0x90,0x45,0x60,
    0xd1,0x54,0x46,0x17,0xc6,0x36,0x04,0x51,0x8e,0x25,0x58,0x82,0x45,0xe0,0x16,0x96,
    0x26,0xe7,0x32,0xf6,0xd6,0x06,0x97,0xc6,0x56,0xe6,0x42,0x56,0xe6,0xf6,0x26,0xd7,
    0x36,0xf7,0x45,0x96,0x36,0x17,0x26,0xc6,0x56,0x36,0x44,0x50,0x12,0x72,0x61,0x69,
    0x72,0x2e,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x2e,0x66,0x61,0x73,0x74,0x5f,0x6d,
    0x61,0x74,0x68,0x5f,0x65,0x6e,0x61,0x62,0x6c,0x65,0x43,0x04,0x65,0x21,0x19,0x84,
    0xa5,0xc9,0xb9,0x8c,0xbd,0xb5,0xc1,0xa5,0xb1,0x95,0xb9,0x98,0xc9,0x85,0xb5,0x95,
    0x89,0xd5,0x99,0x99,0x95,0xc9,0x7d,0x99,0x95,0xd1,0x8d,0xa1,0x7d,0x95,0xb9,0x85,
    0x89,0xb1,0x95,0x0d,0x11,0x94,0x86,0x51,0x58,0x9a,0x9c,0x8b,0x5d,0x99,0x1c,0x5d,
    0x19,0xde,0xd7,0x5b,0x1d,0x1d,0x5c,0x1d,0x1d,0x97,0xba,0xb9,0x32,0x39,0x14,0xb6,
    0xb7,0x31,0x37,0x98,0x14,0x46,0x61,0x69,0x72,0x2e,0x61,0x72,0x67,0x5f,0x74,0x79,
    0x70,0x65,0x5f,0x6e,0x61,0x6d,0x65,0x34,0xcc,0xd8,0xde,0xc2,0xe8,0x68,0xc8,0x84,
    0xa5,0xc9,0xb9,0x84,0xc9,0x9d,0x7d,0xb9,0x85,0xb5,0x95,0x51,0xa8,0xb3,0x1b,0xc2,
    0x28,0x8f,0x02,0x29,0x91,0x22,0x29,0x93,0x42,0x71,0xa9,0x9b,0x2b,0x93,0x43,0x61,
    0x7b,0x1b,0x73,0x8b,0x49,0x61,0x31,0xf6,0xc6,0xf6,0x26,0x37,0x84,0x51,0x1e,0xc5,
    0x52,0x22,0x45,0x52,0x26,0xe5,0x22,0x13,0x96,0x26,0xe7,0x02,0xf7,0x36,0x97,0x46,
    0x97,0xf6,0xe6,0xc6,0xe5,0x8c,0xed,0x0b,0xea,0x6d,0x2e,0x8d,0x2e,0xed,0xcd,0x6d,
    0x88,0xa2,0x64,0x4a,0xa4,0x48,0xca,0xa4,0x68,0x74,0xc2,0xd2,0xe4,0x5c,0xe0,0xde,
    0xd2,0xdc,0xe8,0xbe,0xe6,0xd2,0xf4,0xca,0x58,0x98,0xb1,0xbd,0x85,0xd1,0x91,0x39,
    0x63,0xfb,0x82,0x7a,0x4b,0x73,0xa3,0x9b,0x4a,0xd3,0x2b,0x1b,0xa2,0x28,0x9c,0x12,
    0x29,0x9d,0x32,0x29,0xde,0x10,0x44,0xa9,0x14,0x4c,0xd9,0x94,0x8f,0x50,0x58,0x9a,
    0x9c,0x8b,0x5d,0x99,0x1c,0x5d,0x19,0xde,0x57,0x9a,0x1b,0x5c,0x1d,0x1d,0xa5,0xb0,
    0x34,0x39,0x17,0xb6,0xb7,0xb1,0x30,0xba,0xb4,0x37,0xb7,0xaf,0x34,0x37,0xb2,0x32,
    0x3c,0x7a,0x67,0x65,0x6e,0x65,0x72,0x61,0x74,0x65,0x64,0x28,0x5f,0x5f,0x61,0x69,
    0x72,0x5f,0x70,0x6c,0x61,0x63,0x65,0x68,0x6f,0x6c,0x64,0x65,0x72,0x5f,0x5f,0x29,
    0x44,0xe0,0xde,0xe6,0xd2,0xe8,0xd2,0xde,0xdc,0x86,0x50,0x8b,0xa0,0x84,0x81,0x22,
    0x06,0x8b,0xb0,0x04,0xca,0x18,0x28,0x91,0x22,0x29,0x93,0x42,0x06,0x34,0xcc,0xd8,
    0xde,0xc2,0xe8,0x64,0x98,0xd0,0x95,0xe1,0x8d,0xbd,0xbd,0xc9,0x91,0xc1,0x0c,0xa1,
    0x96,0x40,0x09,0x03,0x45,0x0c,0x96,0x60,0x09,0x94,0x31,0x50,0x22,0xc5,0x0c,0x94,
    0x49,0x39,0x03,0x1a,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x43,0xa8,0x65,0x50,0xc2,0x40,
    0x11,0x83,0x65,0x58,0x02,0x65,0x0c,0x94,0x48,0x91,0x94,0x49,0x49,0x03,0x16,0x70,
    0x73,0x69,0x7a,0x65,0x43,0xa8,0xc5,0x50,0xc2,0x40,0x11,0x83,0xc5,0x58,0x02,0x65,
    0x0c,0x94,0x48,0xe9,0x94,0x49,0x59,0x03,0x2a,0x61,0x69,0x72,0x2e,0x62,0x75,0x66,
    0x66,0x65,0x72,0x7c,0xc2,0xd2,0xe4,0x5c,0xc4,0xea,0xcc,0xcc,0xca,0xe4,0xbe,0xe6,
    0xd2,0xf4,0xca,0x88,0x84,0xa5,0xc9,0xb9,0xc8,0x95,0x85,0x91,0x91,0x0a,0x4b,0x93,
    0x73,0x99,0xa3,0x93,0xab,0x1b,0xa3,0xfb,0xa2,0xcb,0x83,0x2b,0xfb,0x4a,0x73,0x33,
    0x7b,0x23,0x62,0xc6,0xf6,0x16,0x46,0x47,0x83,0x47,0xc3,0xa1,0xcd,0x0e,0x8e,0x02,
    0x5d,0xdb,0x10,0x6a,0x11,0x16,0x62,0x11,0x94,0x38,0x50,0xe4,0x60,0x21,0x16,0x62,
    0x11,0x94,0x38,0x50,0xe6,0x80,0x51,0x58,0x9a,0x9c,0x4b,0x98,0xdc,0xd9,0x17,0x5d,
    0x1e,0x5c,0xd9,0xd7,0x5c,0x9a,0x5e,0x19,0xaf,0xb0,0x34,0x39,0x97,0x30,0xb9,0xb3,
    0x2f,0xba,0x3c,0xb8,0xb2,0xaf,0x30,0xb6,0xb4,0x33,0xb7,0xaf,0xb9,0x34,0xbd,0x32,
    0x26,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x1c,0xbe,0x62,0x72,0x86,0x90,
    0xc1,0x52,0x28,0x6d,0xa0,0xb8,0xc1,0x72,0x28,0x62,0xb0,0x08,0x4b,0xa0,0xbc,0x81,
    0x02,0x07,0x0a,0x1d,0x28,0x75,0xb0,0x1c,0x8a,0x1d,0x2c,0x89,0x12,0x29,0x77,0xa0,
    0x4c,0x0a,0x1e,0x0c,0x51,0x94,0x32,0x50,0xd0,0x40,0x51,0x03,0x85,0x0d,0x94,0x3c,
    0x18,0x62,0x24,0x80,0x02,0x06,0x8a,0x1e,0xf0,0x79,0x6b,0x73,0x4b,0x83,0x7b,0xa3,
    0x2b,0x73,0xa3,0x03,0x19,0x43,0x0b,0x93,0xe3,0x33,0x95,0xd6,0x06,0xc7,0x56,0x06,
    0x32,0xb4,0xb2,0x02,0x42,0x25,0x14,0x14,0x34,0x44,0x50,0xfa,0x60,0x88,0xa1,0xf0,
    0x81,0xe2,0x07,0x8d,0x32,0xc4,0x50,0xfe,0x40,0xf9,0x83,0x46,0x19,0x11,0xb1,0x03,
    0x3b,0xd8,0x43,0x3b,0xb8,0x41,0x3b,0xbc,0x03,0x39,0xd4,0x03,0x3b,0x94,0x83,0x1b,
    0x98,0x03,0x3b,0x84,0xc3,0x39,0xcc,0xc3,0x14,0x21,0x18,0x46,0x28,0xec,0xc0,0x0e,
    0xf6,0xd0,0x0e,0x6e,0x90,0x0e,0xe4,0x50,0x0e,0xee,0x40,0x0f,0x53,0x82,0x62,0xc4,
    0x12,0x0e,0xe9,0x20,0x0f,0x6e,0x60,0x0f,0xe5,0x20,0x0f,0xf3,0x90,0x0e,0xef,0xe0,
    0x0e,0x53,0x02,0x63,0x04,0x15,0x0e,0xe9,0x20,0x0f,0x6e,0xc0,0x0e,0xe1,0xe0,0x0e,
    0xe7,0x50,0x0f,0xe1,0x70,0x0e,0xe5,0xf0,0x0b,0xf6,0x50,0x0e,0xf2,0x30,0x0f,0xe9,
    0xf0,0x0e,0xee,0x30,0x25,0x40,0x46,0x4c,0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xe3,0xf0,
    0x0e,0xed,0x00,0x0f,0xe9,0xc0,0x0e,0xe5,0xf0,0x0b,0xef,0x00,0x0f,0xf4,0x90,0x0e,
    0xef,0xe0,0x0e,0xf3,0x30,0x65,0x50,0x18,0x67,0x84,0x12,0x0e,0xe9,0x20,0x0f,0x6e,
    0x60,0x0f,0xe5,0x20,0x0f,0xf4,0x50,0x0e,0xf8,0x30,0x25,0xd8,0x03,0x00,0x00,0x00,
    0x00,0x79,0x18,0x00,0x00,0x7b,0x00,0x00,0x00,0x33,0x08,0x80,0x1c,0xc4,0xe1,0x1c,
    0x66,0x14,0x01,0x3d,0x88,0x43,0x38,0x84,0xc3,0x8c,0x42,0x80,0x07,0x79,0x78,0x07,
    0x73,0x98,0x71,0x0c,0xe6,0x00,0x0f,0xed,0x10,0x0e,0xf4,0x80,0x0e,0x33,0x0c,0x42,
    0x1e,0xc2,0xc1,0x1d,0xce,0xa1,0x1c,0x66,0x30,0x05,0x3d,0x88,0x43,0x38,0x84,0x83,
    0x1b,0xcc,0x03,0x3d,0xc8,0x43,0x3d,0x8c,0x03,0x3d,0xcc,0x78,0x8c,0x74,0x70,0x07,
    0x7b,0x08,0x07,0x79,0x48,0x87,0x70,0x70,0x07,0x7a,0x70,0x03,0x76,0x78,0x87,0x70,
    0x20,0x87,0x19,0xcc,0x11,0x0e,0xec,0x90,0x0e,0xe1,0x30,0x0f,0x6e,0x30,0x0f,0xe3,
    0xf0,0x0e,0xf0,0x50,0x0e,0x33,0x10,0xc4,0x1d,0xde,0x21,0x1c,0xd8,0x21,0x1d,0xc2,
    0x61,0x1e,0x66,0x30,0x89,0x3b,0xbc,0x83,0x3b,0xd0,0x43,0x39,0xb4,0x03,0x3c,0xbc,
    0x83,0x3c,0x84,0x03,0x3b,0xcc,0xf0,0x14,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x68,
    0x87,0x72,0x68,0x07,0x37,0x80,0x87,0x70,0x90,0x87,0x70,0x60,0x07,0x76,0x28,0x07,
    0x76,0xf8,0x05,0x76,0x78,0x87,0x77,0x80,0x87,0x5f,0x08,0x87,0x71,0x18,0x87,0x72,
    0x98,0x87,0x79,0x98,0x81,0x2c,0xee,0xf0,0x0e,0xee,0xe0,0x0e,0xf5,0xc0,0x0e,0xec,
    0x30,0x03,0x62,0xc8,0xa1,0x1c,0xe4,0xa1,0x1c,0xcc,0xa1,0x1c,0xe4,0xa1,0x1c,0xdc,
    0x61,0x1c,0xca,0x21,0x1c,0xc4,0x81,0x1d,0xca,0x61,0x06,0xd6,0x90,0x43,0x39,0xc8,
    0x43,0x39,0x98,0x43,0x39,0xc8,0x43,0x39,0xb8,0xc3,0x38,0x94,0x43,0x38,0x88,0x03,
    0x3b,0x94,0xc3,0x2f,0xbc,0x83,0x3c,0xfc,0x82,0x3b,0xd4,0x03,0x3b,0xb0,0xc3,0x0c,
    0xc7,0x69,0x87,0x70,0x58,0x87,0x72,0x70,0x83,0x74,0x68,0x07,0x78,0x60,0x87,0x74,
    0x18,0x87,0x74,0xa0,0x87,0x19,0xce,0x53,0x0f,0xee,0x00,0x0f,0xf2,0x50,0x0e,0xe4,
    0x90,0x0e,0xe3,0x40,0x0f,0xe1,0x20,0x0e,0xec,0x50,0x0e,0x33,0x20,0x28,0x1d,0xdc,
    0xc1,0x1e,0xc2,0x41,0x1e,0xd2,0x21,0x1c,0xdc,0x81,0x1e,0xdc,0xe0,0x1c,0xe4,0xe1,
    0x1d,0xea,0x01,0x1e,0x66,0x18,0x51,0x38,0xb0,0x43,0x3a,0x9c,0x83,0x3b,0xcc,0x50,
    0x24,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x60,0x87,0x77,0x78,0x07,0x78,0x98,0x51,
    0x4c,0xf4,0x90,0x0f,0xf0,0x50,0x0e,0x33,0x1e,0x6a,0x1e,0xca,0x61,0x1c,0xe8,0x21,
    0x1d,0xde,0xc1,0x1d,0x7e,0x01,0x1e,0xe4,0xa1,0x1c,0xcc,0x21,0x1d,0xf0,0x61,0x06,
    0x54,0x85,0x83,0x38,0xcc,0xc3,0x3b,0xb0,0x43,0x3d,0xd0,0x43,0x39,0xfc,0xc2,0x3c,
    0xe4,0x43,0x3b,0x88,0xc3,0x3b,0xb0,0xc3,0x8c,0xc5,0x0a,0x87,0x79,0x98,0x87,0x77,
    0x18,0x87,0x74,0x08,0x07,0x7a,0x28,0x07,0x72,0x98,0x81,0x5c,0xe3,0x10,0x0e,0xec,
    0xc0,0x0e,0xe5,0x50,0x0e,0xf3,0x30,0x23,0xc1,0xd2,0x41,0x1e,0xe4,0xe1,0x17,0xd8,
    0xe1,0x1d,0xde,0x01,0x1e,0x66,0x50,0x59,0x38,0xa4,0x83,0x3c,0xb8,0x81,0x39,0xd4,
    0x83,0x3b,0x8c,0x03,0x3d,0xa4,0xc3,0x3b,0xb8,0xc3,0x2f,0x9c,0x83,0x3c,0xbc,0x43,
    0x3d,0xc0,0xc3,0x3c,0x00,0x71,0x20,0x00,0x00,0x02,0x00,0x00,0x00,0x06,0x50,0x30,
    0x00,0xd2,0xd0,0x00,0x00,0x61,0x20,0x00,0x00,0x3e,0x00,0x00,0x00,0x13,0x04,0x41,
    0x2c,0x10,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0xf4,0xc6,0x22,0x86,0x61,0x18,0xc6,
    0x22,0x04,0x41,0x10,0xc6,0x22,0x82,0x20,0x08,0xa8,0x95,0x40,0x19,0x14,0x01,0xbd,
    0x11,0x00,0x1a,0x33,0x00,0x24,0x66,0x00,0x28,0xcc,0x00,0x00,0x00,0xe3,0x15,0x4b,
    0x94,0x65,0x11,0x05,0x65,0x90,0x21,0x1a,0x0c,0x13,0x02,0xf9,0x8c,0x57,0x3c,0x55,
    0xd7,0x2d,0x14,0x94,0x41,0x86,0xea,0x70,0x4c,0x08,0xe4,0x63,0x41,0x01,0x9f,0xf1,
    0x0a,0x4a,0x13,0x03,0x31,0x70,0x28,0x28,0x83,0x0c,0x1a,0x43,0x99,0x10,0xc8,0xc7,
    0x8a,0x00,0x3e,0xe3,0x15,0xd9,0x77,0x06,0x67,0x40,0x51,0x50,0x06,0x19,0xbe,0x48,
    0x33,0x21,0x90,0x8f,0x15,0x01,0x7c,0xc6,0x2b,0x3c,0x32,0x68,0x03,0x36,0x20,0x03,
    0x0a,0xca,0x20,0xc3,0x18,0x60,0x99,0x09,0x81,0x7c,0xc6,0x2b,0xc4,0x00,0x0d,0xe2,
    0x00,0x0e,0x3c,0x0a,0xca,0x20,0xc3,0x19,0x70,0x61,0x60,0x42,0x20,0x1f,0x0b,0x0a,
    0xf8,0x8c,0x57,0x9c,0x41,0x1b,0xd8,0x41,0x1d,0x88,0x01,0x05,0xc5,0x86,0x00,0x3e,
    0xb3,0x0d,0x61,0x10,0x00,0xb3,0x0d,0x41,0x1b,0x04,0xb3,0x0d,0xc1,0x23,0xcc,0x36,
    0x04,0x6e,0x30,0x64,0x10,0x10,0x03,0x00,0x00,0x09,0x00,0x00,0x00,0x5b,0x86,0x20,
    0x00,0x85,0x2d,0x43,0x11,0x80,0xc2,0x96,0x41,0x09,0x40,0x61,0xcb,0xf0,0x04,0xa0,
    0xb0,0x65,0xa0,0x02,0x50,0xd8,0x32,0x60,0x01,0x28,0x6c,0x19,0xba,0x00,0x14,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,
};
static const uint8_t _sgl_fs_bytecode_metal_ios[2809] = {
    0x4d,0x54,0x4c,0x42,0x01,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0xf9,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd9,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x20,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x6d,0x00,0x00,0x00,
    0x4e,0x41,0x4d,0x45,0x06,0x00,0x6d,0x61,0x69,0x6e,0x30,0x00,0x54,0x59,0x50,0x45,
    0x01,0x00,0x01,0x48,0x41,0x53,0x48,0x20,0x00,0xc1,0x98,0x28,0x2b,0x2b,0x1f,0x36,
    0x7c,0x5c,0xb0,0x69,0x3f,0xc3,0xd1,0x80,0x4b,0xcf,0xa1,0x10,0xfc,0x19,0x31,0x58,
    0xad,0x45,0xd3,0x5a,0x81,0x72,0x0d,0x8f,0x85,0x4f,0x46,0x46,0x54,0x18,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x56,0x45,0x52,0x53,0x08,0x00,0x01,0x00,0x08,
    0x00,0x01,0x00,0x01,0x00,0x45,0x4e,0x44,0x54,0x04,0x00,0x00,0x00,0x45,0x4e,0x44,
    0x54,0x04,0x00,0x00,0x00,0x45,0x4e,0x44,0x54,0xde,0xc0,0x17,0x0b,0x00,0x00,0x00,
    0x00,0x14,0x00,0x00,0x00,0x08,0x0a,0x00,0x00,0xff,0xff,0xff,0xff,0x42,0x43,0xc0,
    0xde,0x21,0x0c,0x00,0x00,0x7f,0x02,0x00,0x00,0x0b,0x82,0x20,0x00,0x02,0x00,0x00,
    0x00,0x12,0x00,0x00,0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,
    0x39,0x92,0x01,0x84,0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,
    0x02,0x42,0x92,0x0b,0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,
    0x24,0x48,0x0a,0x90,0x21,0x23,0xc4,0x52,0x80,0x0c,0x19,0x21,0x72,0x24,0x07,0xc8,
    0x48,0x11,0x62,0xa8,0xa0,0xa8,0x40,0xc6,0xf0,0x01,0x00,0x00,0x00,0x51,0x18,0x00,
    0x00,0x89,0x00,0x00,0x00,0x1b,0xcc,0x25,0xf8,0xff,0xff,0xff,0xff,0x01,0x60,0x00,
    0x09,0xa8,0x88,0x71,0x78,0x07,0x79,0x90,0x87,0x72,0x18,0x07,0x7a,0x60,0x87,0x7c,
    0x68,0x03,0x79,0x78,0x87,0x7a,0x70,0x07,0x72,0x28,0x07,0x72,0x68,0x03,0x72,0x48,
    0x07,0x7b,0x48,0x07,0x72,0x28,0x87,0x36,0x98,0x87,0x78,0x90,0x07,0x7a,0x68,0x03,
    0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xcc,0x21,0x1c,0xd8,0x61,
    0x1e,0xca,0x01,0x20,0xc8,0x21,0x1d,0xe6,0x21,0x1c,0xc4,0x81,0x1d,0xca,0xa1,0x0d,
    0xe8,0x21,0x1c,0xd2,0x81,0x1d,0xda,0x60,0x1c,0xc2,0x81,0x1d,0xd8,0x61,0x1e,0x00,
    0x73,0x08,0x07,0x76,0x98,0x87,0x72,0x00,0x08,0x76,0x28,0x87,0x79,0x98,0x87,0x36,
    0x80,0x07,0x79,0x28,0x87,0x71,0x48,0x87,0x79,0x28,0x87,0x36,0x30,0x07,0x78,0x68,
    0x87,0x70,0x20,0x07,0xc0,0x1c,0xc2,0x81,0x1d,0xe6,0xa1,0x1c,0x00,0xc2,0x1d,0xde,
    0xa1,0x0d,0xcc,0x41,0x1e,0xc2,0xa1,0x1d,0xca,0xa1,0x0d,0xe0,0xe1,0x1d,0xd2,0xc1,
    0x1d,0xe8,0xa1,0x1c,0xe4,0xa1,0x0d,0xca,0x81,0x1d,0xd2,0xa1,0x1d,0x00,0x7a,0x90,
    0x87,0x7a,0x28,0x07,0x60,0x70,0x87,0x77,0x68,0x03,0x73,0x90,0x87,0x70,0x68,0x87,
    0x72,0x68,0x03,0x78,0x78,0x87,0x74,0x70,0x07,0x7a,0x28,0x07,0x79,0x68,0x83,0x72,
    0x60,0x87,0x74,0x68,0x87,0x36,0x70,0x87,0x77,0x70,0x87,0x36,0x60,0x87,0x72,0x08,
    0x07,0x73,0x00,0x08,0x77,0x78,0x87,0x36,0x48,0x07,0x77,0x30,0x87,0x79,0x68,0x03,
    0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,0x1e,0xea,0xa1,
    0x1c,0x00,0xc2,0x1d,0xde,0xa1,0x0d,0xd4,0xa1,0x1e,0xda,0x01,0x1e,0xda,0x80,0x1e,
    0xc2,0x41,0x1c,0xd8,0xa1,0x1c,0xe6,0x01,0x30,0x87,0x70,0x60,0x87,0x79,0x28,0x07,
    0x80,0x70,0x87,0x77,0x68,0x03,0x77,0x08,0x07,0x77,0x98,0x87,0x36,0x30,0x07,0x78,
    0x68,0x83,0x76,0x08,0x07,0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,
    0xdc,0xe1,0x1d,0xda,0x60,0x1e,0xd2,0xe1,0x1c,0xdc,0xa1,0x1c,0xc8,0xa1,0x0d,0xf4,
    0xa1,0x1c,0xe4,0xe1,0x1d,0xe6,0xa1,0x0d,0xcc,0x01,0x1e,0xda,0xa0,0x1d,0xc2,0x81,
    0x1e,0xd0,0x01,0xa0,0x07,0x79,0xa8,0x87,0x72,0x00,0x08,0x77,0x78,0x87,0x36,0xa0,
    0x07,0x79,0x08,0x07,0x78,0x80,0x87,0x74,0x70,0x87,0x73,0x68,0x83,0x76,0x08,0x07,
    0x7a,0x40,0x07,0x80,0x1e,0xe4,0xa1,0x1e,0xca,0x01,0x20,0xe6,0x81,0x1e,0xc2,0x61,
    0x1c,0xd6,0xa1,0x0d,0xe0,0x41,0x1e,0xde,0x81,0x1e,0xca,0x61,0x1c,0xe8,0xe1,0x1d,
    0xe4,0xa1,0x0d,0xc4,0xa1,0x1e,0xcc,0xc1,0x1c,0xca,0x41,0x1e,0xda,0x60,0x1e,0xd2,
    0x41,0x1f,0xca,0x01,0xc0,0x03,0x80,0xa8,0x07,0x77,0x98,0x87,0x70,0x30,0x87,0x72,
    0x68,0x03,0x73,0x80,0x87,0x36,0x68,0x87,0x70,0xa0,0x07,0x74,0x00,0xe8,0x41,0x1e,
    0xea,0xa1,0x1c,0x00,0xa2,0x1e,0xe6,0xa1,0x1c,0xda,0x60,0x1e,0xde,0xc1,0x1c,0xe8,
    0xa1,0x0d,0xcc,0x81,0x1d,0xde,0x21,0x1c,0xe8,0x01,0x30,0x87,0x70,0x60,0x87,0x79,
    0x28,0x07,0x60,0x83,0x21,0x0c,0xc0,0x02,0x54,0x1b,0x8c,0x81,0x00,0x16,0xa0,0xda,
    0x80,0x10,0xff,0xff,0xff,0xff,0x3f,0x00,0x0c,0x20,0x01,0xd5,0x06,0xa3,0x08,0x80,
    0x05,0xa8,0x36,0x18,0x86,0x00,0x2c,0x40,0x05,0x49,0x18,0x00,0x00,0x03,0x00,0x00,
    0x00,0x13,0x86,0x40,0x18,0x26,0x0c,0x44,0x61,0x00,0x00,0x00,0x00,0x89,0x20,0x00,
    0x00,0x1d,0x00,0x00,0x00,0x32,0x22,0x48,0x09,0x20,0x64,0x85,0x04,0x93,0x22,0xa4,
    0x84,0x04,0x93,0x22,0xe3,0x84,0xa1,0x90,0x14,0x12,0x4c,0x8a,0x8c,0x0b,0x84,0xa4,
    0x4c,0x10,0x48,0x33,0x00,0xc3,0x08,0x04,0x60,0x83,0x70,0x94,0x34,0x45,0x94,0x30,
    0xf9,0xff,0x44,0x5c,0x13,0x15,0x11,0xbf,0x3d,0xfc,0xd3,0x18,0x01,0x30,0x88,0x30,
    0x04,0x17,0x49,0x53,0x44,0x09,0x93,0xff,0x4b,0x00,0xf3,0x2c,0x44,0xf4,0x4f,0x63,
    0x04,0xc0,0x20,0x42,0x21,0x94,0x42,0x84,0x40,0x0c,0x9d,0x61,0x04,0x01,0x98,0x23,
    0x08,0xe6,0x08,0xc0,0x60,0x18,0x41,0x58,0x0a,0x12,0x88,0x49,0x8a,0x29,0x40,0x6d,
    0x20,0x20,0x05,0xd6,0x08,0x00,0x00,0x00,0x00,0x13,0xa8,0x70,0x48,0x07,0x79,0xb0,
    0x03,0x3a,0x68,0x83,0x70,0x80,0x07,0x78,0x60,0x87,0x72,0x68,0x83,0x74,0x78,0x87,
    0x79,0xc8,0x03,0x37,0x80,0x03,0x37,0x80,0x83,0x0d,0xb7,0x51,0x0e,0x6d,0x00,0x0f,
    0x7a,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xe9,
    0x10,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,0x78,0xa0,0x07,0x78,0xa0,
    0x07,0x78,0xd0,0x06,0xe9,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x7a,0x10,0x07,
    0x76,0xd0,0x06,0xe9,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,
    0xd0,0x06,0xe9,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,
    0x06,0xe6,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xd0,0x06,
    0xe6,0x60,0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xf6,
    0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x7a,0x10,0x07,0x76,0xd0,0x06,0xf6,0x20,
    0x07,0x74,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xd0,0x06,0xf6,0x30,0x07,
    0x72,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xd0,0x06,0xf6,0x40,0x07,0x78,
    0xa0,0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xf6,0x60,0x07,0x74,0xa0,
    0x07,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xf6,0x90,0x07,0x76,0xa0,0x07,
    0x71,0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xd0,0x06,0xf6,0x10,0x07,0x72,
    0x80,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x7a,0x10,0x07,0x72,0x80,0x07,0x6d,0x60,
    0x0f,0x71,0x90,0x07,0x72,0xa0,0x07,0x72,0x50,0x07,0x76,0xa0,0x07,0x72,0x50,0x07,
    0x76,0xd0,0x06,0xf6,0x20,0x07,0x75,0x60,0x07,0x7a,0x20,0x07,0x75,0x60,0x07,0x7a,
    0x20,0x07,0x75,0x60,0x07,0x6d,0x60,0x0f,0x75,0x10,0x07,0x72,0xa0,0x07,0x75,0x10,
    0x07,0x72,0xa0,0x07,0x75,0x10,0x07,0x72,0xd0,0x06,0xf6,0x10,0x07,0x70,0x20,0x07,
    0x74,0xa0,0x07,0x71,0x00,0x07,0x72,0x40,0x07,0x7a,0x10,0x07,0x70,0x20,0x07,0x74,
    0xd0,0x06,0xee,0x80,0x07,0x7a,0x10,0x07,0x76,0xa0,0x07,0x73,0x20,0x07,0x43,0x18,
    0x04,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x80,0x21,0x8c,0x03,0x04,0x80,0x00,0x00,
    0x00,0x00,0x00,0x40,0x16,0x08,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x32,0x1e,0x98,
    0x10,0x19,0x11,0x4c,0x90,0x8c,0x09,0x26,0x47,0xc6,0x04,0x43,0x5a,0x25,0x30,0x02,
    0x50,0x04,0x85,0x50,0x10,0x65,0x40,0x70,0x2c,0x01,0x12,0x00,0x00,0x79,0x18,0x00,
    0x00,0xb7,0x00,0x00,0x00,0x1a,0x03,0x4c,0x10,0x97,0x29,0xa2,0x25,0x10,0xab,0x32,
    0xb9,0xb9,0xb4,0x37,0xb7,0x21,0xc6,0x42,0x3c,0x00,0x84,0x50,0xb9,0x1b,0x43,0x0b,
    0x93,0xfb,0x9a,0x4b,0xd3,0x2b,0x1b,0x62,0x2c,0xc2,0x23,0x2c,0x05,0xe7,0x20,0x08,
    0x0e,0x8e,0xad,0x0c,0xa4,0xad,0x8c,0x2e,0x8c,0x0d,0xc4,0xae,0x4c,0x6e,0x2e,0xed,
    0xcd,0x0d,0x64,0x26,0x06,0x06,0x26,0xc6,0xc5,0xc6,0xe6,0x06,0x04,0xa5,0xad,0x8c,
    0x2e,0x8c,0xcd,0xac,0xac,0x65,0x26,0x06,0x06,0x26,0xc6,0xc5,0xc6,0xe6,0xc6,0x45,
    0x26,0x65,0x88,0xf0,0x10,0x43,0x8c,0x45,0x58,0x8c,0x65,0x60,0xd1,0x54,0x46,0x17,
    0xc6,0x36,0x04,0x79,0x8e,0x45,0x58,0x84,0x65,0xe0,0x16,0x96,0x26,0xe7,0x32,0xf6,
    0xd6,0x06,0x97,0xc6,0x56,0xe6,0x42,0x56,0xe6,0xf6,0x26,0xd7,0x36,0xf7,0x45,0x96,
    0x36,0x17,0x26,0xc6,0x56,0x36,0x44,0x78,0x12,0x72,0x61,0x69,0x72,0x2e,0x63,0x6f,
    0x6d,0x70,0x69,0x6c,0x65,0x2e,0x66,0x61,0x73,0x74,0x5f,0x6d,0x61,0x74,0x68,0x5f,
    0x65,0x6e,0x61,0x62,0x6c,0x65,0x43,0x84,0x67,0x21,0x19,0x84,0xa5,0xc9,0xb9,0x8c,
    0xbd,0xb5,0xc1,0xa5,0xb1,0x95,0xb9,0x98,0xc9,0x85,0xb5,0x95,0x89,0xd5,0x99,0x99,
    0x95,0xc9,0x7d,0x99,0x95,0xd1,0x8d,0xa1,0x7d,0x95,0xb9,0x85,0x89,0xb1,0x95,0x0d,
    0x11,0x9e,0x86,0x51,0x58,0x9a,0x9c,0x8b,0x5c,0x99,0x1b,0x59,0x99,0xdc,0x17,0x5d,
    0x98,0xdc,0x59,0x19,0x1d,0xa3,0xb0,0x34,0x39,0x97,0x30,0xb9,0xb3,0x2f,0xba,0x3c,
    0xb8,0xb2,0x2f,0xb7,0xb0,0xb6,0x32,0x1a,0x66,0x6c,0x6f,0x61,0x74,0x34,0x64,0xc2,
    0xd2,0xe4,0x5c,0xc2,0xe4,0xce,0xbe,0xdc,0xc2,0xda,0xca,0xa8,0x98,0xc9,0x85,0x9d,
    0x7d,0x8d,0xbd,0xb1,0xbd,0xc9,0x0d,0x61,0x9e,0x67,0x19,0x1e,0xe8,0x89,0x1e,0xe9,
    0x99,0x86,0x08,0x0f,0x45,0x29,0x2c,0x4d,0xce,0xc5,0x4c,0x2e,0xec,0xac,0xad,0xcc,
    0x8d,0xee,0x2b,0xcd,0x0d,0xae,0x8e,0x8e,0x4b,0xdd,0x5c,0x99,0x1c,0x0a,0xdb,0xdb,
    0x98,0x1b,0x4c,0x0a,0x95,0xb0,0x34,0x39,0x97,0xb1,0x32,0x37,0xba,0x32,0x39,0x3e,
    0x61,0x69,0x72,0x2e,0x70,0x65,0x72,0x73,0x70,0x65,0x63,0x74,0x69,0x76,0x65,0x14,
    0xea,0xec,0x86,0x48,0xcb,0xf0,0x58,0xcf,0xf5,0x60,0x4f,0xf6,0x40,0x4f,0xf4,0x48,
    0x8f,0xc6,0xa5,0x6e,0xae,0x4c,0x0e,0x85,0xed,0x6d,0xcc,0x2d,0x26,0x85,0xc5,0xd8,
    0x1b,0xdb,0x9b,0xdc,0x10,0x69,0x11,0x1e,0xeb,0xe1,0x1e,0xec,0xc9,0x1e,0xe8,0x89,
    0x1e,0xe9,0xe9,0xb8,0x84,0xa5,0xc9,0xb9,0xd0,0x95,0xe1,0xd1,0xd5,0xc9,0x95,0x51,
    0x0a,0x4b,0x93,0x73,0x61,0x7b,0x1b,0x0b,0xa3,0x4b,0x7b,0x73,0xfb,0x4a,0x73,0x23,
    0x2b,0xc3,0xa3,0x12,0x96,0x26,0xe7,0x32,0x17,0xd6,0x06,0xc7,0x56,0x46,0x8c,0xae,
    0x0c,0x8f,0xae,0x4e,0xae,0x4c,0x86,0x8c,0xc7,0x8c,0xed,0x2d,0x8c,0x8e,0x05,0x64,
    0x2e,0xac,0x0d,0x8e,0xad,0xcc,0x87,0x03,0x5d,0x19,0xde,0x10,0x6a,0x21,0x9e,0xef,
    0x01,0x83,0x65,0x58,0x84,0x27,0x0c,0x1e,0xe8,0x11,0x83,0x47,0x7a,0xc6,0x80,0x4b,
    0x58,0x9a,0x9c,0xcb,0x5c,0x58,0x1b,0x1c,0x5b,0x99,0x1c,0x8f,0xb9,0xb0,0x36,0x38,
    0xb6,0x32,0x39,0x0e,0x73,0x6d,0x70,0x43,0xa4,0xe5,0x78,0xca,0xe0,0x01,0x83,0x65,
    0x58,0x84,0x07,0x7a,0xcc,0xe0,0x91,0x9e,0x33,0x18,0x82,0x3c,0xdb,0xe3,0x3d,0x64,
    0xf0,0xa0,0xc1,0x10,0x03,0x01,0x9e,0xea,0x49,0x83,0x11,0x11,0x3b,0xb0,0x83,0x3d,
    0xb4,0x83,0x1b,0xb4,0xc3,0x3b,0x90,0x43,0x3d,0xb0,0x43,0x39,0xb8,0x81,0x39,0xb0,
    0x43,0x38,0x9c,0xc3,0x3c,0x4c,0x11,0x82,0x61,0x84,0xc2,0x0e,0xec,0x60,0x0f,0xed,
    0xe0,0x06,0xe9,0x40,0x0e,0xe5,0xe0,0x0e,0xf4,0x30,0x25,0x28,0x46,0x2c,0xe1,0x90,
    0x0e,0xf2,0xe0,0x06,0xf6,0x50,0x0e,0xf2,0x30,0x0f,0xe9,0xf0,0x0e,0xee,0x30,0x25,
    0x30,0x46,0x50,0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xec,0x10,0x0e,0xee,0x70,0x0e,0xf5,
    0x10,0x0e,0xe7,0x50,0x0e,0xbf,0x60,0x0f,0xe5,0x20,0x0f,0xf3,0x90,0x0e,0xef,0xe0,
    0x0e,0x53,0x02,0x64,0xc4,0x14,0x0e,0xe9,0x20,0x0f,0x6e,0x30,0x0e,0xef,0xd0,0x0e,
    0xf0,0x90,0x0e,0xec,0x50,0x0e,0xbf,0xf0,0x0e,0xf0,0x40,0x0f,0xe9,0xf0,0x0e,0xee,
    0x30,0x0f,0x53,0x06,0x85,0x71,0x46,0x30,0xe1,0x90,0x0e,0xf2,0xe0,0x06,0xe6,0x20,
    0x0f,0xe1,0x70,0x0e,0xed,0x50,0x0e,0xee,0x40,0x0f,0x53,0x02,0x35,0x00,0x00,0x00,
    0x00,0x79,0x18,0x00,0x00,0x7b,0x00,0x00,0x00,0x33,0x08,0x80,0x1c,0xc4,0xe1,0x1c,
    0x66,0x14,0x01,0x3d,0x88,0x43,0x38,0x84,0xc3,0x8c,0x42,0x80,0x07,0x79,0x78,0x07,
    0x73,0x98,0x71,0x0c,0xe6,0x00,0x0f,0xed,0x10,0x0e,0xf4,0x80,0x0e,0x33,0x0c,0x42,
    0x1e,0xc2,0xc1,0x1d,0xce,0xa1,0x1c,0x66,0x30,0x05,0x3d,0x88,0x43,0x38,0x84,0x83,
    0x1b,0xcc,0x03,0x3d,0xc8,0x43,0x3d,0x8c,0x03,0x3d,0xcc,0x78,0x8c,0x74,0x70,0x07,
    0x7b,0x08,0x07,0x79,0x48,0x87,0x70,0x70,0x07,0x7a,0x70,0x03,0x76,0x78,0x87,0x70,
    0x20,0x87,0x19,0xcc,0x11,0x0e,0xec,0x90,0x0e,0xe1,0x30,0x0f,0x6e,0x30,0x0f,0xe3,
    0xf0,0x0e,0xf0,0x50,0x0e,0x33,0x10,0xc4,0x1d,0xde,0x21,0x1c,0xd8,0x21,0x1d,0xc2,
    0x61,0x1e,0x66,0x30,0x89,0x3b,0xbc,0x83,0x3b,0xd0,0x43,0x39,0xb4,0x03,0x3c,0xbc,
    0x83,0x3c,0x84,0x03,0x3b,0xcc,0xf0,0x14,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x68,
    0x87,0x72,0x68,0x07,0x37,0x80,0x87,0x70,0x90,0x87,0x70,0x60,0x07,0x76,0x28,0x07,
    0x76,0xf8,0x05,0x76,0x78,0x87,0x77,0x80,0x87,0x5f,0x08,0x87,0x71,0x18,0x87,0x72,
    0x98,0x87,0x79,0x98,0x81,0x2c,0xee,0xf0,0x0e,0xee,0xe0,0x0e,0xf5,0xc0,0x0e,0xec,
    0x30,0x03,0x62,0xc8,0xa1,0x1c,0xe4,0xa1,0x1c,0xcc,0xa1,0x1c,0xe4,0xa1,0x1c,0xdc,
    0x61,0x1c,0xca,0x21,0x1c,0xc4,0x81,0x1d,0xca,0x61,0x06,0xd6,0x90,0x43,0x39,0xc8,
    0x43,0x39,0x98,0x43,0x39,0xc8,0x43,0x39,0xb8,0xc3,0x38,0x94,0x43,0x38,0x88,0x03,
    0x3b,0x94,0xc3,0x2f,0xbc,0x83,0x3c,0xfc,0x82,0x3b,0xd4,0x03,0x3b,0xb0,0xc3,0x0c,
    0xc7,0x69,0x87,0x70,0x58,0x87,0x72,0x70,0x83,0x74,0x68,0x07,0x78,0x60,0x87,0x74,
    0x18,0x87,0x74,0xa0,0x87,0x19,0xce,0x53,0x0f,0xee,0x00,0x0f,0xf2,0x50,0x0e,0xe4,
    0x90,0x0e,0xe3,0x40,0x0f,0xe1,0x20,0x0e,0xec,0x50,0x0e,0x33,0x20,0x28,0x1d,0xdc,
    0xc1,0x1e,0xc2,0x41,0x1e,0xd2,0x21,0x1c,0xdc,0x81,0x1e,0xdc,0xe0,0x1c,0xe4,0xe1,
    0x1d,0xea,0x01,0x1e,0x66,0x18,0x51,0x38,0xb0,0x43,0x3a,0x9c,0x83,0x3b,0xcc,0x50,
    0x24,0x76,0x60,0x07,0x7b,0x68,0x07,0x37,0x60,0x87,0x77,0x78,0x07,0x78,0x98,0x51,
    0x4c,0xf4,0x90,0x0f,0xf0,0x50,0x0e,0x33,0x1e,0x6a,0x1e,0xca,0x61,0x1c,0xe8,0x21,
    0x1d,0xde,0xc1,0x1d,0x7e,0x01,0x1e,0xe4,0xa1,0x1c,0xcc,0x21,0x1d,0xf0,0x61,0x06,
    0x54,0x85,0x83,0x38,0xcc,0xc3,0x3b,0xb0,0x43,0x3d,0xd0,0x43,0x39,0xfc,0xc2,0x3c,
    0xe4,0x43,0x3b,0x88,0xc3,0x3b,0xb0,0xc3,0x8c,0xc5,0x0a,0x87,0x79,0x98,0x87,0x77,
    0x18,0x87,0x74,0x08,0x07,0x7a,0x28,0x07,0x72,0x98,0x81,0x5c,0xe3,0x10,0x0e,0xec,
    0xc0,0x0e,0xe5,0x50,0x0e,0xf3,0x30,0x23,0xc1,0xd2,0x41,0x1e,0xe4,0xe1,0x17,0xd8,
    0xe1,0x1d,0xde,0x01,0x1e,0x66,0x50,0x59,0x38,0xa4,0x83,0x3c,0xb8,0x81,0x39,0xd4,
    0x83,0x3b,0x8c,0x03,0x3d,0xa4,0xc3,0x3b,0xb8,0xc3,0x2f,0x9c,0x83,0x3c,0xbc,0x43,
    0x3d,0xc0,0xc3,0x3c,0x00,0x71,0x20,0x00,0x00,0x08,0x00,0x00,0x00,0x16,0xb0,0x01,
    0x48,0xe4,0x4b,0x00,0xf3,0x2c,0xc4,0x3f,0x11,0xd7,0x44,0x45,0xc4,0x6f,0x0f,0x7e,
    0x85,0x17,0xb7,0x6d,0x00,0x05,0x03,0x20,0x0d,0x0d,0x00,0x00,0x00,0x61,0x20,0x00,
    0x00,0x0f,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x06,0x00,0x00,
    0x00,0xc4,0x46,0x00,0xc6,0x12,0x80,0x80,0xd4,0x08,0x40,0x0d,0x90,0x98,0x01,0xa0,
    0x30,0x03,0x40,0x60,0x04,0x00,0x00,0x00,0x00,0x83,0x0c,0x8b,0x60,0x8c,0x18,0x28,
    0x42,0x40,0x29,0x49,0x50,0x20,0x86,0x60,0x01,0x23,0x9f,0xd9,0x06,0x23,0x00,0x32,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
static const char _sgl_vs_source_metal_sim[756] = {
    0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
    0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
    0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
    0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
    0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x76,
    0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
    0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x6d,0x76,0x70,0x3b,0x0a,0x20,0x20,0x20,
    0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x78,0x34,0x20,0x74,0x6d,0x3b,0x0a,0x7d,0x3b,
    0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,
    0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
    0x75,0x76,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,
    0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,
    0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,
    0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,
    0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x70,
    0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,
    0x6c,0x6f,0x61,0x74,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74,0x53,0x69,0x7a,
    0x65,0x20,0x5b,0x5b,0x70,0x6f,0x69,0x6e,0x74,0x5f,0x73,0x69,0x7a,0x65,0x5d,0x5d,
    0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,
    0x6e,0x30,0x5f,0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,
    0x74,0x34,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x5b,0x5b,0x61,0x74,
    0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,
    0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x32,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,
    0x64,0x30,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,0x74,0x65,0x28,0x31,
    0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
    0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,0x62,0x75,
    0x74,0x65,0x28,0x32,0x29,0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,
    0x61,0x74,0x20,0x70,0x73,0x69,0x7a,0x65,0x20,0x5b,0x5b,0x61,0x74,0x74,0x72,0x69,
    0x62,0x75,0x74,0x65,0x28,0x33,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x76,
    0x65,0x72,0x74,0x65,0x78,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,
    0x6d,0x61,0x69,0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,
    0x6e,0x20,0x5b,0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,
    0x63,0x6f,0x6e,0x73,0x74,0x61,0x6e,0x74,0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,
    0x6d,0x73,0x26,0x20,0x5f,0x31,0x39,0x20,0x5b,0x5b,0x62,0x75,0x66,0x66,0x65,0x72,
    0x28,0x30,0x29,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x6d,0x61,0x69,
    0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,
    0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,
    0x74,0x69,0x6f,0x6e,0x20,0x3d,0x20,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70,0x20,0x2a,
    0x20,0x69,0x6e,0x2e,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x3b,0x0a,0x20,0x20,
    0x20,0x20,0x6f,0x75,0x74,0x2e,0x67,0x6c,0x5f,0x50,0x6f,0x69,0x6e,0x74,0x53,0x69,
    0x7a,0x65,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x70,0x73,0x69,0x7a,0x65,0x3b,0x0a,0x20,
    0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x75,0x76,0x20,0x3d,0x20,0x5f,0x31,0x39,0x2e,
    0x74,0x6d,0x20,0x2a,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x28,0x69,0x6e,0x2e,0x74,
    0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x2c,0x20,0x30,0x2e,0x30,0x2c,0x20,0x31,
    0x2e,0x30,0x29,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,0x63,0x6f,0x6c,
    0x6f,0x72,0x20,0x3d,0x20,0x69,0x6e,0x2e,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x3b,0x0a,
    0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,0x74,0x3b,0x0a,
    0x7d,0x0a,0x0a,0x00,
};
static const char _sgl_fs_source_metal_sim[439] = {
    0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20,0x3c,0x6d,0x65,0x74,0x61,0x6c,0x5f,
    0x73,0x74,0x64,0x6c,0x69,0x62,0x3e,0x0a,0x23,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,
    0x20,0x3c,0x73,0x69,0x6d,0x64,0x2f,0x73,0x69,0x6d,0x64,0x2e,0x68,0x3e,0x0a,0x0a,
    0x75,0x73,0x69,0x6e,0x67,0x20,0x6e,0x61,0x6d,0x65,0x73,0x70,0x61,0x63,0x65,0x20,
    0x6d,0x65,0x74,0x61,0x6c,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,
    0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,
    0x6c,0x6f,0x61,0x74,0x34,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
    0x20,0x5b,0x5b,0x63,0x6f,0x6c,0x6f,0x72,0x28,0x30,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,
    0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,
    0x69,0x6e,0x0a,0x7b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,
    0x75,0x76,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,0x30,0x29,
    0x5d,0x5d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x66,0x6c,0x6f,0x61,0x74,0x34,0x20,0x63,
    0x6f,0x6c,0x6f,0x72,0x20,0x5b,0x5b,0x75,0x73,0x65,0x72,0x28,0x6c,0x6f,0x63,0x6e,
    0x31,0x29,0x5d,0x5d,0x3b,0x0a,0x7d,0x3b,0x0a,0x0a,0x66,0x72,0x61,0x67,0x6d,0x65,
    0x6e,0x74,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6d,0x61,0x69,
    0x6e,0x30,0x28,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x69,0x6e,0x20,0x69,0x6e,0x20,0x5b,
    0x5b,0x73,0x74,0x61,0x67,0x65,0x5f,0x69,0x6e,0x5d,0x5d,0x2c,0x20,0x74,0x65,0x78,
    0x74,0x75,0x72,0x65,0x32,0x64,0x3c,0x66,0x6c,0x6f,0x61,0x74,0x3e,0x20,0x74,0x65,
    0x78,0x20,0x5b,0x5b,0x74,0x65,0x78,0x74,0x75,0x72,0x65,0x28,0x30,0x29,0x5d,0x5d,
    0x2c,0x20,0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x20,0x73,0x6d,0x70,0x20,0x5b,0x5b,
    0x73,0x61,0x6d,0x70,0x6c,0x65,0x72,0x28,0x30,0x29,0x5d,0x5d,0x29,0x0a,0x7b,0x0a,
    0x20,0x20,0x20,0x20,0x6d,0x61,0x69,0x6e,0x30,0x5f,0x6f,0x75,0x74,0x20,0x6f,0x75,
    0x74,0x20,0x3d,0x20,0x7b,0x7d,0x3b,0x0a,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x2e,
    0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x74,0x65,0x78,
    0x2e,0x73,0x61,0x6d,0x70,0x6c,0x65,0x28,0x73,0x6d,0x70,0x2c,0x20,0x69,0x6e,0x2e,
    0x75,0x76,0x2e,0x78,0x79,0x29,0x20,0x2a,0x20,0x69,0x6e,0x2e,0x63,0x6f,0x6c,0x6f,
    0x72,0x3b,0x0a,0x20,0x20,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6f,0x75,
    0x74,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
};
#elif defined(SOKOL_D3D11)
static const uint8_t _sgl_vs_bytecode_hlsl4[1032] = {
    0x44,0x58,0x42,0x43,0x74,0x7f,0x01,0xd9,0xf4,0xd5,0xed,0x1d,0x74,0xc1,0x30,0x27,
    0xd8,0xe9,0x9d,0x50,0x01,0x00,0x00,0x00,0x08,0x04,0x00,0x00,0x05,0x00,0x00,0x00,
    0x34,0x00,0x00,0x00,0x14,0x01,0x00,0x00,0x90,0x01,0x00,0x00,0x00,0x02,0x00,0x00,
    0x8c,0x03,0x00,0x00,0x52,0x44,0x45,0x46,0xd8,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
    0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xfe,0xff,
    0x10,0x81,0x00,0x00,0xaf,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,
    0x73,0x00,0xab,0xab,0x3c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x60,0x00,0x00,0x00,
    0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x98,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0xa8,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x40,0x00,0x00,0x00,
    0x02,0x00,0x00,0x00,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0x31,0x39,0x5f,
    0x6d,0x76,0x70,0x00,0x02,0x00,0x03,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x5f,0x31,0x39,0x5f,0x74,0x6d,0x00,0x4d,0x69,0x63,0x72,0x6f,
    0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,
    0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,
    0x2e,0x31,0x00,0xab,0x49,0x53,0x47,0x4e,0x74,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
    0x08,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x68,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
    0x03,0x03,0x00,0x00,0x68,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x68,0x00,0x00,0x00,
    0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x00,0xab,0xab,0xab,
    0x4f,0x53,0x47,0x4e,0x68,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
    0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,
    0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
    0x02,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,
    0x00,0x53,0x56,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x00,0xab,0xab,0xab,
    0x53,0x48,0x44,0x52,0x84,0x01,0x00,0x00,0x40,0x00,0x01,0x00,0x61,0x00,0x00,0x00,
    0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
    0x5f,0x00,0x00,0x03,0xf2,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,
    0x32,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0xf2,0x10,0x10,0x00,
    0x02,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,
    0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00,0x67,0x00,0x00,0x04,
    0xf2,0x20,0x10,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x00,0x02,
    0x01,0x00,0x00,0x00,0x38,0x00,0x00,0x08,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
    0x56,0x15,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,
    0x05,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,
    0x06,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,
    0x04,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,
    0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,
    0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x36,0x00,0x00,0x05,
    0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x02,0x00,0x00,0x00,
    0x38,0x00,0x00,0x08,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x56,0x15,0x10,0x00,
    0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
    0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x10,0x00,
    0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,
    0x00,0x00,0x00,0x00,0xa6,0x1a,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,
    0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,
    0x32,0x00,0x00,0x0a,0xf2,0x20,0x10,0x00,0x02,0x00,0x00,0x00,0xf6,0x1f,0x10,0x00,
    0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
    0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,
    0x74,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
static const uint8_t _sgl_fs_bytecode_hlsl4[608] = {
    0x44,0x58,0x42,0x43,0xc8,0x9b,0x66,0x64,0x80,0x2f,0xbe,0x14,0xd9,0x88,0xa0,0x97,
    0x64,0x14,0x66,0xff,0x01,0x00,0x00,0x00,0x60,0x02,0x00,0x00,0x05,0x00,0x00,0x00,
    0x34,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0x14,0x01,0x00,0x00,0x48,0x01,0x00,0x00,
    0xe4,0x01,0x00,0x00,0x52,0x44,0x45,0x46,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,
    0x10,0x81,0x00,0x00,0x64,0x00,0x00,0x00,0x5c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x02,0x00,0x00,0x00,
    0x05,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x73,0x6d,0x70,0x00,0x74,0x65,0x78,0x00,
    0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,
    0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,
    0x65,0x72,0x20,0x31,0x30,0x2e,0x31,0x00,0x49,0x53,0x47,0x4e,0x44,0x00,0x00,0x00,
    0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x03,0x00,0x00,
    0x38,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,
    0x00,0xab,0xab,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
    0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54,
    0x61,0x72,0x67,0x65,0x74,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0x94,0x00,0x00,0x00,
    0x40,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x5a,0x00,0x00,0x03,0x00,0x60,0x10,0x00,
    0x00,0x00,0x00,0x00,0x58,0x18,0x00,0x04,0x00,0x70,0x10,0x00,0x00,0x00,0x00,0x00,
    0x55,0x55,0x00,0x00,0x62,0x10,0x00,0x03,0x32,0x10,0x10,0x00,0x00,0x00,0x00,0x00,
    0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,
    0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,
    0x45,0x00,0x00,0x09,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x10,0x10,0x00,
    0x00,0x00,0x00,0x00,0x46,0x7e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x10,0x00,
    0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,
    0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x01,0x00,0x00,0x00,
    0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
    0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

};
#elif defined(SOKOL_WGPU)
static const char _sgl_vs_source_wgsl[1162] = {
    0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20,
    0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f,
    0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,
    0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x20,0x7b,0x0a,0x20,0x20,0x2f,0x2a,
    0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x30,0x29,0x20,0x2a,0x2f,0x0a,0x20,
    0x20,0x6d,0x76,0x70,0x20,0x3a,0x20,0x6d,0x61,0x74,0x34,0x78,0x34,0x66,0x2c,0x0a,
    0x20,0x20,0x2f,0x2a,0x20,0x40,0x6f,0x66,0x66,0x73,0x65,0x74,0x28,0x36,0x34,0x29,
    0x20,0x2a,0x2f,0x0a,0x20,0x20,0x74,0x6d,0x20,0x3a,0x20,0x6d,0x61,0x74,0x34,0x78,
    0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,0x70,0x28,0x30,0x29,
    0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x30,0x29,0x20,0x76,0x61,0x72,
    0x3c,0x75,0x6e,0x69,0x66,0x6f,0x72,0x6d,0x3e,0x20,0x78,0x5f,0x31,0x39,0x20,0x3a,
    0x20,0x76,0x73,0x5f,0x70,0x61,0x72,0x61,0x6d,0x73,0x3b,0x0a,0x0a,0x76,0x61,0x72,
    0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,
    0x6f,0x6e,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,
    0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,
    0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,
    0x76,0x61,0x74,0x65,0x3e,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,
    0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,
    0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,
    0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,
    0x74,0x65,0x3e,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3a,0x20,0x76,0x65,0x63,
    0x34,0x66,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,
    0x3e,0x20,0x70,0x73,0x69,0x7a,0x65,0x20,0x3a,0x20,0x66,0x33,0x32,0x3b,0x0a,0x0a,
    0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,0x67,0x6c,0x5f,
    0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,
    0x3b,0x0a,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,
    0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x32,0x20,0x3a,0x20,0x6d,0x61,
    0x74,0x34,0x78,0x34,0x66,0x20,0x3d,0x20,0x78,0x5f,0x31,0x39,0x2e,0x6d,0x76,0x70,
    0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x35,0x20,0x3a,0x20,0x76,
    0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,
    0x31,0x3b,0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,
    0x20,0x3d,0x20,0x28,0x78,0x5f,0x32,0x32,0x20,0x2a,0x20,0x78,0x5f,0x32,0x35,0x29,
    0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x32,0x20,0x3a,0x20,0x6d,
    0x61,0x74,0x34,0x78,0x34,0x66,0x20,0x3d,0x20,0x78,0x5f,0x31,0x39,0x2e,0x74,0x6d,
    0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x33,0x36,0x20,0x3a,0x20,0x76,
    0x65,0x63,0x32,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,
    0x3b,0x0a,0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x28,0x78,0x5f,0x33,0x32,0x20,0x2a,
    0x20,0x76,0x65,0x63,0x34,0x66,0x28,0x78,0x5f,0x33,0x36,0x2e,0x78,0x2c,0x20,0x78,
    0x5f,0x33,0x36,0x2e,0x79,0x2c,0x20,0x30,0x2e,0x30,0x66,0x2c,0x20,0x31,0x2e,0x30,
    0x66,0x29,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x34,0x35,0x20,
    0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,
    0x3b,0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x78,0x5f,0x34,0x35,
    0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,0x7d,0x0a,0x0a,0x73,
    0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,
    0x0a,0x20,0x20,0x40,0x62,0x75,0x69,0x6c,0x74,0x69,0x6e,0x28,0x70,0x6f,0x73,0x69,
    0x74,0x69,0x6f,0x6e,0x29,0x0a,0x20,0x20,0x67,0x6c,0x5f,0x50,0x6f,0x73,0x69,0x74,
    0x69,0x6f,0x6e,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,
    0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x0a,0x20,0x20,0x75,0x76,
    0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x20,0x20,0x40,0x6c,
    0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x0a,0x20,0x20,0x63,0x6f,0x6c,
    0x6f,0x72,0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,
    0x0a,0x40,0x76,0x65,0x72,0x74,0x65,0x78,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,
    0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x70,0x6f,
    0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,
    0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,
    0x6e,0x28,0x31,0x29,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,
    0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x32,0x66,0x2c,0x20,0x40,0x6c,
    0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x32,0x29,0x20,0x63,0x6f,0x6c,0x6f,0x72,
    0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,
    0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x33,0x29,0x20,0x70,0x73,
    0x69,0x7a,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x66,0x33,0x32,0x29,
    0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,0x20,
    0x20,0x70,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x20,0x3d,0x20,0x70,0x6f,
    0x73,0x69,0x74,0x69,0x6f,0x6e,0x5f,0x31,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,
    0x20,0x20,0x74,0x65,0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x20,0x3d,0x20,0x74,0x65,
    0x78,0x63,0x6f,0x6f,0x72,0x64,0x30,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,
    0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x30,
    0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x70,0x73,0x69,0x7a,0x65,0x20,
    0x3d,0x20,0x70,0x73,0x69,0x7a,0x65,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,
    0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,
    0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x28,0x67,0x6c,0x5f,
    0x50,0x6f,0x73,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x75,0x76,0x2c,0x20,0x63,0x6f,
    0x6c,0x6f,0x72,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
};
static const char _sgl_fs_source_wgsl[647] = {
    0x64,0x69,0x61,0x67,0x6e,0x6f,0x73,0x74,0x69,0x63,0x28,0x6f,0x66,0x66,0x2c,0x20,
    0x64,0x65,0x72,0x69,0x76,0x61,0x74,0x69,0x76,0x65,0x5f,0x75,0x6e,0x69,0x66,0x6f,
    0x72,0x6d,0x69,0x74,0x79,0x29,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,
    0x76,0x61,0x74,0x65,0x3e,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
    0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,0x40,0x67,0x72,0x6f,0x75,
    0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x28,0x33,0x32,
    0x29,0x20,0x76,0x61,0x72,0x20,0x74,0x65,0x78,0x20,0x3a,0x20,0x74,0x65,0x78,0x74,
    0x75,0x72,0x65,0x5f,0x32,0x64,0x3c,0x66,0x33,0x32,0x3e,0x3b,0x0a,0x0a,0x40,0x67,
    0x72,0x6f,0x75,0x70,0x28,0x31,0x29,0x20,0x40,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,
    0x28,0x34,0x38,0x29,0x20,0x76,0x61,0x72,0x20,0x73,0x6d,0x70,0x20,0x3a,0x20,0x73,
    0x61,0x6d,0x70,0x6c,0x65,0x72,0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,
    0x76,0x61,0x74,0x65,0x3e,0x20,0x75,0x76,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,
    0x3b,0x0a,0x0a,0x76,0x61,0x72,0x3c,0x70,0x72,0x69,0x76,0x61,0x74,0x65,0x3e,0x20,
    0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x3b,0x0a,0x0a,
    0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,0x28,0x29,0x20,0x7b,0x0a,0x20,0x20,
    0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,0x33,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,
    0x20,0x3d,0x20,0x75,0x76,0x3b,0x0a,0x20,0x20,0x6c,0x65,0x74,0x20,0x78,0x5f,0x32,
    0x35,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,0x20,0x74,0x65,0x78,0x74,
    0x75,0x72,0x65,0x53,0x61,0x6d,0x70,0x6c,0x65,0x28,0x74,0x65,0x78,0x2c,0x20,0x73,
    0x6d,0x70,0x2c,0x20,0x76,0x65,0x63,0x32,0x66,0x28,0x78,0x5f,0x32,0x33,0x2e,0x78,
    0x2c,0x20,0x78,0x5f,0x32,0x33,0x2e,0x79,0x29,0x29,0x3b,0x0a,0x20,0x20,0x6c,0x65,
    0x74,0x20,0x78,0x5f,0x32,0x37,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x20,0x3d,
    0x20,0x63,0x6f,0x6c,0x6f,0x72,0x3b,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,
    0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x28,0x78,0x5f,0x32,0x35,0x20,0x2a,0x20,0x78,
    0x5f,0x32,0x37,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x3b,0x0a,
    0x7d,0x0a,0x0a,0x73,0x74,0x72,0x75,0x63,0x74,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,
    0x75,0x74,0x20,0x7b,0x0a,0x20,0x20,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,
    0x28,0x30,0x29,0x0a,0x20,0x20,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
    0x5f,0x31,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x0a,0x7d,0x0a,0x0a,0x40,
    0x66,0x72,0x61,0x67,0x6d,0x65,0x6e,0x74,0x0a,0x66,0x6e,0x20,0x6d,0x61,0x69,0x6e,
    0x28,0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x30,0x29,0x20,0x75,0x76,
    0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,0x2c,0x20,
    0x40,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x28,0x31,0x29,0x20,0x63,0x6f,0x6c,
    0x6f,0x72,0x5f,0x70,0x61,0x72,0x61,0x6d,0x20,0x3a,0x20,0x76,0x65,0x63,0x34,0x66,
    0x29,0x20,0x2d,0x3e,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x6f,0x75,0x74,0x20,0x7b,0x0a,
    0x20,0x20,0x75,0x76,0x20,0x3d,0x20,0x75,0x76,0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,
    0x0a,0x20,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x3d,0x20,0x63,0x6f,0x6c,0x6f,0x72,
    0x5f,0x70,0x61,0x72,0x61,0x6d,0x3b,0x0a,0x20,0x20,0x6d,0x61,0x69,0x6e,0x5f,0x31,
    0x28,0x29,0x3b,0x0a,0x20,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x6d,0x61,0x69,
    0x6e,0x5f,0x6f,0x75,0x74,0x28,0x66,0x72,0x61,0x67,0x5f,0x63,0x6f,0x6c,0x6f,0x72,
    0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x00,
};
#elif defined(SOKOL_DUMMY_BACKEND)
static const char* _sgl_vs_source_dummy = "";
static const char* _sgl_fs_source_dummy = "";
#else
#error "Please define one of SOKOL_GLCORE33, SOKOL_GLES3, SOKOL_D3D11, SOKOL_METAL, SOKOL_WGPU or SOKOL_DUMMY_BACKEND!"
#endif

// ████████ ██    ██ ██████  ███████ ███████
//    ██     ██  ██  ██   ██ ██      ██
//    ██      ████   ██████  █████   ███████
//    ██       ██    ██      ██           ██
//    ██       ██    ██      ███████ ███████
//
// >>types
typedef enum {
    SGL_PRIMITIVETYPE_POINTS = 0,
    SGL_PRIMITIVETYPE_LINES,
    SGL_PRIMITIVETYPE_LINE_STRIP,
    SGL_PRIMITIVETYPE_TRIANGLES,
    SGL_PRIMITIVETYPE_TRIANGLE_STRIP,
    SGL_PRIMITIVETYPE_QUADS,
    SGL_NUM_PRIMITIVE_TYPES,
} _sgl_primitive_type_t;

typedef struct {
    uint32_t id;
    sg_resource_state state;
} _sgl_slot_t;

typedef struct {
    int size;
    int queue_top;
    uint32_t* gen_ctrs;
    int* free_queue;
} _sgl_pool_t;

typedef struct {
    _sgl_slot_t slot;
    sg_pipeline pip[SGL_NUM_PRIMITIVE_TYPES];
} _sgl_pipeline_t;

typedef struct {
    _sgl_pool_t pool;
    _sgl_pipeline_t* pips;
} _sgl_pipeline_pool_t;

typedef enum {
    SGL_MATRIXMODE_MODELVIEW,
    SGL_MATRIXMODE_PROJECTION,
    SGL_MATRIXMODE_TEXTURE,
    SGL_NUM_MATRIXMODES
} _sgl_matrix_mode_t;

typedef struct {
    float pos[3];
    float uv[2];
    uint32_t rgba;
    float psize;
} _sgl_vertex_t;

typedef struct {
    float v[4][4];
} _sgl_matrix_t;

typedef struct {
    _sgl_matrix_t mvp;  /* model-view-projection matrix */
    _sgl_matrix_t tm;   /* texture matrix */
} _sgl_uniform_t;

typedef enum {
    SGL_COMMAND_DRAW,
    SGL_COMMAND_VIEWPORT,
    SGL_COMMAND_SCISSOR_RECT,
} _sgl_command_type_t;

typedef struct {
    sg_pipeline pip;
    sg_image img;
    sg_sampler smp;
    int base_vertex;
    int num_vertices;
    int uniform_index;
} _sgl_draw_args_t;

typedef struct {
    int x, y, w, h;
    bool origin_top_left;
} _sgl_viewport_args_t;

typedef struct {
    int x, y, w, h;
    bool origin_top_left;
} _sgl_scissor_rect_args_t;

typedef union {
    _sgl_draw_args_t draw;
    _sgl_viewport_args_t viewport;
    _sgl_scissor_rect_args_t scissor_rect;
} _sgl_args_t;

typedef struct {
    _sgl_command_type_t cmd;
    int layer_id;
    _sgl_args_t args;
} _sgl_command_t;

#define _SGL_INVALID_SLOT_INDEX (0)
#define _SGL_MAX_STACK_DEPTH (64)
#define _SGL_DEFAULT_CONTEXT_POOL_SIZE (4)
#define _SGL_DEFAULT_PIPELINE_POOL_SIZE (64)
#define _SGL_DEFAULT_MAX_VERTICES (1<<16)
#define _SGL_DEFAULT_MAX_COMMANDS (1<<14)
#define _SGL_SLOT_SHIFT (16)
#define _SGL_MAX_POOL_SIZE (1<<_SGL_SLOT_SHIFT)
#define _SGL_SLOT_MASK (_SGL_MAX_POOL_SIZE-1)

typedef struct {
    _sgl_slot_t slot;
    sgl_context_desc_t desc;
    uint32_t frame_id;
    uint32_t update_frame_id;
    struct {
        int cap;
        int next;
        _sgl_vertex_t* ptr;
    } vertices;
    struct {
        int cap;
        int next;
        _sgl_uniform_t* ptr;
    } uniforms;
    struct {
        int cap;
        int next;
        _sgl_command_t* ptr;
    } commands;

    /* state tracking */
    int base_vertex;
    int vtx_count;          /* number of times vtx function has been called, used for non-triangle primitives */
    sgl_error_t error;
    bool in_begin;
    int layer_id;
    float u, v;
    uint32_t rgba;
    float point_size;
    _sgl_primitive_type_t cur_prim_type;
    sg_image cur_img;
    sg_sampler cur_smp;
    bool texturing_enabled;
    bool matrix_dirty;      /* reset in sgl_end(), set in any of the matrix stack functions */

    /* sokol-gfx resources */
    sg_buffer vbuf;
    sgl_pipeline def_pip;
    sg_bindings bind;

    /* pipeline stack */
    int pip_tos;
    sgl_pipeline pip_stack[_SGL_MAX_STACK_DEPTH];

    /* matrix stacks */
    _sgl_matrix_mode_t cur_matrix_mode;
    int matrix_tos[SGL_NUM_MATRIXMODES];
    _sgl_matrix_t matrix_stack[SGL_NUM_MATRIXMODES][_SGL_MAX_STACK_DEPTH];
} _sgl_context_t;

typedef struct {
    _sgl_pool_t pool;
    _sgl_context_t* contexts;
} _sgl_context_pool_t;

typedef struct {
    uint32_t init_cookie;
    sgl_desc_t desc;
    sg_image def_img;   // a default white texture
    sg_sampler def_smp; // a default sampler
    sg_shader shd;      // same shader for all contexts
    sgl_context def_ctx_id;
    sgl_context cur_ctx_id;
    _sgl_context_t* cur_ctx;   // may be 0!
    _sgl_pipeline_pool_t pip_pool;
    _sgl_context_pool_t context_pool;
} _sgl_t;
static _sgl_t _sgl;

// ██       ██████   ██████   ██████  ██ ███    ██  ██████
// ██      ██    ██ ██       ██       ██ ████   ██ ██
// ██      ██    ██ ██   ███ ██   ███ ██ ██ ██  ██ ██   ███
// ██      ██    ██ ██    ██ ██    ██ ██ ██  ██ ██ ██    ██
// ███████  ██████   ██████   ██████  ██ ██   ████  ██████
//
// >>logging
#if defined(SOKOL_DEBUG)
#define _SGL_LOGITEM_XMACRO(item,msg) #item ": " msg,
static const char* _sgl_log_messages[] = {
    _SGL_LOG_ITEMS
};
#undef _SGL_LOGITEM_XMACRO
#endif // SOKOL_DEBUG

#define _SGL_PANIC(code) _sgl_log(SGL_LOGITEM_ ##code, 0, __LINE__)
#define _SGL_ERROR(code) _sgl_log(SGL_LOGITEM_ ##code, 1, __LINE__)
#define _SGL_WARN(code) _sgl_log(SGL_LOGITEM_ ##code, 2, __LINE__)
#define _SGL_INFO(code) _sgl_log(SGL_LOGITEM_ ##code, 3, __LINE__)

static void _sgl_log(sgl_log_item_t log_item, uint32_t log_level, uint32_t line_nr) {
    if (_sgl.desc.logger.func) {
        #if defined(SOKOL_DEBUG)
            const char* filename = __FILE__;
            const char* message = _sgl_log_messages[log_item];
        #else
            const char* filename = 0;
            const char* message = 0;
        #endif
        _sgl.desc.logger.func("sgl", log_level, log_item, message, line_nr, filename, _sgl.desc.logger.user_data);
    } else {
        // for log level PANIC it would be 'undefined behaviour' to continue
        if (log_level == 0) {
            abort();
        }
    }
}

// ███    ███ ███████ ███    ███  ██████  ██████  ██    ██
// ████  ████ ██      ████  ████ ██    ██ ██   ██  ██  ██
// ██ ████ ██ █████   ██ ████ ██ ██    ██ ██████    ████
// ██  ██  ██ ██      ██  ██  ██ ██    ██ ██   ██    ██
// ██      ██ ███████ ██      ██  ██████  ██   ██    ██
//
// >>memory
static void _sgl_clear(void* ptr, size_t size) {
    SOKOL_ASSERT(ptr && (size > 0));
    memset(ptr, 0, size);
}

static void* _sgl_malloc(size_t size) {
    SOKOL_ASSERT(size > 0);
    void* ptr;
    if (_sgl.desc.allocator.alloc_fn) {
        ptr = _sgl.desc.allocator.alloc_fn(size, _sgl.desc.allocator.user_data);
    } else {
        ptr = malloc(size);
    }
    if (0 == ptr) {
        _SGL_PANIC(MALLOC_FAILED);
    }
    return ptr;
}

static void* _sgl_malloc_clear(size_t size) {
    void* ptr = _sgl_malloc(size);
    _sgl_clear(ptr, size);
    return ptr;
}

static void _sgl_free(void* ptr) {
    if (_sgl.desc.allocator.free_fn) {
        _sgl.desc.allocator.free_fn(ptr, _sgl.desc.allocator.user_data);
    } else {
        free(ptr);
    }
}

// ██████   ██████   ██████  ██
// ██   ██ ██    ██ ██    ██ ██
// ██████  ██    ██ ██    ██ ██
// ██      ██    ██ ██    ██ ██
// ██       ██████   ██████  ███████
//
// >>pool
static void _sgl_init_pool(_sgl_pool_t* pool, int num) {
    SOKOL_ASSERT(pool && (num >= 1));
    /* slot 0 is reserved for the 'invalid id', so bump the pool size by 1 */
    pool->size = num + 1;
    pool->queue_top = 0;
    /* generation counters indexable by pool slot index, slot 0 is reserved */
    size_t gen_ctrs_size = sizeof(uint32_t) * (size_t)pool->size;
    pool->gen_ctrs = (uint32_t*) _sgl_malloc_clear(gen_ctrs_size);
    /* it's not a bug to only reserve 'num' here */
    pool->free_queue = (int*) _sgl_malloc_clear(sizeof(int) * (size_t)num);
    /* never allocate the zero-th pool item since the invalid id is 0 */
    for (int i = pool->size-1; i >= 1; i--) {
        pool->free_queue[pool->queue_top++] = i;
    }
}

static void _sgl_discard_pool(_sgl_pool_t* pool) {
    SOKOL_ASSERT(pool);
    SOKOL_ASSERT(pool->free_queue);
    _sgl_free(pool->free_queue);
    pool->free_queue = 0;
    SOKOL_ASSERT(pool->gen_ctrs);
    _sgl_free(pool->gen_ctrs);
    pool->gen_ctrs = 0;
    pool->size = 0;
    pool->queue_top = 0;
}

static int _sgl_pool_alloc_index(_sgl_pool_t* pool) {
    SOKOL_ASSERT(pool);
    SOKOL_ASSERT(pool->free_queue);
    if (pool->queue_top > 0) {
        int slot_index = pool->free_queue[--pool->queue_top];
        SOKOL_ASSERT((slot_index > 0) && (slot_index < pool->size));
        return slot_index;
    } else {
        // pool exhausted
        return _SGL_INVALID_SLOT_INDEX;
    }
}

static void _sgl_pool_free_index(_sgl_pool_t* pool, int slot_index) {
    SOKOL_ASSERT((slot_index > _SGL_INVALID_SLOT_INDEX) && (slot_index < pool->size));
    SOKOL_ASSERT(pool);
    SOKOL_ASSERT(pool->free_queue);
    SOKOL_ASSERT(pool->queue_top < pool->size);
    #ifdef SOKOL_DEBUG
    /* debug check against double-free */
    for (int i = 0; i < pool->queue_top; i++) {
        SOKOL_ASSERT(pool->free_queue[i] != slot_index);
    }
    #endif
    pool->free_queue[pool->queue_top++] = slot_index;
    SOKOL_ASSERT(pool->queue_top <= (pool->size-1));
}

/* allocate the slot at slot_index:
    - bump the slot's generation counter
    - create a resource id from the generation counter and slot index
    - set the slot's id to this id
    - set the slot's state to ALLOC
    - return the resource id
*/
static uint32_t _sgl_slot_alloc(_sgl_pool_t* pool, _sgl_slot_t* slot, int slot_index) {
    /* FIXME: add handling for an overflowing generation counter,
       for now, just overflow (another option is to disable
       the slot)
    */
    SOKOL_ASSERT(pool && pool->gen_ctrs);
    SOKOL_ASSERT((slot_index > _SGL_INVALID_SLOT_INDEX) && (slot_index < pool->size));
    SOKOL_ASSERT((slot->state == SG_RESOURCESTATE_INITIAL) && (slot->id == SG_INVALID_ID));
    uint32_t ctr = ++pool->gen_ctrs[slot_index];
    slot->id = (ctr<<_SGL_SLOT_SHIFT)|(slot_index & _SGL_SLOT_MASK);
    slot->state = SG_RESOURCESTATE_ALLOC;
    return slot->id;
}

/* extract slot index from id */
static int _sgl_slot_index(uint32_t id) {
    int slot_index = (int) (id & _SGL_SLOT_MASK);
    SOKOL_ASSERT(_SGL_INVALID_SLOT_INDEX != slot_index);
    return slot_index;
}

// ██████  ██ ██████  ███████ ██      ██ ███    ██ ███████ ███████
// ██   ██ ██ ██   ██ ██      ██      ██ ████   ██ ██      ██
// ██████  ██ ██████  █████   ██      ██ ██ ██  ██ █████   ███████
// ██      ██ ██      ██      ██      ██ ██  ██ ██ ██           ██
// ██      ██ ██      ███████ ███████ ██ ██   ████ ███████ ███████
//
// >>pipelines
static void _sgl_reset_pipeline(_sgl_pipeline_t* pip) {
    SOKOL_ASSERT(pip);
    _sgl_clear(pip, sizeof(_sgl_pipeline_t));
}

static void _sgl_setup_pipeline_pool(int pool_size) {
    /* note: the pools here will have an additional item, since slot 0 is reserved */
    SOKOL_ASSERT((pool_size > 0) && (pool_size < _SGL_MAX_POOL_SIZE));
    _sgl_init_pool(&_sgl.pip_pool.pool, pool_size);
    size_t pool_byte_size = sizeof(_sgl_pipeline_t) * (size_t)_sgl.pip_pool.pool.size;
    _sgl.pip_pool.pips = (_sgl_pipeline_t*) _sgl_malloc_clear(pool_byte_size);
}

static void _sgl_discard_pipeline_pool(void) {
    SOKOL_ASSERT(0 != _sgl.pip_pool.pips);
    _sgl_free(_sgl.pip_pool.pips); _sgl.pip_pool.pips = 0;
    _sgl_discard_pool(&_sgl.pip_pool.pool);
}

/* get pipeline pointer without id-check */
static _sgl_pipeline_t* _sgl_pipeline_at(uint32_t pip_id) {
    SOKOL_ASSERT(SG_INVALID_ID != pip_id);
    int slot_index = _sgl_slot_index(pip_id);
    SOKOL_ASSERT((slot_index > _SGL_INVALID_SLOT_INDEX) && (slot_index < _sgl.pip_pool.pool.size));
    return &_sgl.pip_pool.pips[slot_index];
}

/* get pipeline pointer with id-check, returns 0 if no match */
static _sgl_pipeline_t* _sgl_lookup_pipeline(uint32_t pip_id) {
    if (SG_INVALID_ID != pip_id) {
        _sgl_pipeline_t* pip = _sgl_pipeline_at(pip_id);
        if (pip->slot.id == pip_id) {
            return pip;
        }
    }
    return 0;
}

/* make pipeline id from uint32_t id */
static sgl_pipeline _sgl_make_pip_id(uint32_t pip_id) {
    sgl_pipeline pip = { pip_id };
    return pip;
}

static sgl_pipeline _sgl_alloc_pipeline(void) {
    sgl_pipeline res;
    int slot_index = _sgl_pool_alloc_index(&_sgl.pip_pool.pool);
    if (_SGL_INVALID_SLOT_INDEX != slot_index) {
        res = _sgl_make_pip_id(_sgl_slot_alloc(&_sgl.pip_pool.pool, &_sgl.pip_pool.pips[slot_index].slot, slot_index));
    } else {
        /* pool is exhausted */
        res = _sgl_make_pip_id(SG_INVALID_ID);
    }
    return res;
}

static void _sgl_init_pipeline(sgl_pipeline pip_id, const sg_pipeline_desc* in_desc, const sgl_context_desc_t* ctx_desc) {
    SOKOL_ASSERT((pip_id.id != SG_INVALID_ID) && in_desc && ctx_desc);

    /* create a new desc with 'patched' shader and pixel format state */
    sg_pipeline_desc desc = *in_desc;
    desc.layout.buffers[0].stride = sizeof(_sgl_vertex_t);
    {
        sg_vertex_attr_state* pos = &desc.layout.attrs[0];
        pos->offset = offsetof(_sgl_vertex_t, pos);
        pos->format = SG_VERTEXFORMAT_FLOAT3;
    }
    {
        sg_vertex_attr_state* uv = &desc.layout.attrs[1];
        uv->offset = offsetof(_sgl_vertex_t, uv);
        uv->format = SG_VERTEXFORMAT_FLOAT2;
    }
    {
        sg_vertex_attr_state* rgba = &desc.layout.attrs[2];
        rgba->offset = offsetof(_sgl_vertex_t, rgba);
        rgba->format = SG_VERTEXFORMAT_UBYTE4N;
    }
    {
        sg_vertex_attr_state* psize = &desc.layout.attrs[3];
        psize->offset = offsetof(_sgl_vertex_t, psize);
        psize->format = SG_VERTEXFORMAT_FLOAT;
    }
    if (in_desc->shader.id == SG_INVALID_ID) {
        desc.shader = _sgl.shd;
    }
    desc.index_type = SG_INDEXTYPE_NONE;
    desc.sample_count = ctx_desc->sample_count;
    if (desc.face_winding == _SG_FACEWINDING_DEFAULT) {
        desc.face_winding = _sgl.desc.face_winding;
    }
    desc.depth.pixel_format = ctx_desc->depth_format;
    if (ctx_desc->depth_format == SG_PIXELFORMAT_NONE) {
        desc.depth.write_enabled = false;
    }
    desc.colors[0].pixel_format = ctx_desc->color_format;
    if (desc.colors[0].write_mask == _SG_COLORMASK_DEFAULT) {
        desc.colors[0].write_mask = SG_COLORMASK_RGB;
    }

    _sgl_pipeline_t* pip = _sgl_lookup_pipeline(pip_id.id);
    SOKOL_ASSERT(pip && (pip->slot.state == SG_RESOURCESTATE_ALLOC));
    pip->slot.state = SG_RESOURCESTATE_VALID;
    for (int i = 0; i < SGL_NUM_PRIMITIVE_TYPES; i++) {
        switch (i) {
            case SGL_PRIMITIVETYPE_POINTS:
                desc.primitive_type = SG_PRIMITIVETYPE_POINTS;
                break;
            case SGL_PRIMITIVETYPE_LINES:
                desc.primitive_type = SG_PRIMITIVETYPE_LINES;
                break;
            case SGL_PRIMITIVETYPE_LINE_STRIP:
                desc.primitive_type = SG_PRIMITIVETYPE_LINE_STRIP;
                break;
            case SGL_PRIMITIVETYPE_TRIANGLES:
                desc.primitive_type = SG_PRIMITIVETYPE_TRIANGLES;
                break;
            case SGL_PRIMITIVETYPE_TRIANGLE_STRIP:
            case SGL_PRIMITIVETYPE_QUADS:
                desc.primitive_type = SG_PRIMITIVETYPE_TRIANGLE_STRIP;
                break;
        }
        if (SGL_PRIMITIVETYPE_QUADS == i) {
            /* quads are emulated via triangles, use the same pipeline object */
            pip->pip[i] = pip->pip[SGL_PRIMITIVETYPE_TRIANGLES];
        } else {
            pip->pip[i] = sg_make_pipeline(&desc);
            if (pip->pip[i].id == SG_INVALID_ID) {
                _SGL_ERROR(MAKE_PIPELINE_FAILED);
                pip->slot.state = SG_RESOURCESTATE_FAILED;
            }
        }
    }
}

static sgl_pipeline _sgl_make_pipeline(const sg_pipeline_desc* desc, const sgl_context_desc_t* ctx_desc) {
    SOKOL_ASSERT(desc && ctx_desc);
    sgl_pipeline pip_id = _sgl_alloc_pipeline();
    if (pip_id.id != SG_INVALID_ID) {
        _sgl_init_pipeline(pip_id, desc, ctx_desc);
    } else {
        _SGL_ERROR(PIPELINE_POOL_EXHAUSTED);
    }
    return pip_id;
}

static void _sgl_destroy_pipeline(sgl_pipeline pip_id) {
    _sgl_pipeline_t* pip = _sgl_lookup_pipeline(pip_id.id);
    if (pip) {
        sg_push_debug_group("sokol-gl");
        for (int i = 0; i < SGL_NUM_PRIMITIVE_TYPES; i++) {
            if (i != SGL_PRIMITIVETYPE_QUADS) {
                sg_destroy_pipeline(pip->pip[i]);
            }
        }
        sg_pop_debug_group();
        _sgl_reset_pipeline(pip);
        _sgl_pool_free_index(&_sgl.pip_pool.pool, _sgl_slot_index(pip_id.id));
    }
}

static sg_pipeline _sgl_get_pipeline(sgl_pipeline pip_id, _sgl_primitive_type_t prim_type) {
    _sgl_pipeline_t* pip = _sgl_lookup_pipeline(pip_id.id);
    if (pip) {
        return pip->pip[prim_type];
    } else {
        sg_pipeline dummy_id = { SG_INVALID_ID };
        return dummy_id;
    }
}

//  ██████  ██████  ███    ██ ████████ ███████ ██   ██ ████████ ███████
// ██      ██    ██ ████   ██    ██    ██       ██ ██     ██    ██
// ██      ██    ██ ██ ██  ██    ██    █████     ███      ██    ███████
// ██      ██    ██ ██  ██ ██    ██    ██       ██ ██     ██         ██
//  ██████  ██████  ██   ████    ██    ███████ ██   ██    ██    ███████
//
// >>contexts
static void _sgl_reset_context(_sgl_context_t* ctx) {
    SOKOL_ASSERT(ctx);
    SOKOL_ASSERT(0 == ctx->vertices.ptr);
    SOKOL_ASSERT(0 == ctx->uniforms.ptr);
    SOKOL_ASSERT(0 == ctx->commands.ptr);
    _sgl_clear(ctx, sizeof(_sgl_context_t));
}

static void _sgl_setup_context_pool(int pool_size) {
    /* note: the pools here will have an additional item, since slot 0 is reserved */
    SOKOL_ASSERT((pool_size > 0) && (pool_size < _SGL_MAX_POOL_SIZE));
    _sgl_init_pool(&_sgl.context_pool.pool, pool_size);
    size_t pool_byte_size = sizeof(_sgl_context_t) * (size_t)_sgl.context_pool.pool.size;
    _sgl.context_pool.contexts = (_sgl_context_t*) _sgl_malloc_clear(pool_byte_size);
}

static void _sgl_discard_context_pool(void) {
    SOKOL_ASSERT(0 != _sgl.context_pool.contexts);
    _sgl_free(_sgl.context_pool.contexts); _sgl.context_pool.contexts = 0;
    _sgl_discard_pool(&_sgl.context_pool.pool);
}

// get context pointer without id-check
static _sgl_context_t* _sgl_context_at(uint32_t ctx_id) {
    SOKOL_ASSERT(SG_INVALID_ID != ctx_id);
    int slot_index = _sgl_slot_index(ctx_id);
    SOKOL_ASSERT((slot_index > _SGL_INVALID_SLOT_INDEX) && (slot_index < _sgl.context_pool.pool.size));
    return &_sgl.context_pool.contexts[slot_index];
}

// get context pointer with id-check, returns 0 if no match
static _sgl_context_t* _sgl_lookup_context(uint32_t ctx_id) {
    if (SG_INVALID_ID != ctx_id) {
        _sgl_context_t* ctx = _sgl_context_at(ctx_id);
        if (ctx->slot.id == ctx_id) {
            return ctx;
        }
    }
    return 0;
}

// make context id from uint32_t id
static sgl_context _sgl_make_ctx_id(uint32_t ctx_id) {
    sgl_context ctx = { ctx_id };
    return ctx;
}

static sgl_context _sgl_alloc_context(void) {
    sgl_context res;
    int slot_index = _sgl_pool_alloc_index(&_sgl.context_pool.pool);
    if (_SGL_INVALID_SLOT_INDEX != slot_index) {
        res = _sgl_make_ctx_id(_sgl_slot_alloc(&_sgl.context_pool.pool, &_sgl.context_pool.contexts[slot_index].slot, slot_index));
    } else {
        // pool is exhausted
        res = _sgl_make_ctx_id(SG_INVALID_ID);
    }
    return res;
}

// return sgl_context_desc_t with patched defaults
static sgl_context_desc_t _sgl_context_desc_defaults(const sgl_context_desc_t* desc) {
    sgl_context_desc_t res = *desc;
    res.max_vertices = _sgl_def(desc->max_vertices, _SGL_DEFAULT_MAX_VERTICES);
    res.max_commands = _sgl_def(desc->max_commands, _SGL_DEFAULT_MAX_COMMANDS);
    return res;
}

static void _sgl_identity(_sgl_matrix_t*);
static sg_commit_listener _sgl_make_commit_listener(_sgl_context_t* ctx);
static void _sgl_init_context(sgl_context ctx_id, const sgl_context_desc_t* in_desc) {
    SOKOL_ASSERT((ctx_id.id != SG_INVALID_ID) && in_desc);
    _sgl_context_t* ctx = _sgl_lookup_context(ctx_id.id);
    SOKOL_ASSERT(ctx);
    ctx->desc = _sgl_context_desc_defaults(in_desc);
    // NOTE: frame_id must be non-zero, so that updates trigger in first frame
    ctx->frame_id = 1;
    ctx->cur_img = _sgl.def_img;
    ctx->cur_smp = _sgl.def_smp;

    // allocate buffers and pools
    ctx->vertices.cap = ctx->desc.max_vertices;
    ctx->commands.cap = ctx->uniforms.cap = ctx->desc.max_commands;
    ctx->vertices.ptr = (_sgl_vertex_t*) _sgl_malloc((size_t)ctx->vertices.cap * sizeof(_sgl_vertex_t));
    ctx->uniforms.ptr = (_sgl_uniform_t*) _sgl_malloc((size_t)ctx->uniforms.cap * sizeof(_sgl_uniform_t));
    ctx->commands.ptr = (_sgl_command_t*) _sgl_malloc((size_t)ctx->commands.cap * sizeof(_sgl_command_t));

    // create sokol-gfx resource objects
    sg_push_debug_group("sokol-gl");

    sg_buffer_desc vbuf_desc;
    _sgl_clear(&vbuf_desc, sizeof(vbuf_desc));
    vbuf_desc.size = (size_t)ctx->vertices.cap * sizeof(_sgl_vertex_t);
    vbuf_desc.type = SG_BUFFERTYPE_VERTEXBUFFER;
    vbuf_desc.usage = SG_USAGE_STREAM;
    vbuf_desc.label = "sgl-vertex-buffer";
    ctx->vbuf = sg_make_buffer(&vbuf_desc);
    SOKOL_ASSERT(SG_INVALID_ID != ctx->vbuf.id);
    ctx->bind.vertex_buffers[0] = ctx->vbuf;

    sg_pipeline_desc def_pip_desc;
    _sgl_clear(&def_pip_desc, sizeof(def_pip_desc));
    def_pip_desc.depth.write_enabled = true;
    ctx->def_pip = _sgl_make_pipeline(&def_pip_desc, &ctx->desc);
    if (!sg_add_commit_listener(_sgl_make_commit_listener(ctx))) {
        _SGL_ERROR(ADD_COMMIT_LISTENER_FAILED);
    }
    sg_pop_debug_group();

    // default state
    ctx->rgba = 0xFFFFFFFF;
    ctx->point_size = 1.0f;
    for (int i = 0; i < SGL_NUM_MATRIXMODES; i++) {
        _sgl_identity(&ctx->matrix_stack[i][0]);
    }
    ctx->pip_stack[0] = ctx->def_pip;
    ctx->matrix_dirty = true;
}

static sgl_context _sgl_make_context(const sgl_context_desc_t* desc) {
    SOKOL_ASSERT(desc);
    sgl_context ctx_id = _sgl_alloc_context();
    if (ctx_id.id != SG_INVALID_ID) {
        _sgl_init_context(ctx_id, desc);
    } else {
        _SGL_ERROR(CONTEXT_POOL_EXHAUSTED);
    }
    return ctx_id;
}

static void _sgl_destroy_context(sgl_context ctx_id) {
    _sgl_context_t* ctx = _sgl_lookup_context(ctx_id.id);
    if (ctx) {
        SOKOL_ASSERT(ctx->vertices.ptr);
        SOKOL_ASSERT(ctx->uniforms.ptr);
        SOKOL_ASSERT(ctx->commands.ptr);

        _sgl_free(ctx->vertices.ptr);
        _sgl_free(ctx->uniforms.ptr);
        _sgl_free(ctx->commands.ptr);
        ctx->vertices.ptr = 0;
        ctx->uniforms.ptr = 0;
        ctx->commands.ptr = 0;

        sg_push_debug_group("sokol-gl");
        sg_destroy_buffer(ctx->vbuf);
        _sgl_destroy_pipeline(ctx->def_pip);
        sg_remove_commit_listener(_sgl_make_commit_listener(ctx));
        sg_pop_debug_group();

        _sgl_reset_context(ctx);
        _sgl_pool_free_index(&_sgl.context_pool.pool, _sgl_slot_index(ctx_id.id));
    }
}

// ███    ███ ██ ███████  ██████
// ████  ████ ██ ██      ██
// ██ ████ ██ ██ ███████ ██
// ██  ██  ██ ██      ██ ██
// ██      ██ ██ ███████  ██████
//
// >>misc
static void _sgl_begin(_sgl_context_t* ctx, _sgl_primitive_type_t mode) {
    ctx->in_begin = true;
    ctx->base_vertex = ctx->vertices.next;
    ctx->vtx_count = 0;
    ctx->cur_prim_type = mode;
}

static void _sgl_rewind(_sgl_context_t* ctx) {
    ctx->frame_id++;
    ctx->vertices.next = 0;
    ctx->uniforms.next = 0;
    ctx->commands.next = 0;
    ctx->base_vertex = 0;
    ctx->error = SGL_NO_ERROR;
    ctx->layer_id = 0;
    ctx->matrix_dirty = true;
}

// called from inside sokol-gfx sg_commit()
static void _sgl_commit_listener(void* userdata) {
    _sgl_context_t* ctx = _sgl_lookup_context((uint32_t)(uintptr_t)userdata);
    if (ctx) {
        _sgl_rewind(ctx);
    }
}

static sg_commit_listener _sgl_make_commit_listener(_sgl_context_t* ctx) {
    sg_commit_listener listener = { _sgl_commit_listener, (void*)(uintptr_t)(ctx->slot.id) };
    return listener;
}

static _sgl_vertex_t* _sgl_next_vertex(_sgl_context_t* ctx) {
    if (ctx->vertices.next < ctx->vertices.cap) {
        return &ctx->vertices.ptr[ctx->vertices.next++];
    } else {
        ctx->error = SGL_ERROR_VERTICES_FULL;
        return 0;
    }
}

static _sgl_uniform_t* _sgl_next_uniform(_sgl_context_t* ctx) {
    if (ctx->uniforms.next < ctx->uniforms.cap) {
        return &ctx->uniforms.ptr[ctx->uniforms.next++];
    } else {
        ctx->error = SGL_ERROR_UNIFORMS_FULL;
        return 0;
    }
}

static _sgl_command_t* _sgl_cur_command(_sgl_context_t* ctx) {
    if (ctx->commands.next > 0) {
        return &ctx->commands.ptr[ctx->commands.next - 1];
    } else {
        return 0;
    }
}

static _sgl_command_t* _sgl_next_command(_sgl_context_t* ctx) {
    if (ctx->commands.next < ctx->commands.cap) {
        return &ctx->commands.ptr[ctx->commands.next++];
    } else {
        ctx->error = SGL_ERROR_COMMANDS_FULL;
        return 0;
    }
}

static uint32_t _sgl_pack_rgbab(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
    return (uint32_t)(((uint32_t)a<<24)|((uint32_t)b<<16)|((uint32_t)g<<8)|r);
}

static float _sgl_clamp(float v, float lo, float hi) {
    if (v < lo) return lo;
    else if (v > hi) return hi;
    else return v;
}

static uint32_t _sgl_pack_rgbaf(float r, float g, float b, float a) {
    uint8_t r_u8 = (uint8_t) (_sgl_clamp(r, 0.0f, 1.0f) * 255.0f);
    uint8_t g_u8 = (uint8_t) (_sgl_clamp(g, 0.0f, 1.0f) * 255.0f);
    uint8_t b_u8 = (uint8_t) (_sgl_clamp(b, 0.0f, 1.0f) * 255.0f);
    uint8_t a_u8 = (uint8_t) (_sgl_clamp(a, 0.0f, 1.0f) * 255.0f);
    return _sgl_pack_rgbab(r_u8, g_u8, b_u8, a_u8);
}

static void _sgl_vtx(_sgl_context_t* ctx, float x, float y, float z, float u, float v, uint32_t rgba) {
    SOKOL_ASSERT(ctx->in_begin);
    _sgl_vertex_t* vtx;
    /* handle non-native primitive types */
    if ((ctx->cur_prim_type == SGL_PRIMITIVETYPE_QUADS) && ((ctx->vtx_count & 3) == 3)) {
        /* for quads, before writing the last quad vertex, reuse
           the first and third vertex to start the second triangle in the quad
        */
        vtx = _sgl_next_vertex(ctx);
        if (vtx) { *vtx = *(vtx - 3); }
        vtx = _sgl_next_vertex(ctx);
        if (vtx) { *vtx = *(vtx - 2); }
    }
    vtx = _sgl_next_vertex(ctx);
    if (vtx) {
        vtx->pos[0] = x; vtx->pos[1] = y; vtx->pos[2] = z;
        vtx->uv[0] = u; vtx->uv[1] = v;
        vtx->rgba = rgba;
        vtx->psize = ctx->point_size;
    }
    ctx->vtx_count++;
}

static void _sgl_identity(_sgl_matrix_t* m) {
    for (int c = 0; c < 4; c++) {
        for (int r = 0; r < 4; r++) {
            m->v[c][r] = (r == c) ? 1.0f : 0.0f;
        }
    }
}

static void _sgl_transpose(_sgl_matrix_t* dst, const _sgl_matrix_t* m) {
    SOKOL_ASSERT(dst != m);
    for (int c = 0; c < 4; c++) {
        for (int r = 0; r < 4; r++) {
            dst->v[r][c] = m->v[c][r];
        }
    }
}

/* _sgl_rotate, _sgl_frustum, _sgl_ortho from MESA m_matric.c */
static void _sgl_matmul4(_sgl_matrix_t* p, const _sgl_matrix_t* a, const _sgl_matrix_t* b) {
    for (int r = 0; r < 4; r++) {
        float ai0=a->v[0][r], ai1=a->v[1][r], ai2=a->v[2][r], ai3=a->v[3][r];
        p->v[0][r] = ai0*b->v[0][0] + ai1*b->v[0][1] + ai2*b->v[0][2] + ai3*b->v[0][3];
        p->v[1][r] = ai0*b->v[1][0] + ai1*b->v[1][1] + ai2*b->v[1][2] + ai3*b->v[1][3];
        p->v[2][r] = ai0*b->v[2][0] + ai1*b->v[2][1] + ai2*b->v[2][2] + ai3*b->v[2][3];
        p->v[3][r] = ai0*b->v[3][0] + ai1*b->v[3][1] + ai2*b->v[3][2] + ai3*b->v[3][3];
    }
}

static void _sgl_mul(_sgl_matrix_t* dst, const _sgl_matrix_t* m) {
    _sgl_matmul4(dst, dst, m);
}

static void _sgl_rotate(_sgl_matrix_t* dst, float a, float x, float y, float z) {

    float s = sinf(a);
    float c = cosf(a);

    float mag = sqrtf(x*x + y*y + z*z);
    if (mag < 1.0e-4F) {
        return;
    }
    x /= mag;
    y /= mag;
    z /= mag;
    float xx = x * x;
    float yy = y * y;
    float zz = z * z;
    float xy = x * y;
    float yz = y * z;
    float zx = z * x;
    float xs = x * s;
    float ys = y * s;
    float zs = z * s;
    float one_c = 1.0f - c;

    _sgl_matrix_t m;
    m.v[0][0] = (one_c * xx) + c;
    m.v[1][0] = (one_c * xy) - zs;
    m.v[2][0] = (one_c * zx) + ys;
    m.v[3][0] = 0.0f;
    m.v[0][1] = (one_c * xy) + zs;
    m.v[1][1] = (one_c * yy) + c;
    m.v[2][1] = (one_c * yz) - xs;
    m.v[3][1] = 0.0f;
    m.v[0][2] = (one_c * zx) - ys;
    m.v[1][2] = (one_c * yz) + xs;
    m.v[2][2] = (one_c * zz) + c;
    m.v[3][2] = 0.0f;
    m.v[0][3] = 0.0f;
    m.v[1][3] = 0.0f;
    m.v[2][3] = 0.0f;
    m.v[3][3] = 1.0f;
    _sgl_mul(dst, &m);
}

static void _sgl_scale(_sgl_matrix_t* dst, float x, float y, float z) {
    for (int r = 0; r < 4; r++) {
        dst->v[0][r] *= x;
        dst->v[1][r] *= y;
        dst->v[2][r] *= z;
    }
}

static void _sgl_translate(_sgl_matrix_t* dst, float x, float y, float z) {
    for (int r = 0; r < 4; r++) {
        dst->v[3][r] = dst->v[0][r]*x + dst->v[1][r]*y + dst->v[2][r]*z + dst->v[3][r];
    }
}

static void _sgl_frustum(_sgl_matrix_t* dst, float left, float right, float bottom, float top, float znear, float zfar) {
    float x = (2.0f * znear) / (right - left);
    float y = (2.0f * znear) / (top - bottom);
    float a = (right + left) / (right - left);
    float b = (top + bottom) / (top - bottom);
    float c = -(zfar + znear) / (zfar - znear);
    float d = -(2.0f * zfar * znear) / (zfar - znear);
    _sgl_matrix_t m;
    m.v[0][0] = x;    m.v[0][1] = 0.0f; m.v[0][2] = 0.0f; m.v[0][3] = 0.0f;
    m.v[1][0] = 0.0f; m.v[1][1] = y;    m.v[1][2] = 0.0f; m.v[1][3] = 0.0f;
    m.v[2][0] = a;    m.v[2][1] = b;    m.v[2][2] = c;    m.v[2][3] = -1.0f;
    m.v[3][0] = 0.0f; m.v[3][1] = 0.0f; m.v[3][2] = d;    m.v[3][3] = 0.0f;
    _sgl_mul(dst, &m);
}

static void _sgl_ortho(_sgl_matrix_t* dst, float left, float right, float bottom, float top, float znear, float zfar) {
    _sgl_matrix_t m;
    m.v[0][0] = 2.0f / (right - left);
    m.v[1][0] = 0.0f;
    m.v[2][0] = 0.0f;
    m.v[3][0] = -(right + left) / (right - left);
    m.v[0][1] = 0.0f;
    m.v[1][1] = 2.0f / (top - bottom);
    m.v[2][1] = 0.0f;
    m.v[3][1] = -(top + bottom) / (top - bottom);
    m.v[0][2] = 0.0f;
    m.v[1][2] = 0.0f;
    m.v[2][2] = -2.0f / (zfar - znear);
    m.v[3][2] = -(zfar + znear) / (zfar - znear);
    m.v[0][3] = 0.0f;
    m.v[1][3] = 0.0f;
    m.v[2][3] = 0.0f;
    m.v[3][3] = 1.0f;

    _sgl_mul(dst, &m);
}

/* _sgl_perspective, _sgl_lookat from Regal project.c */
static void _sgl_perspective(_sgl_matrix_t* dst, float fovy, float aspect, float znear, float zfar) {
    float sine = sinf(fovy / 2.0f);
    float delta_z = zfar - znear;
    if ((delta_z == 0.0f) || (sine == 0.0f) || (aspect == 0.0f)) {
        return;
    }
    float cotan = cosf(fovy / 2.0f) / sine;
    _sgl_matrix_t m;
    _sgl_identity(&m);
    m.v[0][0] = cotan / aspect;
    m.v[1][1] = cotan;
    m.v[2][2] = -(zfar + znear) / delta_z;
    m.v[2][3] = -1.0f;
    m.v[3][2] = -2.0f * znear * zfar / delta_z;
    m.v[3][3] = 0.0f;
    _sgl_mul(dst, &m);
}

static void _sgl_normalize(float v[3]) {
    float r = sqrtf(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
    if (r == 0.0f) {
        return;
    }
    v[0] /= r;
    v[1] /= r;
    v[2] /= r;
}

static void _sgl_cross(float v1[3], float v2[3], float res[3]) {
    res[0] = v1[1]*v2[2] - v1[2]*v2[1];
    res[1] = v1[2]*v2[0] - v1[0]*v2[2];
    res[2] = v1[0]*v2[1] - v1[1]*v2[0];
}

static void _sgl_lookat(_sgl_matrix_t* dst,
                        float eye_x, float eye_y, float eye_z,
                        float center_x, float center_y, float center_z,
                        float up_x, float up_y, float up_z)
{
    float fwd[3], side[3], up[3];

    fwd[0] = center_x - eye_x; fwd[1] = center_y - eye_y; fwd[2] = center_z - eye_z;
    up[0] = up_x; up[1] = up_y; up[2] = up_z;
    _sgl_normalize(fwd);
    _sgl_cross(fwd, up, side);
    _sgl_normalize(side);
    _sgl_cross(side, fwd, up);

    _sgl_matrix_t m;
    _sgl_identity(&m);
    m.v[0][0] = side[0];
    m.v[1][0] = side[1];
    m.v[2][0] = side[2];
    m.v[0][1] = up[0];
    m.v[1][1] = up[1];
    m.v[2][1] = up[2];
    m.v[0][2] = -fwd[0];
    m.v[1][2] = -fwd[1];
    m.v[2][2] = -fwd[2];
    _sgl_mul(dst, &m);
    _sgl_translate(dst, -eye_x, -eye_y, -eye_z);
}

/* current top-of-stack projection matrix */
static _sgl_matrix_t* _sgl_matrix_projection(_sgl_context_t* ctx) {
    return &ctx->matrix_stack[SGL_MATRIXMODE_PROJECTION][ctx->matrix_tos[SGL_MATRIXMODE_PROJECTION]];
}

/* get top-of-stack modelview matrix */
static _sgl_matrix_t* _sgl_matrix_modelview(_sgl_context_t* ctx) {
    return &ctx->matrix_stack[SGL_MATRIXMODE_MODELVIEW][ctx->matrix_tos[SGL_MATRIXMODE_MODELVIEW]];
}

/* get top-of-stack texture matrix */
static _sgl_matrix_t* _sgl_matrix_texture(_sgl_context_t* ctx) {
    return &ctx->matrix_stack[SGL_MATRIXMODE_TEXTURE][ctx->matrix_tos[SGL_MATRIXMODE_TEXTURE]];
}

/* get pointer to current top-of-stack of current matrix mode */
static _sgl_matrix_t* _sgl_matrix(_sgl_context_t* ctx) {
    return &ctx->matrix_stack[ctx->cur_matrix_mode][ctx->matrix_tos[ctx->cur_matrix_mode]];
}

// return sg_context_desc_t with patched defaults
static sgl_desc_t _sgl_desc_defaults(const sgl_desc_t* desc) {
    SOKOL_ASSERT((desc->allocator.alloc_fn && desc->allocator.free_fn) || (!desc->allocator.alloc_fn && !desc->allocator.free_fn));
    sgl_desc_t res = *desc;
    res.max_vertices = _sgl_def(desc->max_vertices, _SGL_DEFAULT_MAX_VERTICES);
    res.max_commands = _sgl_def(desc->max_commands, _SGL_DEFAULT_MAX_COMMANDS);
    res.context_pool_size = _sgl_def(desc->context_pool_size, _SGL_DEFAULT_CONTEXT_POOL_SIZE);
    res.pipeline_pool_size = _sgl_def(desc->pipeline_pool_size, _SGL_DEFAULT_PIPELINE_POOL_SIZE);
    res.face_winding = _sgl_def(desc->face_winding, SG_FACEWINDING_CCW);
    return res;
}

// create resources which are shared between all contexts
static void _sgl_setup_common(void) {
    sg_push_debug_group("sokol-gl");

    uint32_t pixels[64];
    for (int i = 0; i < 64; i++) {
        pixels[i] = 0xFFFFFFFF;
    }
    sg_image_desc img_desc;
    _sgl_clear(&img_desc, sizeof(img_desc));
    img_desc.type = SG_IMAGETYPE_2D;
    img_desc.width = 8;
    img_desc.height = 8;
    img_desc.num_mipmaps = 1;
    img_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
    img_desc.data.subimage[0][0] = SG_RANGE(pixels);
    img_desc.label = "sgl-default-texture";
    _sgl.def_img = sg_make_image(&img_desc);
    SOKOL_ASSERT(SG_INVALID_ID != _sgl.def_img.id);

    sg_sampler_desc smp_desc;
    _sgl_clear(&smp_desc, sizeof(smp_desc));
    smp_desc.min_filter = SG_FILTER_NEAREST;
    smp_desc.mag_filter = SG_FILTER_NEAREST;
    _sgl.def_smp = sg_make_sampler(&smp_desc);
    SOKOL_ASSERT(SG_INVALID_ID != _sgl.def_smp.id);

    // one shader for all contexts
    sg_shader_desc shd_desc;
    _sgl_clear(&shd_desc, sizeof(shd_desc));
    shd_desc.attrs[0].name = "position";
    shd_desc.attrs[1].name = "texcoord0";
    shd_desc.attrs[2].name = "color0";
    shd_desc.attrs[3].name = "psize";
    shd_desc.attrs[0].sem_name = "TEXCOORD";
    shd_desc.attrs[0].sem_index = 0;
    shd_desc.attrs[1].sem_name = "TEXCOORD";
    shd_desc.attrs[1].sem_index = 1;
    shd_desc.attrs[2].sem_name = "TEXCOORD";
    shd_desc.attrs[2].sem_index = 2;
    shd_desc.attrs[3].sem_name = "TEXCOORD";
    shd_desc.attrs[3].sem_index = 3;
    sg_shader_uniform_block_desc* ub = &shd_desc.vs.uniform_blocks[0];
    ub->size = sizeof(_sgl_uniform_t);
    ub->uniforms[0].name = "vs_params";
    ub->uniforms[0].type = SG_UNIFORMTYPE_FLOAT4;
    ub->uniforms[0].array_count = 8;
    shd_desc.fs.images[0].used = true;
    shd_desc.fs.images[0].image_type = SG_IMAGETYPE_2D;
    shd_desc.fs.images[0].sample_type = SG_IMAGESAMPLETYPE_FLOAT;
    shd_desc.fs.samplers[0].used = true;
    shd_desc.fs.samplers[0].sampler_type = SG_SAMPLERTYPE_FILTERING;
    shd_desc.fs.image_sampler_pairs[0].used = true;
    shd_desc.fs.image_sampler_pairs[0].image_slot = 0;
    shd_desc.fs.image_sampler_pairs[0].sampler_slot = 0;
    shd_desc.fs.image_sampler_pairs[0].glsl_name = "tex_smp";
    shd_desc.label = "sgl-shader";
    #if defined(SOKOL_GLCORE33)
        shd_desc.vs.source = _sgl_vs_source_glsl330;
        shd_desc.fs.source = _sgl_fs_source_glsl330;
    #elif defined(SOKOL_GLES3)
        shd_desc.vs.source = _sgl_vs_source_glsl300es;
        shd_desc.fs.source = _sgl_fs_source_glsl300es;
    #elif defined(SOKOL_METAL)
        shd_desc.vs.entry = "main0";
        shd_desc.fs.entry = "main0";
        switch (sg_query_backend()) {
            case SG_BACKEND_METAL_MACOS:
                shd_desc.vs.bytecode = SG_RANGE(_sgl_vs_bytecode_metal_macos);
                shd_desc.fs.bytecode = SG_RANGE(_sgl_fs_bytecode_metal_macos);
                break;
            case SG_BACKEND_METAL_IOS:
                shd_desc.vs.bytecode = SG_RANGE(_sgl_vs_bytecode_metal_ios);
                shd_desc.fs.bytecode = SG_RANGE(_sgl_fs_bytecode_metal_ios);
                break;
            default:
                shd_desc.vs.source = _sgl_vs_source_metal_sim;
                shd_desc.fs.source = _sgl_fs_source_metal_sim;
                break;
        }
    #elif defined(SOKOL_D3D11)
        shd_desc.vs.bytecode = SG_RANGE(_sgl_vs_bytecode_hlsl4);
        shd_desc.fs.bytecode = SG_RANGE(_sgl_fs_bytecode_hlsl4);
    #elif defined(SOKOL_WGPU)
        shd_desc.vs.source = _sgl_vs_source_wgsl;
        shd_desc.fs.source = _sgl_fs_source_wgsl;
    #else
        shd_desc.vs.source = _sgl_vs_source_dummy;
        shd_desc.fs.source = _sgl_fs_source_dummy;
    #endif
    _sgl.shd = sg_make_shader(&shd_desc);
    SOKOL_ASSERT(SG_INVALID_ID != _sgl.shd.id);
    sg_pop_debug_group();
}

// discard resources which are shared between all contexts
static void _sgl_discard_common(void) {
    sg_push_debug_group("sokol-gl");
    sg_destroy_image(_sgl.def_img);
    sg_destroy_sampler(_sgl.def_smp);
    sg_destroy_shader(_sgl.shd);
    sg_pop_debug_group();
}

static bool _sgl_is_default_context(sgl_context ctx_id) {
    return ctx_id.id == SGL_DEFAULT_CONTEXT.id;
}

static void _sgl_draw(_sgl_context_t* ctx, int layer_id) {
    SOKOL_ASSERT(ctx);
    if ((ctx->error == SGL_NO_ERROR) && (ctx->vertices.next > 0) && (ctx->commands.next > 0)) {
        sg_push_debug_group("sokol-gl");

        uint32_t cur_pip_id = SG_INVALID_ID;
        uint32_t cur_img_id = SG_INVALID_ID;
        uint32_t cur_smp_id = SG_INVALID_ID;
        int cur_uniform_index = -1;

        if (ctx->update_frame_id != ctx->frame_id) {
            ctx->update_frame_id = ctx->frame_id;
            const sg_range range = { ctx->vertices.ptr, (size_t)ctx->vertices.next * sizeof(_sgl_vertex_t) };
            sg_update_buffer(ctx->vbuf, &range);
        }

        for (int i = 0; i < ctx->commands.next; i++) {
            const _sgl_command_t* cmd = &ctx->commands.ptr[i];
            if (cmd->layer_id != layer_id) {
                continue;
            }
            switch (cmd->cmd) {
                case SGL_COMMAND_VIEWPORT:
                    {
                        const _sgl_viewport_args_t* args = &cmd->args.viewport;
                        sg_apply_viewport(args->x, args->y, args->w, args->h, args->origin_top_left);
                    }
                    break;
                case SGL_COMMAND_SCISSOR_RECT:
                    {
                        const _sgl_scissor_rect_args_t* args = &cmd->args.scissor_rect;
                        sg_apply_scissor_rect(args->x, args->y, args->w, args->h, args->origin_top_left);
                    }
                    break;
                case SGL_COMMAND_DRAW:
                    {
                        const _sgl_draw_args_t* args = &cmd->args.draw;
                        if (args->pip.id != cur_pip_id) {
                            sg_apply_pipeline(args->pip);
                            cur_pip_id = args->pip.id;
                            /* when pipeline changes, also need to re-apply uniforms and bindings */
                            cur_img_id = SG_INVALID_ID;
                            cur_smp_id = SG_INVALID_ID;
                            cur_uniform_index = -1;
                        }
                        if ((cur_img_id != args->img.id) || (cur_smp_id != args->smp.id)) {
                            ctx->bind.fs.images[0] = args->img;
                            ctx->bind.fs.samplers[0] = args->smp;
                            sg_apply_bindings(&ctx->bind);
                            cur_img_id = args->img.id;
                            cur_smp_id = args->smp.id;
                        }
                        if (cur_uniform_index != args->uniform_index) {
                            const sg_range ub_range = { &ctx->uniforms.ptr[args->uniform_index], sizeof(_sgl_uniform_t) };
                            sg_apply_uniforms(SG_SHADERSTAGE_VS, 0, &ub_range);
                            cur_uniform_index = args->uniform_index;
                        }
                        /* FIXME: what if number of vertices doesn't match the primitive type? */
                        if (args->num_vertices > 0) {
                            sg_draw(args->base_vertex, args->num_vertices, 1);
                        }
                    }
                    break;
            }
        }
        sg_pop_debug_group();
    }
}

static sgl_context_desc_t _sgl_as_context_desc(const sgl_desc_t* desc) {
    sgl_context_desc_t ctx_desc;
    _sgl_clear(&ctx_desc, sizeof(ctx_desc));
    ctx_desc.max_vertices = desc->max_vertices;
    ctx_desc.max_commands = desc->max_commands;
    ctx_desc.color_format = desc->color_format;
    ctx_desc.depth_format = desc->depth_format;
    ctx_desc.sample_count = desc->sample_count;
    return ctx_desc;
}

// ██████  ██    ██ ██████  ██      ██  ██████
// ██   ██ ██    ██ ██   ██ ██      ██ ██
// ██████  ██    ██ ██████  ██      ██ ██
// ██      ██    ██ ██   ██ ██      ██ ██
// ██       ██████  ██████  ███████ ██  ██████
//
// >>public
SOKOL_API_IMPL void sgl_setup(const sgl_desc_t* desc) {
    SOKOL_ASSERT(desc);
    _sgl_clear(&_sgl, sizeof(_sgl));
    _sgl.init_cookie = _SGL_INIT_COOKIE;
    _sgl.desc = _sgl_desc_defaults(desc);
    _sgl_setup_pipeline_pool(_sgl.desc.pipeline_pool_size);
    _sgl_setup_context_pool(_sgl.desc.context_pool_size);
    _sgl_setup_common();
    const sgl_context_desc_t ctx_desc = _sgl_as_context_desc(&_sgl.desc);
    _sgl.def_ctx_id = sgl_make_context(&ctx_desc);
    SOKOL_ASSERT(SGL_DEFAULT_CONTEXT.id == _sgl.def_ctx_id.id);
    sgl_set_context(_sgl.def_ctx_id);
}

SOKOL_API_IMPL void sgl_shutdown(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    // contexts own a pipeline, so destroy contexts before pipelines
    for (int i = 0; i < _sgl.context_pool.pool.size; i++) {
        _sgl_context_t* ctx = &_sgl.context_pool.contexts[i];
        _sgl_destroy_context(_sgl_make_ctx_id(ctx->slot.id));
    }
    for (int i = 0; i < _sgl.pip_pool.pool.size; i++) {
        _sgl_pipeline_t* pip = &_sgl.pip_pool.pips[i];
        _sgl_destroy_pipeline(_sgl_make_pip_id(pip->slot.id));
    }
    _sgl_discard_context_pool();
    _sgl_discard_pipeline_pool();
    _sgl_discard_common();
    _sgl.init_cookie = 0;
}

SOKOL_API_IMPL sgl_error_t sgl_error(void) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        return ctx->error;
    } else {
        return SGL_ERROR_NO_CONTEXT;
    }
}

SOKOL_API_IMPL sgl_error_t sgl_context_error(sgl_context ctx_id) {
    const _sgl_context_t* ctx = _sgl_lookup_context(ctx_id.id);
    if (ctx) {
        return ctx->error;
    } else {
        return SGL_ERROR_NO_CONTEXT;
    }
}

SOKOL_API_IMPL float sgl_rad(float deg) {
    return (deg * (float)M_PI) / 180.0f;
}

SOKOL_API_IMPL float sgl_deg(float rad) {
    return (rad * 180.0f) / (float)M_PI;
}

SOKOL_API_IMPL sgl_context sgl_make_context(const sgl_context_desc_t* desc) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    return _sgl_make_context(desc);
}

SOKOL_API_IMPL void sgl_destroy_context(sgl_context ctx_id) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    if (_sgl_is_default_context(ctx_id)) {
        _SGL_WARN(CANNOT_DESTROY_DEFAULT_CONTEXT);
        return;
    }
    _sgl_destroy_context(ctx_id);
    // re-validate the current context pointer (this will return a nullptr
    // if we just destroyed the current context)
    _sgl.cur_ctx = _sgl_lookup_context(_sgl.cur_ctx_id.id);
}

SOKOL_API_IMPL void sgl_set_context(sgl_context ctx_id) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    if (_sgl_is_default_context(ctx_id)) {
        _sgl.cur_ctx_id = _sgl.def_ctx_id;
    } else {
        _sgl.cur_ctx_id = ctx_id;
    }
    // this will return null if the handle isn't valid
    _sgl.cur_ctx = _sgl_lookup_context(_sgl.cur_ctx_id.id);
}

SOKOL_API_IMPL sgl_context sgl_get_context(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    return _sgl.cur_ctx_id;
}

SOKOL_API_IMPL sgl_context sgl_default_context(void) {
    return SGL_DEFAULT_CONTEXT;
}

SOKOL_API_IMPL sgl_pipeline sgl_make_pipeline(const sg_pipeline_desc* desc) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        return _sgl_make_pipeline(desc, &ctx->desc);
    } else {
        return _sgl_make_pip_id(SG_INVALID_ID);
    }
}

SOKOL_API_IMPL sgl_pipeline sgl_context_make_pipeline(sgl_context ctx_id, const sg_pipeline_desc* desc) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    const _sgl_context_t* ctx = _sgl_lookup_context(ctx_id.id);
    if (ctx) {
        return _sgl_make_pipeline(desc, &ctx->desc);
    } else {
        return _sgl_make_pip_id(SG_INVALID_ID);
    }
}

SOKOL_API_IMPL void sgl_destroy_pipeline(sgl_pipeline pip_id) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_destroy_pipeline(pip_id);
}

SOKOL_API_IMPL void sgl_load_pipeline(sgl_pipeline pip_id) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT((ctx->pip_tos >= 0) && (ctx->pip_tos < _SGL_MAX_STACK_DEPTH));
    ctx->pip_stack[ctx->pip_tos] = pip_id;
}

SOKOL_API_IMPL void sgl_load_default_pipeline(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT((ctx->pip_tos >= 0) && (ctx->pip_tos < _SGL_MAX_STACK_DEPTH));
    ctx->pip_stack[ctx->pip_tos] = ctx->def_pip;
}

SOKOL_API_IMPL void sgl_push_pipeline(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    if (ctx->pip_tos < (_SGL_MAX_STACK_DEPTH - 1)) {
        ctx->pip_tos++;
        ctx->pip_stack[ctx->pip_tos] = ctx->pip_stack[ctx->pip_tos-1];
    } else {
        ctx->error = SGL_ERROR_STACK_OVERFLOW;
    }
}

SOKOL_API_IMPL void sgl_pop_pipeline(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    if (ctx->pip_tos > 0) {
        ctx->pip_tos--;
    } else {
        ctx->error = SGL_ERROR_STACK_UNDERFLOW;
    }
}

SOKOL_API_IMPL void sgl_defaults(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    ctx->u = 0.0f; ctx->v = 0.0f;
    ctx->rgba = 0xFFFFFFFF;
    ctx->point_size = 1.0f;
    ctx->texturing_enabled = false;
    ctx->cur_img = _sgl.def_img;
    ctx->cur_smp = _sgl.def_smp;
    sgl_load_default_pipeline();
    _sgl_identity(_sgl_matrix_texture(ctx));
    _sgl_identity(_sgl_matrix_modelview(ctx));
    _sgl_identity(_sgl_matrix_projection(ctx));
    ctx->cur_matrix_mode = SGL_MATRIXMODE_MODELVIEW;
    ctx->matrix_dirty = true;
}

SOKOL_API_IMPL void sgl_layer(int layer_id) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    ctx->layer_id = layer_id;
}

SOKOL_API_IMPL void sgl_viewport(int x, int y, int w, int h, bool origin_top_left) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    _sgl_command_t* cmd = _sgl_next_command(ctx);
    if (cmd) {
        cmd->cmd = SGL_COMMAND_VIEWPORT;
        cmd->layer_id = ctx->layer_id;
        cmd->args.viewport.x = x;
        cmd->args.viewport.y = y;
        cmd->args.viewport.w = w;
        cmd->args.viewport.h = h;
        cmd->args.viewport.origin_top_left = origin_top_left;
    }
}

SOKOL_API_IMPL void sgl_viewportf(float x, float y, float w, float h, bool origin_top_left) {
    sgl_viewport((int)x, (int)y, (int)w, (int)h, origin_top_left);
}

SOKOL_API_IMPL void sgl_scissor_rect(int x, int y, int w, int h, bool origin_top_left) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    _sgl_command_t* cmd = _sgl_next_command(ctx);
    if (cmd) {
        cmd->cmd = SGL_COMMAND_SCISSOR_RECT;
        cmd->layer_id = ctx->layer_id;
        cmd->args.scissor_rect.x = x;
        cmd->args.scissor_rect.y = y;
        cmd->args.scissor_rect.w = w;
        cmd->args.scissor_rect.h = h;
        cmd->args.scissor_rect.origin_top_left = origin_top_left;
    }
}

SOKOL_API_IMPL void sgl_scissor_rectf(float x, float y, float w, float h, bool origin_top_left) {
    sgl_scissor_rect((int)x, (int)y, (int)w, (int)h, origin_top_left);
}

SOKOL_API_IMPL void sgl_enable_texture(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    ctx->texturing_enabled = true;
}

SOKOL_API_IMPL void sgl_disable_texture(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    ctx->texturing_enabled = false;
}

SOKOL_API_IMPL void sgl_texture(sg_image img, sg_sampler smp) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    if (SG_INVALID_ID != img.id) {
        ctx->cur_img = img;
    } else {
        ctx->cur_img = _sgl.def_img;
    }
    if (SG_INVALID_ID != smp.id) {
        ctx->cur_smp = smp;
    } else {
        ctx->cur_smp = _sgl.def_smp;
    }
}

SOKOL_API_IMPL void sgl_begin_points(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    _sgl_begin(ctx, SGL_PRIMITIVETYPE_POINTS);
}

SOKOL_API_IMPL void sgl_begin_lines(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    _sgl_begin(ctx, SGL_PRIMITIVETYPE_LINES);
}

SOKOL_API_IMPL void sgl_begin_line_strip(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    _sgl_begin(ctx, SGL_PRIMITIVETYPE_LINE_STRIP);
}

SOKOL_API_IMPL void sgl_begin_triangles(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    _sgl_begin(ctx, SGL_PRIMITIVETYPE_TRIANGLES);
}

SOKOL_API_IMPL void sgl_begin_triangle_strip(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    _sgl_begin(ctx, SGL_PRIMITIVETYPE_TRIANGLE_STRIP);
}

SOKOL_API_IMPL void sgl_begin_quads(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(!ctx->in_begin);
    _sgl_begin(ctx, SGL_PRIMITIVETYPE_QUADS);
}

SOKOL_API_IMPL void sgl_end(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT(ctx->in_begin);
    SOKOL_ASSERT(ctx->vertices.next >= ctx->base_vertex);
    ctx->in_begin = false;
    bool matrix_dirty = ctx->matrix_dirty;
    if (matrix_dirty) {
        ctx->matrix_dirty = false;
        _sgl_uniform_t* uni = _sgl_next_uniform(ctx);
        if (uni) {
            _sgl_matmul4(&uni->mvp, _sgl_matrix_projection(ctx), _sgl_matrix_modelview(ctx));
            uni->tm = *_sgl_matrix_texture(ctx);
        }
    }
    // check if command can be merged with current command
    sg_pipeline pip = _sgl_get_pipeline(ctx->pip_stack[ctx->pip_tos], ctx->cur_prim_type);
    sg_image img = ctx->texturing_enabled ? ctx->cur_img : _sgl.def_img;
    sg_sampler smp = ctx->texturing_enabled ? ctx->cur_smp : _sgl.def_smp;
    _sgl_command_t* cur_cmd = _sgl_cur_command(ctx);
    bool merge_cmd = false;
    if (cur_cmd) {
        if ((cur_cmd->cmd == SGL_COMMAND_DRAW) &&
            (cur_cmd->layer_id == ctx->layer_id) &&
            (ctx->cur_prim_type != SGL_PRIMITIVETYPE_LINE_STRIP) &&
            (ctx->cur_prim_type != SGL_PRIMITIVETYPE_TRIANGLE_STRIP) &&
            !matrix_dirty &&
            (cur_cmd->args.draw.img.id == img.id) &&
            (cur_cmd->args.draw.smp.id == smp.id) &&
            (cur_cmd->args.draw.pip.id == pip.id))
        {
            merge_cmd = true;
        }
    }
    if (merge_cmd) {
        // draw command can be merged with the previous command
        cur_cmd->args.draw.num_vertices += ctx->vertices.next - ctx->base_vertex;
    } else {
        // append a new draw command
        _sgl_command_t* cmd = _sgl_next_command(ctx);
        if (cmd) {
            SOKOL_ASSERT(ctx->uniforms.next > 0);
            cmd->cmd = SGL_COMMAND_DRAW;
            cmd->layer_id = ctx->layer_id;
            cmd->args.draw.img = img;
            cmd->args.draw.smp = smp;
            cmd->args.draw.pip = _sgl_get_pipeline(ctx->pip_stack[ctx->pip_tos], ctx->cur_prim_type);
            cmd->args.draw.base_vertex = ctx->base_vertex;
            cmd->args.draw.num_vertices = ctx->vertices.next - ctx->base_vertex;
            cmd->args.draw.uniform_index = ctx->uniforms.next - 1;
        }
    }
}

SOKOL_API_IMPL void sgl_point_size(float s) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->point_size = s;
    }
}

SOKOL_API_IMPL void sgl_t2f(float u, float v) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->u = u;
        ctx->v = v;
    }
}

SOKOL_API_IMPL void sgl_c3f(float r, float g, float b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->rgba = _sgl_pack_rgbaf(r, g, b, 1.0f);
    }
}

SOKOL_API_IMPL void sgl_c4f(float r, float g, float b, float a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->rgba = _sgl_pack_rgbaf(r, g, b, a);
    }
}

SOKOL_API_IMPL void sgl_c3b(uint8_t r, uint8_t g, uint8_t b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->rgba = _sgl_pack_rgbab(r, g, b, 255);
    }
}

SOKOL_API_IMPL void sgl_c4b(uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->rgba = _sgl_pack_rgbab(r, g, b, a);
    }
}

SOKOL_API_IMPL void sgl_c1i(uint32_t rgba) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->rgba = rgba;
    }
}

SOKOL_API_IMPL void sgl_v2f(float x, float y) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, ctx->u, ctx->v, ctx->rgba);
    }
}

SOKOL_API_IMPL void sgl_v3f(float x, float y, float z) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, ctx->u, ctx->v, ctx->rgba);
    }
}

SOKOL_API_IMPL void sgl_v2f_t2f(float x, float y, float u, float v) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, u, v, ctx->rgba);
    }
}

SOKOL_API_IMPL void sgl_v3f_t2f(float x, float y, float z, float u, float v) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, u, v, ctx->rgba);
    }
}

SOKOL_API_IMPL void sgl_v2f_c3f(float x, float y, float r, float g, float b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, ctx->u, ctx->v, _sgl_pack_rgbaf(r, g, b, 1.0f));
    }
}

SOKOL_API_IMPL void sgl_v2f_c3b(float x, float y, uint8_t r, uint8_t g, uint8_t b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, ctx->u, ctx->v, _sgl_pack_rgbab(r, g, b, 255));
    }
}

SOKOL_API_IMPL void sgl_v2f_c4f(float x, float y, float r, float g, float b, float a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, ctx->u, ctx->v, _sgl_pack_rgbaf(r, g, b, a));
    }
}

SOKOL_API_IMPL void sgl_v2f_c4b(float x, float y, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, ctx->u, ctx->v, _sgl_pack_rgbab(r, g, b, a));
    }
}

SOKOL_API_IMPL void sgl_v2f_c1i(float x, float y, uint32_t rgba) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, ctx->u, ctx->v, rgba);
    }
}

SOKOL_API_IMPL void sgl_v3f_c3f(float x, float y, float z, float r, float g, float b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, ctx->u, ctx->v, _sgl_pack_rgbaf(r, g, b, 1.0f));
    }
}

SOKOL_API_IMPL void sgl_v3f_c3b(float x, float y, float z, uint8_t r, uint8_t g, uint8_t b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, ctx->u, ctx->v, _sgl_pack_rgbab(r, g, b, 255));
    }
}

SOKOL_API_IMPL void sgl_v3f_c4f(float x, float y, float z, float r, float g, float b, float a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, ctx->u, ctx->v, _sgl_pack_rgbaf(r, g, b, a));
    }
}

SOKOL_API_IMPL void sgl_v3f_c4b(float x, float y, float z, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, ctx->u, ctx->v, _sgl_pack_rgbab(r, g, b, a));
    }
}

SOKOL_API_IMPL void sgl_v3f_c1i(float x, float y, float z, uint32_t rgba) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, ctx->u, ctx->v, rgba);
    }
}

SOKOL_API_IMPL void sgl_v2f_t2f_c3f(float x, float y, float u, float v, float r, float g, float b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, u, v, _sgl_pack_rgbaf(r, g, b, 1.0f));
    }
}

SOKOL_API_IMPL void sgl_v2f_t2f_c3b(float x, float y, float u, float v, uint8_t r, uint8_t g, uint8_t b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, u, v, _sgl_pack_rgbab(r, g, b, 255));
    }
}

SOKOL_API_IMPL void sgl_v2f_t2f_c4f(float x, float y, float u, float v, float r, float g, float b, float a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, u, v, _sgl_pack_rgbaf(r, g, b, a));
    }
}

SOKOL_API_IMPL void sgl_v2f_t2f_c4b(float x, float y, float u, float v, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, u, v, _sgl_pack_rgbab(r, g, b, a));
    }
}

SOKOL_API_IMPL void sgl_v2f_t2f_c1i(float x, float y, float u, float v, uint32_t rgba) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, 0.0f, u, v, rgba);
    }
}

SOKOL_API_IMPL void sgl_v3f_t2f_c3f(float x, float y, float z, float u, float v, float r, float g, float b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, u, v, _sgl_pack_rgbaf(r, g, b, 1.0f));
    }
}

SOKOL_API_IMPL void sgl_v3f_t2f_c3b(float x, float y, float z, float u, float v, uint8_t r, uint8_t g, uint8_t b) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, u, v, _sgl_pack_rgbab(r, g, b, 255));
    }
}

SOKOL_API_IMPL void sgl_v3f_t2f_c4f(float x, float y, float z, float u, float v, float r, float g, float b, float a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, u, v, _sgl_pack_rgbaf(r, g, b, a));
    }
}

SOKOL_API_IMPL void sgl_v3f_t2f_c4b(float x, float y, float z, float u, float v, uint8_t r, uint8_t g, uint8_t b, uint8_t a) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx, x, y, z, u, v, _sgl_pack_rgbab(r, g, b, a));
    }
}

SOKOL_API_IMPL void sgl_v3f_t2f_c1i(float x, float y, float z, float u, float v, uint32_t rgba) {
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_vtx(ctx,x, y, z, u, v, rgba);
    }
}

SOKOL_API_IMPL void sgl_matrix_mode_modelview(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->cur_matrix_mode = SGL_MATRIXMODE_MODELVIEW;
    }
}

SOKOL_API_IMPL void sgl_matrix_mode_projection(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->cur_matrix_mode = SGL_MATRIXMODE_PROJECTION;
    }
}

SOKOL_API_IMPL void sgl_matrix_mode_texture(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        ctx->cur_matrix_mode = SGL_MATRIXMODE_TEXTURE;
    }
}

SOKOL_API_IMPL void sgl_load_identity(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_identity(_sgl_matrix(ctx));
}

SOKOL_API_IMPL void sgl_load_matrix(const float m[16]) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    memcpy(&_sgl_matrix(ctx)->v[0][0], &m[0], 64);
}

SOKOL_API_IMPL void sgl_load_transpose_matrix(const float m[16]) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_transpose(_sgl_matrix(ctx), (const _sgl_matrix_t*) &m[0]);
}

SOKOL_API_IMPL void sgl_mult_matrix(const float m[16]) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    const _sgl_matrix_t* m0  = (const _sgl_matrix_t*) &m[0];
    _sgl_mul(_sgl_matrix(ctx), m0);
}

SOKOL_API_IMPL void sgl_mult_transpose_matrix(const float m[16]) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_matrix_t m0;
    _sgl_transpose(&m0, (const _sgl_matrix_t*) &m[0]);
    _sgl_mul(_sgl_matrix(ctx), &m0);
}

SOKOL_API_IMPL void sgl_rotate(float angle_rad, float x, float y, float z) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_rotate(_sgl_matrix(ctx), angle_rad, x, y, z);
}

SOKOL_API_IMPL void sgl_scale(float x, float y, float z) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_scale(_sgl_matrix(ctx), x, y, z);
}

SOKOL_API_IMPL void sgl_translate(float x, float y, float z) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_translate(_sgl_matrix(ctx), x, y, z);
}

SOKOL_API_IMPL void sgl_frustum(float l, float r, float b, float t, float n, float f) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_frustum(_sgl_matrix(ctx), l, r, b, t, n, f);
}

SOKOL_API_IMPL void sgl_ortho(float l, float r, float b, float t, float n, float f) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_ortho(_sgl_matrix(ctx), l, r, b, t, n, f);
}

SOKOL_API_IMPL void sgl_perspective(float fov_y, float aspect, float z_near, float z_far) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_perspective(_sgl_matrix(ctx), fov_y, aspect, z_near, z_far);
}

SOKOL_API_IMPL void sgl_lookat(float eye_x, float eye_y, float eye_z, float center_x, float center_y, float center_z, float up_x, float up_y, float up_z) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    ctx->matrix_dirty = true;
    _sgl_lookat(_sgl_matrix(ctx), eye_x, eye_y, eye_z, center_x, center_y, center_z, up_x, up_y, up_z);
}

SOKOL_GL_API_DECL void sgl_push_matrix(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT((ctx->cur_matrix_mode >= 0) && (ctx->cur_matrix_mode < SGL_NUM_MATRIXMODES));
    ctx->matrix_dirty = true;
    if (ctx->matrix_tos[ctx->cur_matrix_mode] < (_SGL_MAX_STACK_DEPTH - 1)) {
        const _sgl_matrix_t* src = _sgl_matrix(ctx);
        ctx->matrix_tos[ctx->cur_matrix_mode]++;
        _sgl_matrix_t* dst = _sgl_matrix(ctx);
        *dst = *src;
    } else {
        ctx->error = SGL_ERROR_STACK_OVERFLOW;
    }
}

SOKOL_GL_API_DECL void sgl_pop_matrix(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (!ctx) {
        return;
    }
    SOKOL_ASSERT((ctx->cur_matrix_mode >= 0) && (ctx->cur_matrix_mode < SGL_NUM_MATRIXMODES));
    ctx->matrix_dirty = true;
    if (ctx->matrix_tos[ctx->cur_matrix_mode] > 0) {
        ctx->matrix_tos[ctx->cur_matrix_mode]--;
    } else {
        ctx->error = SGL_ERROR_STACK_UNDERFLOW;
    }
}

SOKOL_API_IMPL void sgl_draw(void) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_draw(ctx, 0);
    }
}

SOKOL_API_IMPL void sgl_draw_layer(int layer_id) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl.cur_ctx;
    if (ctx) {
        _sgl_draw(ctx, layer_id);
    }
}

SOKOL_API_IMPL void sgl_context_draw(sgl_context ctx_id) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl_lookup_context(ctx_id.id);
    if (ctx) {
        _sgl_draw(ctx, 0);
    }
}

SOKOL_API_IMPL void sgl_context_draw_layer(sgl_context ctx_id, int layer_id) {
    SOKOL_ASSERT(_SGL_INIT_COOKIE == _sgl.init_cookie);
    _sgl_context_t* ctx = _sgl_lookup_context(ctx_id.id);
    if (ctx) {
        _sgl_draw(ctx, layer_id);
    }
}

#endif /* SOKOL_GL_IMPL */
