From 826ec1fac3c012e71ab34207328faaac5b5827b7 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 29 Sep 2026 09:43:05 -0300 Subject: Shader files compile again on save; an attached GUI runs the session's post chain shader_build.zig takes the Shadertoy compile out of the GUI's Post: the process that holds the core compiles each chain file behind the prefix on a thread, watches its directory (file_watch's new shader slots), and on a change reads and hashes each file, compiling only one whose bytes moved. A failed compile keeps the last good SPIR-V and is said once; the same bytes are never compiled or reported twice. A file is read with std, not fs.zig's readFile, whose turn hand-off a worker thread does not hold. A detached session compiles for its frontends and sends them the chain (wire post: each pass's scene and level or the file's SPIR-V, and ShaderAnimation) on attach and on every change, so an attached GUI runs the same passes, levels and animation as a local one while still reading no disk and running no program. The attached GUI describes its frames to the chain from the session's chrome and redraws an animating chain on its own. --- src/detached/client.zig | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'src/detached/client.zig') diff --git a/src/detached/client.zig b/src/detached/client.zig index 8c9a2560..69ab2fdd 100644 --- a/src/detached/client.zig +++ b/src/detached/client.zig @@ -109,6 +109,10 @@ pub const Client = struct { regions: std.ArrayListUnmanaged(pardes.Region) = .empty, /// The palette its chrome is drawn in, as its last frame gave it. chrome: pardes.Chrome = .{}, + /// The post chain its frames are drawn through, as the session last + /// sent it; its paths and SPIR-V owned here. `post_key` moves with it. + post: wire.Post = .{}, + post_key: u32 = 0, in: std.ArrayListUnmanaged(u8) = .empty, out: std.ArrayListUnmanaged(u8) = .empty, /// Bytes of `in` belonging to the message `next` returned last. Compacted at @@ -187,6 +191,7 @@ pub const Client = struct { } for (&c.tag_layers) |*layer| c.gpa.free(layer.cells); c.regions.deinit(c.gpa); + c.freePost(); c.in.deinit(c.gpa); c.out.deinit(c.gpa); } @@ -356,10 +361,30 @@ pub const Client = struct { // open a URI on this display or read this display's selection back // over the socket. `Ungreeted` is the same refusal a frame gets. .set_clipboard, .read_clipboard, .open_link => if (!c.attached()) return error.Ungreeted, + // Kept, like the chrome: the frames that follow are drawn + // through it. + .post => |chain| { + if (!c.attached()) return error.Ungreeted; + c.freePost(); + c.post = chain; + for (c.post.passes[0..c.post.len]) |*pass| { + pass.path = c.gpa.dupe(u8, pass.path) catch return error.Closed; + pass.spirv = c.gpa.dupe(u8, pass.spirv) catch return error.Closed; + } + c.post_key +%= 1; + }, } return msg; } + fn freePost(c: *Client) void { + for (c.post.passes[0..c.post.len]) |pass| { + c.gpa.free(pass.path); + c.gpa.free(pass.spirv); + } + c.post = .{}; + } + // ---- internals -------------------------------------------------------- fn reshape(c: *Client, cols: u16, rows: u16) (Error || wire.Error)!void { @@ -1131,7 +1156,7 @@ test "detached session: the seam's own routing rules, per surviving effect" { test "detached session: a frontend is never asked to fork, write, or watch" { // THE INVARIANT OF THE WHOLE DETACHED DESIGN, pinned as a property of the // protocol rather than of one code path: a frontend is input and screen, so - // the set of messages that can reach it is exactly the eight below. If a + // the set of messages that can reach it is exactly the nine below. If a // machine-local effect is ever put back on the wire, a frontend becomes the // process that owns a pane's shell again — and a pane whose shell belongs to // a frontend dies when that frontend leaves, which is the bug this replaced. @@ -1149,6 +1174,10 @@ test "detached session: a frontend is never asked to fork, write, or watch" { // The three that need THIS human's display and cannot be done by a // daemon nobody is looking at. "set_clipboard", "read_clipboard", "open_link", + // Display state, like a frame's chrome: the passes this display + // draws its frames through. A file's SPIR-V arrives compiled, so the + // frontend still reads no disk and runs no program. + "post", }; // One: the union a frontend decodes into has no other variant. Named @@ -1183,7 +1212,7 @@ test "detached session: a frontend is never asked to fork, write, or watch" { if (@intFromEnum(want) == tag) break true; } else false; if (!named) { - std.debug.print("tag 0x{x:0>2} is decodable by a frontend and is not one of the seven\n", .{tag}); + std.debug.print("tag 0x{x:0>2} is decodable by a frontend and is not one of the nine\n", .{tag}); return error.MachineLocalEffectOnTheWire; } } -- cgit v1.3