Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1ac00db
docs(brief): add S6 milestone brief
guysenpai May 17, 2026
9f2ba08
docs(brief): confirm specs read for S6
guysenpai May 17, 2026
4b8fc51
docs(brief): activate S6
guysenpai May 17, 2026
c5a5424
feat(ipc): add protocol/messages/framing foundations
guysenpai May 17, 2026
cd3525d
docs(brief): journal — IPC foundations landed
guysenpai May 17, 2026
8ce5c0f
feat(ipc): add transport layer (AF_UNIX + named pipes)
guysenpai May 17, 2026
075118e
feat(ipc): add shared memory layer (POSIX shm_open + Windows CreateFi…
guysenpai May 17, 2026
2403074
feat(ipc): add ShmViewport double-buffer + platform/process API
guysenpai May 17, 2026
e924cf8
docs(brief): journal — shm/viewport/process + platform shim fixes
guysenpai May 17, 2026
ba1af34
test(ipc): skip runtime inline tests, redirect to tests/ipc/
guysenpai May 18, 2026
38acfcc
fix(tests): isolate ipc test hang via per-test timeouts
guysenpai May 18, 2026
df990a9
feat(ipc): add connection/server/client + handshake test
guysenpai May 18, 2026
272fd5b
feat(ipc): editor+runtime stubs, crash_recovery, fuzz, RTT bench
guysenpai May 18, 2026
a2fc352
fix(ipc): tighten shm permissions to 0o600, remove umask hack
guysenpai May 18, 2026
7e57192
test(ipc): split shm/viewport per-binary, drop dead SkipZigTest stubs
guysenpai May 18, 2026
fcddc23
docs(ipc): macOS shm cross-process diagnostic + --no-spawn editor flag
guysenpai May 18, 2026
8218ea6
fix(tests): align fuzz_1h seq counter type with framing.encode signature
guysenpai May 18, 2026
8299e1a
feat(editor): vulkan blit pipeline driving 1280×720 viewport window
guysenpai May 18, 2026
83046f4
fix(ipc): platform-correct socket path + windows GetLastError log
guysenpai May 18, 2026
7fd1dc4
fix(editor): nullify p_resolve_attachments to prevent nvidia segfault
guysenpai May 18, 2026
5779e87
docs(validation): finalize S6 go/no-go verdict across platforms
guysenpai May 18, 2026
5da26f0
docs(brief): close S6
guysenpai May 18, 2026
d63699c
fix(bench): use QueryPerformanceCounter on Windows + record linux RTT
guysenpai May 18, 2026
69f06b6
docs(validation): record windows RTT bench numbers + 3/3 G1/G2 GO
guysenpai May 18, 2026
9059716
test(ipc): add G5 — editor close → runtime EOF + exits clean
guysenpai May 18, 2026
03ed509
fix(tests): replace allocPrintZ with bufPrintZ in crash_recovery
guysenpai May 18, 2026
ac0c0f9
fix(build): wire crash_recovery test dep on weld-runtime install
guysenpai May 18, 2026
025584e
test(ipc): unblock fuzz_short + fuzz_1h for windows + macos
guysenpai May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 38 additions & 34 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,44 @@ session and captures the operational state of the project plus the rules that
must never be violated. The full specification lives in the claude.ai
knowledge base — see § Quick links spec.

> **Status:** Phase −1 — S5 closed (code + bench verdict GO), PR pending
> **Status:** Phase −1 — S6 closed (code + verdict GO on CI targets), PR pending
>
> S5 closed: Etch → Zig codegen on the S3 subset plus the compile-time
> measurement harness. `src/etch/zig_codegen/` lowers components to
> `extern struct`s and rules to functions that open a
> `comptime_query.query(world, .{T1, T2})` iteration (the comptime path
> mandated by the brief); the iterator is in `src/core/ecs/comptime_query.zig`.
> The registry has a new `registerAlias` so a single component is
> reachable by both Etch name (`world.spawnDynamic`) and Zig type
> (`@typeName` keyed comptime query). `tools/etch_cook` consolidates N
> inputs into one `.zig` for static linking; `tools/etch_synth`
> generates a deterministic 100-file corpus at
> `bench/fixtures/synth_100/scripts/`. The differential corpus (20
> programs) passes through both the interpreter and the cooked runner
> with byte-exact parity. Bench verdict on dev machine (Apple Silicon,
> macOS, ReleaseSafe, N=10): metric (a) codegen only 17 ms median,
> (b) cold `zig build-exe` 1087 ms median, (c) incremental
> `zig build-exe` 1049 ms median. Gates: (a)+(b) cold 1104 ms vs 30 s
> (27× margin), (a)+(c) incremental 1066 ms vs 2 s (1.9× margin), zero
> leak under `std.testing.allocator`, **382 distinct comptime query
> instantiations over 400 rules / 382 signatures (ceiling 4×=1528)**,
> 20/20 differential corpus parity. Validation: `zig build`, `zig build
> test` (debug + ReleaseSafe), `zig fmt --check`, `zig build
> bench-etch-compile`, `zig build run-demo-etch-codegen`, `zig build
> test-codegen-diff` all green. PR
> `Phase -1 / Etch / Etch → Zig codegen and compile-time measurement`
> opens next; tag `v0.0.6-S5-etch-codegen-zig` posted by Guy after
> squash-merge.
> S6 closed: editor↔runtime IPC validated. `src/core/ipc/` is the
> Tier 0 endpoint per `engine-ipc.md` — transport (AF_UNIX
> + named pipes), 16-byte framing + comptime Wyhash `schemaHash`,
> 13-message catalogue, shm + 2-slot viewport double-buffer, server
> + client wrappers, and an `IpcConnection` symmetric layer.
> `src/editor/main.zig` + `src/runtime/main.zig` are the two canonical
> binaries; the editor opens a 1280×720 Vulkan window and presents
> the runtime's CPU-side mire each frame through a fullscreen-triangle
> blit pipeline (`src/editor/vk_blit.zig`, SPIR-V committed under
> `assets/shaders/viewport_blit.{vert,frag}.spv`). Bench RTT on the
> dev primary (Apple Silicon, ReleaseSafe, Zig 0.16.0_1): p50 6 µs,
> p99 16 µs, max 61 µs, stddev 3 µs, mean 7 µs — G1 < 1 ms / G2
> p99 < 5 ms + max < 50 ms cleared by ~166×. G6 visual on the Fedora
> 44 + GTX 1660 Ti dev box: GO (60 s observation, no tearing, no
> stale frame > 100 ms). One BSD POSIX shm cross-process quirk found
> on macOS (`shm_open(O_RDWR)` returns EACCES for non-creator sibling
> independent of mode bits — diagnostic matrix in
> `validation/s6-go-nogo.md`) → migrate to SCM_RIGHTS fd-passing in
> Phase 0.6 (cohérent `engine-ipc.md` §4.7). Linux CI + Windows CI =
> GO ; macOS dev primary = partial (G1/G2/G7 GO ; G3/G4/G5/G6 SKIP
> documented). Validation : `zig build`, `zig build test`,
> `zig fmt --check`, `zig build bench-ipc-rtt`, `zig build run-ipc-demo`
> (Linux), `zig build -Dtarget=x86_64-linux`,
> `zig build -Dtarget=x86_64-windows` all clean. PR
> `Phase -1 / IPC / IPC editor↔runtime round-trip` opens next ; tag
> `v0.0.7-S6-ipc-round-trip` posted by Guy after squash-merge.

## Current state

| Field | Value |
|---|---|
| Phase | −1 (Spikes) |
| Current milestone | S5Etch → Zig codegen + compile-time measurement (CLOSED, PR pending) |
| Last released tag | `v0.0.5-S4-etch-tree-walking-interpreter` |
| Active branch | `phase-pre-0/etch/codegen-zig` |
| Next planned milestone | S6 — IPC editor↔runtime round-trip |
| Current milestone | S6IPC editor↔runtime round-trip (CLOSED, PR pending) |
| Last released tag | `v0.0.6-S5-etch-codegen-zig` |
| Active branch | `phase-pre-0/ipc/editor-runtime-round-trip` |
| Next planned milestone | Phase −1 closed at S6 → Phase 0 plan |

## Tags

Expand All @@ -53,7 +53,8 @@ knowledge base — see § Quick links spec.
| `v0.0.3-S2-window-vulkan-triangle` | 2026-05-11 | S2 — Window + Vulkan triangle | Native Win32 + Wayland windowing, Vulkan triangle, no SDL/GLFW. Validated GO on Win11 + RTX 4080, Fedora 44 + UHD 630, Fedora 44 + GTX 1660 Ti. |
| `v0.0.4-S3-etch-parser-subset` | 2026-05-15 | S3 — Etch parser on subset | Lexer + parser + tabular SoA AST + minimal type-checker on 5 constructs. Bench verdict GO (worst median 0.019 ms vs 5 ms target on dev machine; re-confirmation on reference machine pending). |
| `v0.0.5-S4-etch-tree-walking-interpreter` | 2026-05-16 | S4 — Etch tree-walking interpreter | Interpreter over S3 AST + additive Tier 0 ECS (runtime registry, dynamic archetype, resource store, runtime query). 20-program differential corpus. Bench verdict GO (median 0.603 ms / tick at 1 000 entities × 5 rules, gate 10 ms; median 6.593 ms / tick at 10 000 × 5, gate 100 ms) on dev Apple Silicon ReleaseSafe. |
| `v0.0.6-S5-etch-codegen-zig` | (planned) | S5 — Etch → Zig codegen and compile-time measurement | Etch → Zig codegen on the S3 subset. `extern struct` types + comptime `world.query(.{T1, T2})` iteration (via `src/core/ecs/comptime_query.zig`), with `Registry.registerAlias` letting components be keyed by both Etch name and `@typeName(T)`. `tools/etch_cook` consolidates N inputs into one `.zig`. 100-file synthetic corpus + 3-metric bench. Verdict GO on all 5 gates: (a)+(b) cold 1104 ms vs 30 s, (a)+(c) incremental 1066 ms vs 2 s, zero leak, **382 distinct comptime query instantiations on 400 rules (ceiling 4×=1528)**, 20/20 differential parity. Tag posted by Guy after squash-merge of PR `Phase -1 / Etch / Etch → Zig codegen and compile-time measurement`. |
| `v0.0.6-S5-etch-codegen-zig` | 2026-05-17 | S5 — Etch → Zig codegen and compile-time measurement | Etch → Zig codegen on the S3 subset. `extern struct` types + comptime `world.query(.{T1, T2})` iteration (via `src/core/ecs/comptime_query.zig`), with `Registry.registerAlias` letting components be keyed by both Etch name and `@typeName(T)`. `tools/etch_cook` consolidates N inputs into one `.zig`. 100-file synthetic corpus + 3-metric bench. Verdict GO on all 5 gates: (a)+(b) cold 1104 ms vs 30 s, (a)+(c) incremental 1066 ms vs 2 s, zero leak, **382 distinct comptime query instantiations on 400 rules (ceiling 4×=1528)**, 20/20 differential parity. |
| `v0.0.7-S6-ipc-round-trip` | (planned) | S6 — IPC editor↔runtime round-trip | Tier 0 `src/core/ipc/` (transport, framing, shm, viewport, server, client, connection). Two binaries `weld-editor` + `weld-runtime` at canonical `src/editor/` and `src/runtime/`. Fullscreen-triangle Vulkan blit pipeline + SPIR-V committed. RTT bench Apple Silicon ReleaseSafe: p50 6 µs / p99 16 µs / max 61 µs / stddev 3 µs (G1 < 1 ms cleared by 166×, G2 cleared). G6 visual GO on Fedora 44 + GTX 1660 Ti dev box (60 s, no tearing, no stale > 100 ms). G7 fd-passing POSIX GO. Linux CI + Windows CI = GO ; macOS dev primary = partial — BSD shm cross-process quirk documented in `validation/s6-go-nogo.md` § Diagnostics, migration vers SCM_RIGHTS fd-passing tracée Phase 0.6. Tag posted by Guy after squash-merge of PR `Phase -1 / IPC / IPC editor↔runtime round-trip`. |

## Hypotheses validated by spikes

Expand All @@ -65,14 +66,17 @@ knowledge base — see § Quick links spec.
| S3 | Etch grammar EBNF v0.6 (S3 subset) implementable, parsing < 5 ms / file | validated (worst median 0.019 ms on dev Apple Silicon ReleaseSafe; reference-machine re-run pending) |
| S4 | AST tree-walking interpreter executes Etch correctly with ECS bridge | validated (20-program differential corpus green; bench median 0.603 ms / tick @ 1 000 × 5 vs 10 ms gate on dev Apple Silicon ReleaseSafe) |
| S5 | Etch → Zig codegen viable build-time-wise (incremental < 2 s) | validated (5/5 gates GO; cold (a)+(b) 1104 ms vs 30 s gate, incremental (a)+(c) 1066 ms vs 2 s gate, 382 distinct comptime query instantiations on dev Apple Silicon ReleaseSafe; 100-file synth corpus + 20-program differential parity) |
| S6 | IPC editor↔runtime stable, < 1 ms RTT, 1h fuzz, kill -9 recovery | pending |
| S6 | IPC editor↔runtime stable, < 1 ms RTT, 1h fuzz, kill -9 recovery | validated (GO on CI targets — Linux + Windows; Apple Silicon ReleaseSafe RTT p50 6 µs / p99 16 µs / max 61 µs, G6 visual GO on Fedora 44 + GTX 1660 Ti dev box; macOS dev primary partial — BSD shm cross-process quirk → SCM_RIGHTS fd-passing migration tracée Phase 0.6) |

## Open / deferred decisions

- **Custom Zig linter** (`zig build lint`, `zig build lint-commit`): deferred to a dedicated Phase 0 milestone post-S1. No production code to lint at S0; the `commit-msg` hook uses a POSIX shell script (`scripts/check-commit-msg.sh`) until then.
- **macOS in the CI matrix**: deferred, re-evaluated after Phase 0 (CI quota constraints, primary targets are Win11 + Fedora 44).
- **Codeberg migration**: end of Phase 1 (criterion C1.10 in `engine-phase-1-criteria.md`). The repo lives on GitHub for Phase −1 / 0 / 1.
- **`spec/` directory in the repo**: out of scope at S0 per `engine-development-workflow.md` §3.5. Spec lives in the claude.ai knowledge base; re-evaluated at the start of Phase 0 if the absence creates friction.
- **SCM_RIGHTS fd-passing as primary POSIX shm attach (Phase 0.6)**: the S6 BSD shm cross-process diagnostic showed `shm_open(O_RDWR)` is structurally refused for non-creator siblings on macOS even with same UID. The Phase 0.6 migration ships the create fd via the existing AF_UNIX socket (`IpcSocket.sendWithHandles`, G7 GO) and has the runtime `mmap` directly on the received fd. Sidesteps the macOS quirk completely; cleaner protocol on every platform. `engine-ipc.md` §4.7 to be patched at the same time.
- **Editor stub Windows path (Phase 0.6)**: `src/editor/main.zig` returns `error.Unimplemented` on Windows. `CreateProcessW` + named pipe + the S2 Win32 window backend already exist — wiring it up is Phase 0.6 work.
- **`sendWithHandles` Windows (Phase 3)**: `transport_windows.zig:sendWithHandles` returns `error.Unimplemented`. The `DuplicateHandle`-based equivalent lands with the GPU shared framebuffer when an exportable Vulkan semaphore appears upstream (cf. `engine-ipc.md` §4.7).

## Non-negotiable rules

Expand Down Expand Up @@ -139,4 +143,4 @@ The `briefs/` directory is the source of truth for milestone state. The brief's

---

Last updated: 2026-05-17
Last updated: 2026-05-18
41 changes: 37 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

A game engine written in Zig 0.16.x.

> **Status:** Phase −1 — Etch Zig codegen + compile-time measurement (S5)
> **Status:** Phase −1 — IPC editor↔runtime round-trip (S6, closing)
>
> Weld is in its earliest exploratory phase: the spike list of Phase −1 is
> validating the core architectural hypotheses (comptime ECS, work-stealing
Expand Down Expand Up @@ -44,7 +44,7 @@ A game engine written in Zig 0.16.x.
> `zig build bench-etch-interp -Doptimize=ReleaseSafe` and the demo with
> `zig build run-demo-etch-interp -Doptimize=ReleaseSafe`.
>
> **S5** (closed, tag `v0.0.6-S5-etch-codegen-zig` pending merge) validated
> **S5** (closed, tag `v0.0.6-S5-etch-codegen-zig`) validated
> the shipping codegen hypothesis — `Etch → Zig source → Zig compile` is
> viable build-time-wise. The codegen lives in `src/etch/zig_codegen/`
> and lowers the S3 subset to idiomatic Zig: components become `extern
Expand All @@ -62,6 +62,26 @@ A game engine written in Zig 0.16.x.
> `zig build bench-etch-compile -Doptimize=ReleaseSafe` and the demo
> with `zig build run-demo-etch-codegen`. Full report:
> [`validation/s5-go-nogo.md`](validation/s5-go-nogo.md).
>
> **S6** (closed, tag `v0.0.7-S6-ipc-round-trip` pending merge) validated
> the editor↔runtime IPC. `src/core/ipc/` is the Tier 0 endpoint per
> `engine-ipc.md` — AF_UNIX socket / Win32 named pipe transport, 16 B
> framing header + comptime Wyhash `schemaHash`, 13-message catalogue,
> POSIX shm + Win32 file-mapping double-buffer viewport, fd-passing
> via `SCM_RIGHTS` cmsg. `src/editor/main.zig` and `src/runtime/main.zig`
> are the two canonical binaries at their Phase 0+ locations; the editor
> opens a 1280×720 Vulkan window and presents the runtime's
> CPU-side mire via a fullscreen-triangle blit pipeline
> (`src/editor/vk_blit.zig`, SPIR-V committed under
> `assets/shaders/viewport_blit.{vert,frag}.spv`). Bench RTT on the
> dev primary (Apple Silicon, ReleaseSafe) reports **p50 6 µs / p99
> 16 µs / max 61 µs** — G1 < 1 ms cleared by ~166×, G2 cleared. G6
> visual on Fedora 44 + GTX 1660 Ti: GO (60 s observation, no
> tearing, no stale frame > 100 ms). One macOS BSD POSIX shm cross-
> process limitation found en route, scoped to a Phase 0.6 SCM_RIGHTS
> fd-passing migration. Full report:
> [`validation/s6-go-nogo.md`](validation/s6-go-nogo.md).
> Brief: [`briefs/S6-ipc-editor-runtime.md`](briefs/S6-ipc-editor-runtime.md).

## Prerequisites

Expand Down Expand Up @@ -89,6 +109,13 @@ zig build bench-ecs -- --smoke # short bench run (used
zig build bench-etch -- --smoke # short Etch bench run (sanity)
zig build bench-etch-interp -- --smoke # short S4 bench run (sanity)
zig build bench-etch-compile -- --smoke # short S5 compile-time bench (sanity)
zig build run-editor-stub # S6 editor stub alone (spawns the runtime)
zig build run-runtime-stub # S6 runtime stub alone (needs --socket=… --shm=…)
zig build run-ipc-demo # S6 full demo: editor spawns runtime, window + mire 60 s
zig build run-ipc-demo -- --frames=600 # override the frame budget (default 3600 ≈ 60 s)
zig build bench-ipc-rtt -Doptimize=ReleaseSafe # S6 Echo RTT bench (N=10 000, report under bench/results/)
zig build test-ipc # S6 IPC tests (subset of `zig build test`, fast iteration)
zig build test-ipc-fuzz-1h # S6 1 h fuzz harness — manual invocation only
./scripts/install-hooks.sh # install local git hooks (run once after clone)
```

Expand Down Expand Up @@ -120,11 +147,17 @@ src/
ecs/ Tier 0 ECS — components, chunks, archetypes, queries, world
jobs/ Tier 0 work-stealing scheduler (Chase-Lev deques + 4 workers)
testing/ testing helpers (counting allocator wrapper)
platform/ generated Vulkan binding + native Win32 / Wayland windowing
ipc/ S6 Tier 0 editor↔runtime IPC — transport, framing, shm, viewport, server, client, connection
platform/ generated Vulkan binding + native Win32 / Wayland windowing + process control
vk.zig ~31 000 lines — generated from vk.xml by tools/vk_gen
window.zig public Window interface (create/destroy/pollEvent/nativeHandles)
window/{win32,wayland,stub}.zig per-OS backends (no SDL/GLFW, no @cImport)
window/wayland_protocols/ ~3 000 lines — generated from wayland XMLs by tools/wayland_gen
process.zig S6 process control — spawn / wait_nonblock / kill / is_alive (POSIX + Windows stub)
editor/ S6 editor binary — Window + Vulkan blit pipeline + IPC server
main.zig, vk_blit.zig
runtime/ S6 runtime binary — IPC client + 60 Hz CPU mire to shm viewport
main.zig
etch/ S3 Etch parser, S4 interpreter, S5 Zig codegen
zig_codegen/ S5 codegen — lower, emit, type_map, cache, errors, tests
parser.zig, types.zig, ast.zig (S3) / interp.zig, value.zig, ecs_bridge.zig (S4)
Expand All @@ -136,7 +169,7 @@ tools/
wayland_gen/ XML → Zig generator for Wayland protocol bindings
etch_cook/ S5 codegen CLI (Etch → consolidated Zig)
etch_synth/ S5 synthetic Etch corpus generator (deterministic)
assets/shaders/ GLSL sources + pre-compiled SPIR-V (triangle.vert, triangle.frag)
assets/shaders/ GLSL sources + pre-compiled SPIR-V (S2 triangle + S6 viewport_blit)
bench/ performance benchmarks (see "Basic commands" above)
tests/ out-of-tree tests wired into `zig build test`
validation/ hardware validation reports + PPM/PNG artefacts (step (j) per milestone)
Expand Down
15 changes: 11 additions & 4 deletions assets/shaders/embed.zig
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
//! Compile-time embedding of the S2 spike's pre-compiled SPIR-V shaders.
//! Routed through this tiny module so `@embedFile` resolves inside the
//! `assets/shaders/` package — the spike's executable module sits under
//! `src/`, which `@embedFile` cannot escape directly.
//! Compile-time embedding of pre-compiled SPIR-V shaders. Routed
//! through this tiny module so `@embedFile` resolves inside the
//! `assets/shaders/` package — caller modules sit under `src/`,
//! which `@embedFile` cannot escape directly.

// S2 triangle spike — kept for the legacy `weld` binary.
pub const triangle_vert_spv: []const u8 = @embedFile("triangle.vert.spv");
pub const triangle_frag_spv: []const u8 = @embedFile("triangle.frag.spv");

// S6 viewport blit pipeline — fullscreen triangle (no VBO,
// algorithmic positions from gl_VertexIndex) sampling the runtime-
// written shm framebuffer.
pub const viewport_blit_vert_spv: []const u8 = @embedFile("viewport_blit.vert.spv");
pub const viewport_blit_frag_spv: []const u8 = @embedFile("viewport_blit.frag.spv");
14 changes: 14 additions & 0 deletions assets/shaders/viewport_blit.frag.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#version 450

// Samples the runtime-written viewport framebuffer texture and
// outputs the unmodified RGBA value. The texture is uploaded each
// frame by the editor's command-buffer recording (CPU staging buffer
// → image transfer) from the shm region's currently-published slot.

layout(binding = 0) uniform sampler2D viewportTex;
layout(location = 0) in vec2 vUv;
layout(location = 0) out vec4 fragColor;

void main() {
fragColor = texture(viewportTex, vUv);
}
Binary file added assets/shaders/viewport_blit.frag.spv
Binary file not shown.
24 changes: 24 additions & 0 deletions assets/shaders/viewport_blit.vert.glsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#version 450

// Fullscreen-triangle generator — no VBO, no vertex input. Vertex
// indices 0, 1, 2 trace out a triangle that covers the entire
// `[-1, 1] × [-1, 1]` clip-space rectangle (the third vertex lies
// off-screen but the triangle's clipped area covers the full view).
// UV is derived from the position so the fragment shader can sample
// the viewport texture with a `[0, 1] × [0, 1]` coordinate.
//
// Source: Sascha Willems' fullscreen-triangle technique.
//
// index 0 → pos (-1, -1) → uv (0, 0)
// index 1 → pos ( 3, -1) → uv (2, 0)
// index 2 → pos (-1, 3) → uv (0, 2)
//
// The visible portion after clipping is uv ∈ [0, 1]² mapped onto the
// canonical screen quad.

layout(location = 0) out vec2 vUv;

void main() {
vUv = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(vUv * 2.0 - 1.0, 0.0, 1.0);
}
Binary file added assets/shaders/viewport_blit.vert.spv
Binary file not shown.
Loading
Loading