Skip to content

Commit 76925b1

Browse files
refactor: remove runtime shader compilation and constants generation, use precompiled Metal library instead
Closes: #77
1 parent 3b8391c commit 76925b1

4 files changed

Lines changed: 45 additions & 274 deletions

File tree

mopro-msm/build.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,21 @@ fn compile_shaders() -> std::io::Result<()> {
5151

5252
// Compile combined source to AIR
5353
let target = env::var("TARGET").unwrap_or_default();
54-
let sdk = if target.contains("apple-ios") { "iphoneos" } else { "macosx" };
54+
let sdk = if target.contains("apple-ios") {
55+
"iphoneos"
56+
} else {
57+
"macosx"
58+
};
5559
let air = shader_out_dir.join("msm.air");
5660
let status = Command::new("xcrun")
5761
.args(&[
58-
"-sdk", sdk,
59-
"metal", "-c",
62+
"-sdk",
63+
sdk,
64+
"metal",
65+
"-c",
6066
combined.to_str().unwrap(),
61-
"-o", air.to_str().unwrap(),
67+
"-o",
68+
air.to_str().unwrap(),
6269
])
6370
.status()
6471
.expect("Failed to invoke metal");
@@ -72,10 +79,12 @@ fn compile_shaders() -> std::io::Result<()> {
7279
let msm_lib = shader_out_dir.join("msm.metallib");
7380
let status = Command::new("xcrun")
7481
.args(&[
75-
"-sdk", sdk,
82+
"-sdk",
83+
sdk,
7684
"metallib",
7785
air_path,
78-
"-o", msm_lib.to_str().unwrap(),
86+
"-o",
87+
msm_lib.to_str().unwrap(),
7988
])
8089
.status()
8190
.expect("Failed to invoke metallib");

mopro-msm/src/msm/metal_msm/host/shader.rs

Lines changed: 0 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ use ark_ff::{BigInt, PrimeField, Zero};
2121
use num_bigint::BigUint;
2222
use std::fs;
2323
use std::path::PathBuf;
24-
use std::process::Command;
25-
use std::string::String;
2624

2725
macro_rules! write_constant_array {
2826
($data:expr, $name:expr, $values:expr, $size:expr) => {
@@ -36,108 +34,6 @@ macro_rules! write_constant_array {
3634
};
3735
}
3836

39-
/// Get the shader directory path using CARGO_MANIFEST_DIR for proper OS file location
40-
/// This function provides robust path resolution that works across different build environments
41-
pub fn get_shader_dir() -> PathBuf {
42-
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
43-
let shader_path = manifest_dir
44-
.join("src")
45-
.join("msm")
46-
.join("metal_msm")
47-
.join("shader");
48-
49-
// Verify the path exists, if not try alternative locations
50-
if shader_path.exists() {
51-
shader_path
52-
} else {
53-
// Fallback: try relative path from workspace root
54-
let workspace_shader_path = manifest_dir
55-
.parent() // go up one level from mopro-msm to workspace root
56-
.unwrap_or(&manifest_dir)
57-
.join("mopro-msm")
58-
.join("src")
59-
.join("msm")
60-
.join("metal_msm")
61-
.join("shader");
62-
63-
if workspace_shader_path.exists() {
64-
workspace_shader_path
65-
} else {
66-
// Final fallback: use the original path and let error handling take care of it
67-
shader_path
68-
}
69-
}
70-
}
71-
72-
pub fn compile_metal(path_from_cargo_manifest_dir: &str, input_filename: &str) -> String {
73-
let input_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
74-
.join(path_from_cargo_manifest_dir)
75-
.join(input_filename);
76-
let c = input_path.clone().into_os_string().into_string().unwrap();
77-
78-
let lib = input_path.clone().into_os_string().into_string().unwrap();
79-
let lib = format!("{}.lib", lib);
80-
81-
let exe = if cfg!(target_os = "ios") {
82-
Command::new("xcrun")
83-
.args([
84-
"-sdk",
85-
"iphoneos",
86-
"metal",
87-
"-std=metal3.2",
88-
"-target",
89-
"air64-apple-ios18.0",
90-
"-fmetal-enable-logging",
91-
"-o",
92-
lib.as_str(),
93-
c.as_str(),
94-
])
95-
.output()
96-
.expect("failed to compile")
97-
} else if cfg!(target_os = "macos") {
98-
let macos_version = std::process::Command::new("sw_vers")
99-
.args(["-productVersion"])
100-
.output()
101-
.ok()
102-
.and_then(|output| String::from_utf8(output.stdout).ok())
103-
.and_then(|version| {
104-
version
105-
.trim()
106-
.split('.')
107-
.next()
108-
.and_then(|major| major.parse::<u32>().ok())
109-
})
110-
.unwrap_or(0);
111-
112-
let mut args = vec!["-sdk", "macosx", "metal"];
113-
114-
// Only specify Metal 3.2 for metal logging if macOS version is 15.0 or higher
115-
if macos_version >= 15 {
116-
args.extend([
117-
"-std=metal3.2",
118-
"-target",
119-
"air64-apple-macos15.0",
120-
"-fmetal-enable-logging",
121-
]);
122-
}
123-
124-
args.extend(["-o", lib.as_str(), c.as_str()]);
125-
126-
Command::new("xcrun")
127-
.args(args)
128-
.output()
129-
.expect("failed to compile")
130-
} else {
131-
panic!("Unsupported architecture");
132-
};
133-
134-
if exe.stderr.len() != 0 {
135-
panic!("{}", String::from_utf8(exe.stderr).unwrap());
136-
}
137-
138-
lib
139-
}
140-
14137
pub fn write_constants(
14238
filepath: &str,
14339
num_limbs: usize,
@@ -293,16 +189,6 @@ pub fn write_constants(
293189
pub mod tests {
294190
use super::*;
295191

296-
#[test]
297-
#[serial_test::serial]
298-
pub fn test_compile() {
299-
let lib_filepath = compile_metal(
300-
"../mopro-msm/src/msm/metal_msm/shader",
301-
"bigint/bigint_add_unsafe.metal",
302-
);
303-
println!("{}", lib_filepath);
304-
}
305-
306192
#[test]
307193
#[serial_test::serial]
308194
pub fn test_write_constants() {

mopro-msm/src/msm/metal_msm/utils/metal_wrapper.rs

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::msm::metal_msm::host::gpu::{
22
create_buffer, create_empty_buffer, get_default_device, read_buffer,
33
};
4-
use crate::msm::metal_msm::host::shader::{compile_metal, get_shader_dir, write_constants};
4+
// no runtime shader compilation, drop constants generation here
55
use crate::msm::metal_msm::utils::barrett_params::calc_barrett_mu;
66
use crate::msm::metal_msm::utils::mont_params::{calc_mont_radix, calc_nsafe, calc_rinv_and_n0};
77

@@ -13,6 +13,8 @@ use num_bigint::BigUint;
1313
use once_cell::sync::Lazy;
1414
use std::collections::HashMap;
1515
use std::sync::Mutex;
16+
// Embed the precompiled Metal library
17+
include!(concat!(env!("OUT_DIR"), "/built_shaders.rs"));
1618

1719
/// Cache of precomputed constants
1820
static CONSTANTS_CACHE: Lazy<Mutex<HashMap<(usize, u32), MSMConstants>>> =
@@ -143,42 +145,15 @@ impl MetalHelper {
143145
let encoder =
144146
command_buffer.compute_command_encoder_with_descriptor(compute_pass_descriptor);
145147

146-
// Setup shader constants
147-
let constants = get_or_calc_constants(config.num_limbs, config.log_limb_size);
148-
write_constants(
149-
get_shader_dir().to_str().unwrap(),
150-
config.num_limbs,
151-
config.log_limb_size,
152-
constants.n0,
153-
constants.nsafe,
154-
);
155-
156-
// Prepare full shader path
157-
let shader_path = format!(
158-
"{}/{}",
159-
get_shader_dir().to_str().unwrap(),
160-
config.shader_file
161-
);
162-
let parts: Vec<&str> = shader_path.rsplitn(2, '/').collect();
163-
let shader_dir = if parts.len() > 1 { parts[1] } else { "" };
164-
let shader_file = parts[0];
165-
166-
// Compile shader
167-
let library_path = compile_metal(shader_dir, shader_file);
168-
let library = self.device.new_library_with_file(library_path).unwrap();
148+
149+
// Load precompiled Metal library and create pipeline
150+
let library = self.device.new_library_with_data(MSM_METALLIB).unwrap();
169151
let kernel = library
170152
.get_function(config.kernel_name.as_str(), None)
171153
.unwrap();
172-
173-
// Create pipeline
174-
let pipeline_state_descriptor = ComputePipelineDescriptor::new();
175-
pipeline_state_descriptor.set_compute_function(Some(&kernel));
176-
177154
let pipeline_state = self
178155
.device
179-
.new_compute_pipeline_state_with_function(
180-
pipeline_state_descriptor.compute_function().unwrap(),
181-
)
156+
.new_compute_pipeline_state_with_function(&kernel)
182157
.unwrap();
183158

184159
encoder.set_compute_pipeline_state(&pipeline_state);

0 commit comments

Comments
 (0)