examples.gpu-shaders · shader ·

Paint your first pixels

Give each GPU invocation one pixel. Turn its coordinates into color.

complete-programcomputegpuimageshaderyeho

A compute shader is a small program that runs across data on the GPU. Here the data is an image. Yeho translates the [gpu] compute body to the selected provider; on Mac, that provider is Metal.

[gpu] compute Paint(buffer of int pixels, int width, int height, float time)

Status: native-metal-example

01 / Paint your first pixels

Give each GPU invocation one pixel. Turn its coordinates into color.

gpu · shader · image · type checked

[gpu]
compute Paint(buffer of int pixels, int width, int height, float time)
{
    int index = compute.index
    if index >= pixels.count { return }
    int row = index / width
    int column = index - row * width
    float u = Math.IntToFloat(column) / Math.IntToFloat(width - 1)
    float v = Math.IntToFloat(row) / Math.IntToFloat(height - 1)
    float r = 0.08 + u * 0.8
    float g = 0.08 + v * 0.8
    float b = 0.3 + (1.0 - u) * 0.6
    int red = Math.RoundToInt(Math.ClampFloat(r, 0.0, 1.0) * 255.0)
    int green = Math.RoundToInt(Math.ClampFloat(g, 0.0, 1.0) * 255.0)
    int blue = Math.RoundToInt(Math.ClampFloat(b, 0.0, 1.0) * 255.0)
    pixels[index] = red * 65536 + green * 256 + blue
}

// CPU: allocate an image and submit one GPU invocation per pixel.
int width = 128
int height = 128
buffer of int pixels
pixels.Resize(width * height)
computeTask job = dispatch Paint(pixels, width, height, 0.0)
wait job
if job.failed { Console.Error(job.error.message) Process.Exit(1) }

// CPU: save the completed RGB pixels as a portable PPM image.
text image = "P3\n" + Text.From(width) + " " + Text.From(height) + "\n255\n"
for row from 0 < height
{
    text line = ""
    for column from 0 < width
    {
        int pixel = pixels[row * width + column]
        int red = pixel / 65536
        int green = (pixel - red * 65536) / 256
        int blue = pixel - red * 65536 - green * 256
        line = line + Text.From(red) + " " + Text.From(green) + " " + Text.From(blue) + " "
    }
    image = image + line + "\n"
}
File.WriteText("shader.ppm", image)
Console.Log("Wrote shader.ppm")
project.mech
manifestVersion = "2"
package = "learning.shaders.gpu_gradient"
version = "0.1.0"
languageEdition = "yeho-core-2026.1"

[app]
kind = "headless"
Expected output
Wrote shader.ppm
Notes and source

Swap u and v in the red and green expressions. Then set b to 0.0. Rebuild and compare shader.ppm.

The dedicated shader verifier executes this program on Metal and compares every output channel with a separate CPU reference. Evidence: https://demonhunterlabs.com/learning/gpu-shaders/verification.json

The program writes shader.ppm in its current directory. Native image generation is separate from presenting frames in a game window.

demonhunterlabs/app/lib/yeho-gpu-shaders.ts