gpui: Add runtime-shaders feature so that Xcode.app is no longer necessary for Nix-based workflows (#7148)

Release Notes:

- N/A

Co-authored-by: Niklas <niklas@niklaskorz.de>
This commit is contained in:
Piotr Osiewicz 2024-01-31 17:37:16 +01:00 committed by GitHub
parent 8c8a5ad275
commit 5941102aac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 40 additions and 4 deletions

View file

@ -8,7 +8,14 @@ publish = false
license = "Apache-2.0"
[features]
test-support = ["backtrace", "dhat", "env_logger", "collections/test-support", "util/test-support"]
test-support = [
"backtrace",
"dhat",
"env_logger",
"collections/test-support",
"util/test-support",
]
runtime_shaders = []
[lib]
path = "src/gpui.rs"

View file

@ -1,7 +1,6 @@
use std::{
env,
path::{Path, PathBuf},
process::{self, Command},
};
use cbindgen::Config;
@ -9,6 +8,9 @@ use cbindgen::Config;
fn main() {
generate_dispatch_bindings();
let header_path = generate_shader_bindings();
#[cfg(feature = "runtime_shaders")]
emit_stitched_shaders(&header_path);
#[cfg(not(feature = "runtime_shaders"))]
compile_metal_shaders(&header_path);
}
@ -95,11 +97,30 @@ fn generate_shader_bindings() -> PathBuf {
output_path
}
/// To enable runtime compilation, we need to "stitch" the shaders file with the generated header
/// so that it is self-contained.
#[cfg(feature = "runtime_shaders")]
fn emit_stitched_shaders(header_path: &Path) {
use std::str::FromStr;
fn stitch_header(header: &Path, shader_path: &Path) -> std::io::Result<PathBuf> {
let header_contents = std::fs::read_to_string(header)?;
let shader_contents = std::fs::read_to_string(shader_path)?;
let stitched_contents = format!("{header_contents}\n{shader_contents}");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("stitched_shaders.metal");
let _ = std::fs::write(&out_path, stitched_contents)?;
Ok(out_path)
}
let shader_source_path = "./src/platform/mac/shaders.metal";
let shader_path = PathBuf::from_str(shader_source_path).unwrap();
stitch_header(header_path, &shader_path).unwrap();
println!("cargo:rerun-if-changed={}", &shader_source_path);
}
#[cfg(not(feature = "runtime_shaders"))]
fn compile_metal_shaders(header_path: &Path) {
use std::process::{self, Command};
let shader_path = "./src/platform/mac/shaders.metal";
let air_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.air");
let metallib_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.metallib");
println!("cargo:rerun-if-changed={}", shader_path);
let output = Command::new("xcrun")

View file

@ -17,7 +17,11 @@ use objc::{self, msg_send, sel, sel_impl};
use smallvec::SmallVec;
use std::{ffi::c_void, mem, ptr, sync::Arc};
#[cfg(not(feature = "runtime_shaders"))]
const SHADERS_METALLIB: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/shaders.metallib"));
#[cfg(feature = "runtime_shaders")]
const SHADERS_SOURCE_FILE: &'static str =
include_str!(concat!(env!("OUT_DIR"), "/stitched_shaders.metal"));
const INSTANCE_BUFFER_SIZE: usize = 32 * 1024 * 1024; // This is an arbitrary decision. There's probably a more optimal value (maybe even we could adjust dynamically...)
pub(crate) struct MetalRenderer {
@ -60,7 +64,11 @@ impl MetalRenderer {
| AutoresizingMask::HEIGHT_SIZABLE
];
}
#[cfg(feature = "runtime_shaders")]
let library = device
.new_library_with_source(&SHADERS_SOURCE_FILE, &metal::CompileOptions::new())
.expect("error building metal library");
#[cfg(not(feature = "runtime_shaders"))]
let library = device
.new_library_with_data(SHADERS_METALLIB)
.expect("error building metal library");