sugarloaf 0.4.4

Sugarloaf is Rio rendering engine, designed to be multiplatform. It is based on WebGPU, Rust library for Desktops and WebAssembly for Web (JavaScript). This project is created and maintained for Rio terminal purposes but feel free to use it.
#version 450

// Image fragment shader, ported from `image_fs_main` in
// `sugarloaf/src/renderer/image.metal`. The texture is
// `R8G8B8A8_SRGB`, so the HW sRGB-decodes bytes on sample —
// bilinear filtering happens in *linear* light, matching Metal's
// `RGBA8Unorm_sRGB` behaviour. We then `linear_to_srgb` back to
// gamma encoding for the framebuffer (plain `B8G8R8A8_UNORM`,
// gamma-space alpha blending — same as the rest of sugarloaf).

layout(set = 0, binding = 0, std140) uniform Globals {
    mat4 transform;
    uint input_colorspace;
    uint _pad0;
    uint _pad1;
    uint _pad2;
} globals;

layout(set = 1, binding = 0) uniform sampler2D image_texture;

layout(location = 0) in vec2 in_tex_coord;

layout(location = 0) out vec4 out_color;

vec3 linear_to_srgb(vec3 c) {
    vec3 lo = c * 12.92;
    vec3 hi = pow(c, vec3(1.0 / 2.4)) * 1.055 - 0.055;
    return mix(lo, hi, greaterThan(c, vec3(0.0031308)));
}

vec3 rec2020_to_p3(vec3 linear_r2020) {
    return vec3(
        dot(linear_r2020, vec3( 1.34357825, -0.28217967, -0.06139858)),
        dot(linear_r2020, vec3(-0.06529745,  1.08782226, -0.02252481)),
        dot(linear_r2020, vec3( 0.00282179, -0.02598807,  1.02316628))
    );
}

void main() {
    // R8G8B8A8_SRGB: HW decodes the byte → linear before handing it
    // to the shader. Alpha is linear by convention regardless of
    // format. After optional Rec.2020 → P3 gamut conversion, encode
    // back to gamma-sRGB for the framebuffer.
    vec4 rgba = texture(image_texture, in_tex_coord);
    vec3 lin = rgba.rgb;
    if (globals.input_colorspace == 2u) {
        lin = rec2020_to_p3(lin);
    }
    vec3 enc = linear_to_srgb(lin);
    // Premultiply alpha — pipeline blend factors are ONE / ONE_MINUS_SRC_ALPHA.
    out_color = vec4(enc * rgba.a, rgba.a);
}