캔버스에 그리기
전체 화면 @fragment 진입점과 이를 그리는 호스트입니다. 호스트는 fs를 가져와 프레임마다 fs(canvas, { frame })를 한 번 부르고, 유니폼에 시간을 넣습니다. 그리는 것은 전체 화면 삼각형 하나입니다. WebGPU가 먼저이고, 없으면 WebGL2, 그다음은 CPU tier입니다. 호스트 코드에는 파이프라인도 버퍼도 바인드 그룹도 없다(규칙 8.24).
실행 tier WebGPUWebGL2CPU tier
이 목록은 컴파일러가 확인합니다. tier(호출이 실행되는 백엔드)는 호스트의 실행 전체가 그 tier 하나만으로 기준값을 낼 때만 목록에 오릅니다. 컴파일러의 저니 게이트가 호스트마다 WebGPU와 WebGL2에서 실행하고, 단위 테스트가 CPU tier에서 실행합니다.
"use typeshade";
/* @example{ "title": "Host: draw into a canvas", "blurb": "A full-screen `@fragment` entry and the host that draws it. The host imports `fs` and calls `fs(canvas, { frame })` once a frame, with the time in the uniform: one full-screen triangle, on WebGPU, then WebGL2, then the CPU tier, with no pipeline, buffer or bind group in the host's code (Rule 8.24).", "renderable": false, "reason": "no entry point"}*/
// What the host sets each frame: the time, and the canvas's size in pixels.class Frame { time: f32; size: vec2;}
declare const frame: uniform<Frame>;
// A full-screen fragment entry reads no builtin but `position`, and writes one colour, so a host// draws it into a canvas with no vertex entry of its own.@fragmentexport function fs(@builtin("position") p: vec4): vec4 { const uv = p.xy / frame.size; const wave = 0.5 + 0.5 * sin(6.2831853 * uv.x + frame.time); return vec4(uv.x, uv.y, wave, 1.);}// Draw a full-screen fragment entry into a canvas (surface §67, Rule 8.24).//// The import is the shader module itself: the Vite plugin (`typeshade/vite`) turns `fs` into a// function that draws one frame. The first draw into a canvas picks its tier: WebGPU, then// WebGL2, then the CPU tier, which paints the frame pixel by pixel.import { fs } from './host-draw.shade.ts';
/** Draw one frame at `time` seconds. The promise resolves when the frame is submitted. */export function draw(canvas: HTMLCanvasElement | OffscreenCanvas, time: number): Promise<void> { return fs(canvas, { frame: { time, size: [canvas.width, canvas.height] } });}
/** Animate `canvas`: a new uniform value each frame. A frame loop need not wait for a draw. */export function animate(canvas: HTMLCanvasElement): void { const frame = (ms: number): void => { void draw(canvas, ms / 1000); requestAnimationFrame(frame); }; requestAnimationFrame(frame);}
/** Draw the frames at `times`, one after another. The canvas then shows the last one. */export async function run( canvas: HTMLCanvasElement | OffscreenCanvas, times: readonly number[] = [0, 0.5, 1.25],): Promise<void> { for (const time of times) await draw(canvas, time);}두 파일 모두 커밋 91c2fe31의 컴파일러에 있는 그대로이며, 예제 디렉터리에서 읽어 왔습니다.