diff options
Diffstat (limited to 'build.zig')
| -rw-r--r-- | build.zig | 79 |
1 files changed, 51 insertions, 28 deletions
@@ -21,6 +21,19 @@ pub const macos_min_version: std.SemanticVersion = .{ .major = 13, .minor = 0, . const zls_version = "0.16.1-dev+3e0d0820"; pub const TreeSitterGrammars = enum { disabled, zig, minimal, full }; +/// The GUI shell's shaders, spelled ONCE. Three things read this list: the +/// eight SPIR-V imports the gui module embeds, the glslc runs that produce +/// them, and `zig build shaders`, which writes the same set into the tracked +/// shaders/prebuilt/. Each name is `shaders/<name>.glsl`, and the `.vert`/ +/// `.frag` in it is also the glslc shader stage — adding a shader is adding a +/// name here plus the @embedFile in src/gui/gui.zig. +const gui_shaders = [_][]const u8{ + "ui.vert", "ui.frag", + "overlay.vert", "overlay.frag", + "image.vert", "image.frag", + "crt.vert", "crt.frag", +}; + pub fn build(b: *std.Build) void { const platform = b.option(Platform, "platform", "which shell to build (tty, gui, web, macos)") orelse .tty; // Default target is the Steam Deck (deckcap's trick): x86_64 linux-gnu @@ -88,6 +101,20 @@ pub fn build(b: *std.Build) void { // the machine that built it and needs no keychain; a Developer ID here is // what makes one launchable on someone else's. See the macos branch below. const macos_identity = b.option([]const u8, "macos-identity", "codesigning identity for pardes.app (default: ad-hoc)") orelse "-"; + // Shader compilation is the one build input that needs a tool nothing else + // here needs: glslc, which ships with the Vulkan SDK / shaderc and is not + // on a stock machine. It is also the input that changes least often, so + // -Dprebuilt-shaders decouples the two: the SPIR-V compiled from + // shaders/*.glsl is committed under shaders/prebuilt/, and this flag + // embeds that copy instead of shelling out. `-Dplatform=gui` then builds + // with nothing but a C toolchain. + // + // Off by default because it trades a dependency for a freshness problem: + // with the flag on, the .glsl sources are NOT build inputs, so editing one + // changes nothing until someone runs `zig build shaders` (see below). The + // default therefore stays the honest one — compile the shaders that are + // actually in the tree. + const prebuilt_shaders = b.option(bool, "prebuilt-shaders", "embed the committed shaders/prebuilt/*.spv instead of running glslc (-Dplatform=gui without a Vulkan SDK)") orelse false; // The browser shell is a freestanding wasm core plus ordinary web files. // JavaScript owns the loop and IO; HTML/CSS own rendering. @@ -102,6 +129,19 @@ pub fn build(b: *std.Build) void { if (!enable_mupdf) pdf_sections_bench_step.dependOn(&b.addFail("pdf-sections-bench is unavailable with -Dmupdf=false").step); + // The other half of -Dprebuilt-shaders: recompile every shader and write + // the SPIR-V back into shaders/prebuilt/, which is TRACKED rather than + // generated-and-gitignored, because a machine without glslc cannot + // regenerate it. Deliberately independent of -Dplatform: whoever changes a + // shader runs `zig build shaders` on a machine that has the compiler and + // commits the diff (`jj diff shaders/prebuilt` says whether the cache had + // drifted), and no gui build is involved either way. + const shaders_step = b.step("shaders", "recompile shaders/*.glsl into the tracked shaders/prebuilt/*.spv (glslc; refreshes what -Dprebuilt-shaders embeds)"); + const update_shaders = b.addUpdateSourceFiles(); + for (gui_shaders) |name| + update_shaders.addCopyFileToSource(compileGlsl(b, name), b.fmt("shaders/prebuilt/{s}.spv", .{name})); + shaders_step.dependOn(&update_shaders.step); + // Web LOOK has a tiny read-only source filesystem. Generate one Zig module // on the host from every tracked .zig path + its current working-tree // contents. The generator prefers Git as the tracked-file filter and has a @@ -610,29 +650,11 @@ pub fn build(b: *std.Build) void { root_mod.addAnonymousImport("AdwaitaMono-Regular.ttf", .{ .root_source_file = b.path("assets/AdwaitaMono-Regular.ttf"), }); - root_mod.addAnonymousImport("ui.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/ui.vert.glsl", "vertex", "ui.vert.spv"), - }); - root_mod.addAnonymousImport("ui.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/ui.frag.glsl", "fragment", "ui.frag.spv"), - }); - root_mod.addAnonymousImport("overlay.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/overlay.vert.glsl", "vertex", "overlay.vert.spv"), - }); - root_mod.addAnonymousImport("overlay.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/overlay.frag.glsl", "fragment", "overlay.frag.spv"), - }); - root_mod.addAnonymousImport("image.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/image.vert.glsl", "vertex", "image.vert.spv"), - }); - root_mod.addAnonymousImport("image.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/image.frag.glsl", "fragment", "image.frag.spv"), - }); - root_mod.addAnonymousImport("crt.vert.spv", .{ - .root_source_file = compileGlsl(b, "shaders/crt.vert.glsl", "vertex", "crt.vert.spv"), - }); - root_mod.addAnonymousImport("crt.frag.spv", .{ - .root_source_file = compileGlsl(b, "shaders/crt.frag.glsl", "fragment", "crt.frag.spv"), + for (gui_shaders) |name| root_mod.addAnonymousImport(b.fmt("{s}.spv", .{name}), .{ + .root_source_file = if (prebuilt_shaders) + b.path(b.fmt("shaders/prebuilt/{s}.spv", .{name})) + else + compileGlsl(b, name), }); } @@ -1180,13 +1202,14 @@ fn reindexed(b: *std.Build, archive: std.Build.LazyPath, index: usize) std.Build return run.addOutputFileArg(b.fmt("{d}.a", .{index})); } -// glslc <src> -fshader-stage=<stage> -o <out> -> .spv, returned as a LazyPath -// for @embedFile. Only used by the SDL3 GPU shell (-Dplatform=gui). -fn compileGlsl(b: *std.Build, src: []const u8, stage: []const u8, out: []const u8) std.Build.LazyPath { +// glslc shaders/<name>.glsl -fshader-stage=<vertex|fragment> -o <name>.spv, +// returned as a LazyPath for @embedFile. The stage is the name's own suffix. +fn compileGlsl(b: *std.Build, name: []const u8) std.Build.LazyPath { + const stage = if (std.mem.endsWith(u8, name, ".vert")) "vertex" else "fragment"; const cmd = b.addSystemCommand(&.{ "glslc", b.fmt("-fshader-stage={s}", .{stage}) }); - cmd.addFileArg(b.path(src)); + cmd.addFileArg(b.path(b.fmt("shaders/{s}.glsl", .{name}))); cmd.addArg("-o"); - return cmd.addOutputFileArg(out); + return cmd.addOutputFileArg(b.fmt("{s}.spv", .{name})); } /// The theme sources, sorted. SORTED because the run step is cached by its |
