User Tools

Site Tools


The new 'GPU FFI' lets you write vertex and fragment shaders to draw things.

Here is a very basic shader that you can just paste as a virtual program (or print). It will color a triangle underneath itself green-blue.

Wish the GPU compiles pipeline "$this's triangle" {
    {vec2 p0 vec2 p1 vec2 p2} {
        vec2 vertices[4] = vec2[4](p0, p1, p2, p0);
        return vertices[gl_VertexIndex];
    } {
        return vec4(0, 0.1, 0.1, 1);

Wish $this is outlined blue
When $this has region /r/ {
    set r' [region move $r down 100%]
    Wish the GPU draws pipeline "$this's triangle" with arguments [list {*}[lrange [region vertices ${r'}] 0 2]]

The pipeline source object that you pass after Wish the GPU compiles pipeline NAME has the form {ALL-ARGS VERT-SHADER [FRAG-ARGS] FRAG-SHADER}.

The first element of the pipeline source object, {vec2 p0 vec2 p1 vec2 p2}, is a list of overall arguments for both shaders. These are accessible from both the vertex and fragment shader. You pass these in at draw time (they're push constants – sort of like uniforms in GL, but limited in total size to 128 bytes). (The exception is fn-type arguments, which aren't actually passed in; they're meant to be names of Gpu::fn functions you've already made, which are looked up at call time from the surrounding Tcl environment and inlined into the shader. They just fall out and don't map to arguments in Gpu::draw)

The second element in the pipeline is the source code of the main function of a vertex shader. It should return a vec2 vertex of a quad in Vulkan triangle-strip vertex order (should be topleft, topright, bottomleft, bottomright, like a Z, not counterclockwise) based on gl_VertexIndex (it will be called with vertex index 0, 1, 2, 3). The returned vertex should be in screen coordinates, not in [0, 1]. You can access the builtin vec2 _resolution to get resolution of the screen. (In practice, so far we mostly use the vertex shader for clipping so we don't have to touch the whole display on every draw.)

The third (or fourth, if you make fragment shader fn arguments before it) element in the pipeline is the source code of the main function of a fragment shader. You can access vec2 gl_FragCoord to get current pixel coordinates. It should return a vec4 color. You can access any of the overall arguments (including _resolution) from here as well.

You can make sampler2D-type arguments if you want to pass an image in; you can make fn arguments to a fragment shader as third argument. See the implementations of drawing primitives in virtual-programs/display/*.folk for more examples.

TODO: Document internal Gpu:: API

These must be called on the display thread: Gpu::pipeline, Gpu::draw, Gpu::fn

(originally in but pulling here to keep updated)

guides/gpu.txt · Last modified: 2023/11/01 01:02 by osnr

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki