diff --git a/Brewfile b/Brewfile new file mode 100644 index 0000000..b37b701 --- /dev/null +++ b/Brewfile @@ -0,0 +1,4 @@ +# Runtime tools for RetroArch .slang shaders. Slang itself is installed by +# scripts/setup-dependencies.sh from the official shader-slang release. +brew "glslang" +brew "spirv-cross" diff --git a/README.md b/README.md index 871f5b9..cdbac7e 100644 --- a/README.md +++ b/README.md @@ -20,20 +20,41 @@ Useful for applying shaders like [my EINK shader](https://github.com/crutchcorn/ # Pre-reqs - [Homebrew](https://brew.sh/) -- Silicon Mac (M1+) with macOS 26+ +- Apple Silicon Mac (M1+) with macOS 26 or later, including macOS 27 # Installation -First, install the pre-req packages: +From a copy of this repository, install or update the shader compilers: ```shell -brew install spirv-cross glslang +./scripts/setup-dependencies.sh ``` -Then, [install `slangc`](https://github.com/shader-slang/slang/releases/latest) to `~/slang/bin/slangc` +This installs and upgrades the `glslang` and `spirv-cross` packages in [Brewfile](./Brewfile), then downloads [Slang 2026.18](https://github.com/shader-slang/slang/releases/tag/v2026.18) and checks its SHA-256 checksum. Slang is installed into `~/Library/Application Support/ScreenSlanger/Tools/slang/2026.18`, with a `current` symlink that ScreenSlanger discovers automatically. The full Slang distribution is needed, including its libraries. Existing installations under `~/slang` are preserved. Finally, [install ScreenSlanger from the DMG in our "Releases" tab.](https://github.com/crutchcorn/ScreenSlanger/releases/latest) +Run the setup script again after pulling project updates. Homebrew packages follow their current stable releases; the Slang version and checksums are pinned in the script so a compiler update can be reviewed and tested together with the app. The macOS 27 dependency baseline is: + +| Dependency | Version | Purpose | +| --- | --- | --- | +| [Slang](https://github.com/shader-slang/slang/releases/tag/v2026.18) | 2026.18 | Native Slang effects | +| [glslang](https://formulae.brew.sh/formula/glslang) | 16.6.0 | RetroArch GLSL to SPIR-V | +| [SPIRV-Cross](https://formulae.brew.sh/formula/spirv-cross) | 1.4.357.0 | SPIR-V to Metal | + +To inspect installed versions: + +```shell +brew list --versions glslang spirv-cross +"$HOME/Library/Application Support/ScreenSlanger/Tools/slang/current/bin/slangc" -version +``` + +For a custom installation, `SLANG_PATH`, `GLSLANG_PATH`, and `SPIRV_CROSS_PATH` may point to the respective executables in the app's environment. `brew install slang` installs the unrelated S-Lang library, not the shader compiler. + +# Building from source + +Use Xcode 27 with its macOS 27 SDK. Open `ScreenSlanger.xcodeproj`, select the **ScreenSlanger** scheme and **My Mac** destination, then build and run. The app retains macOS 26 as its minimum deployment version. There are no Swift package dependencies to resolve; the shader compilers above are runtime dependencies. + # Usage Simply open the `.app` and it should automatically prompt you for the `.slang` or `.slangp` files you want to apply and for which screens you want to enable them on. diff --git a/ScreenSlanger/slang_compiler.swift b/ScreenSlanger/slang_compiler.swift index fc52836..876e238 100644 --- a/ScreenSlanger/slang_compiler.swift +++ b/ScreenSlanger/slang_compiler.swift @@ -10,7 +10,7 @@ enum SlangCompilerError: Error, LocalizedError { var errorDescription: String? { switch self { case .slangcNotFound: - return "slangc compiler not found. Please install Slang or set SLANG_PATH environment variable." + return "slangc compiler not found. Run scripts/setup-dependencies.sh or set SLANG_PATH to the compiler executable." case .compilationFailed(let message): return "Slang compilation failed: \(message)" case .invalidOutput: @@ -86,6 +86,9 @@ class SlangCompiler { private static let slangcSearchPaths = [ // Environment variable override ProcessInfo.processInfo.environment["SLANG_PATH"], + // Version managed by scripts/setup-dependencies.sh (also works when launched from Finder). + FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent("Library/Application Support/ScreenSlanger/Tools/slang/current/bin/slangc").path, // Homebrew installation "/opt/homebrew/bin/slangc", "/usr/local/bin/slangc", diff --git a/scripts/setup-dependencies.sh b/scripts/setup-dependencies.sh new file mode 100755 index 0000000..3d4c38b --- /dev/null +++ b/scripts/setup-dependencies.sh @@ -0,0 +1,75 @@ +#!/bin/bash +set -euo pipefail + +if [[ "$(uname -s)" != "Darwin" ]]; then + echo "ScreenSlanger's dependencies must be installed on macOS." >&2 + exit 1 +fi + +project_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +slang_version="2026.18" +# Checksums published with the official v2026.18 GitHub release assets. +# https://github.com/shader-slang/slang/releases/tag/v2026.18 +case "$(uname -m)" in + arm64) + slang_arch="aarch64" + slang_sha256="59833c5cfa12aad72c6fbad9cfcc06be8781ecd58c5983e6c79425e819e16bb2" + ;; + x86_64) + slang_arch="x86_64" + slang_sha256="8d27b7020b102beecaa769c1ff7342dd2534c14cfae505a36e1b71d595208739" + ;; + *) + echo "Unsupported Mac architecture: $(uname -m)" >&2 + exit 1 + ;; +esac + +brew_command="$(command -v brew || true)" +if [[ -z "$brew_command" ]]; then + echo "Install Homebrew from https://brew.sh, then run this script again." >&2 + exit 1 +fi + +# Upgrade only this project's formulae and their required dependencies. +# Do not clean up other installed packages. +HOMEBREW_NO_INSTALL_CLEANUP=1 "$brew_command" bundle install --upgrade --file="$project_dir/Brewfile" + +slang_root="$HOME/Library/Application Support/ScreenSlanger/Tools/slang" +slang_directory="$slang_root/$slang_version" +mkdir -p "$slang_root" + +if [[ -e "$slang_root/current" && ! -L "$slang_root/current" ]]; then + echo "$slang_root/current exists and is not a symlink; leaving it unchanged." >&2 + exit 1 +fi + +if [[ ! -e "$slang_directory" ]]; then + staging_directory="$(mktemp -d "$slang_root/.install.XXXXXX")" + trap 'rm -rf "$staging_directory"' EXIT + archive_url="https://github.com/shader-slang/slang/releases/download/v$slang_version/slang-$slang_version-macos-$slang_arch.tar.gz" + curl --fail --location --retry 3 "$archive_url" --output "$staging_directory/slang.tar.gz" + ( + cd "$staging_directory" + printf '%s slang.tar.gz\n' "$slang_sha256" | shasum -a 256 --check - + ) + mkdir "$staging_directory/unpacked" + tar -xzf "$staging_directory/slang.tar.gz" -C "$staging_directory/unpacked" + installed_version="$("$staging_directory/unpacked/bin/slangc" -version 2>&1)" + if [[ "$installed_version" != "$slang_version" ]]; then + echo "Expected Slang $slang_version, got $installed_version; installation stopped." >&2 + exit 1 + fi + mv "$staging_directory/unpacked" "$slang_directory" +fi + +installed_version="$("$slang_directory/bin/slangc" -version 2>&1)" +if [[ "$installed_version" != "$slang_version" ]]; then + echo "Unexpected Slang version in $slang_directory: $installed_version" >&2 + exit 1 +fi +ln -sfn "$slang_version" "$slang_root/current" + +printf '\nInstalled ScreenSlanger dependencies:\n' +"$brew_command" list --versions glslang spirv-cross +printf 'slang %s (%s)\n' "$installed_version" "$slang_root/current/bin/slangc"