Skip to content

Commit f35e492

Browse files
committed
compile_codegen: allow SpirvBuilder watch to return something on first completion
1 parent 0c7f509 commit f35e492

File tree

2 files changed

+41
-15
lines changed

2 files changed

+41
-15
lines changed

crates/spirv-builder/src/watch.rs

+24-7
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@ use std::{collections::HashSet, sync::mpsc::sync_channel};
88
impl SpirvBuilder {
99
/// Watches the module for changes using [`notify`](https://crates.io/crates/notify),
1010
/// and rebuild it upon changes. Calls `on_compilation_finishes` after each
11-
/// successful compilation.
12-
pub fn watch(
11+
/// successful compilation. The second `Option<AcceptFirstCompile<T>>`
12+
/// param allows you to return some `T` on the first compile, which is
13+
/// then returned by this function (wrapped in Option).
14+
pub fn watch<T>(
1315
&self,
14-
mut on_compilation_finishes: impl FnMut(CompileResult) + Send + 'static,
15-
) -> Result<(), SpirvBuilderError> {
16+
mut on_compilation_finishes: impl FnMut(CompileResult, Option<AcceptFirstCompile<'_, T>>)
17+
+ Send
18+
+ 'static,
19+
) -> Result<Option<T>, SpirvBuilderError> {
1620
let path_to_crate = self
1721
.path_to_crate
1822
.as_ref()
@@ -42,7 +46,8 @@ impl SpirvBuilder {
4246
}
4347
};
4448
let metadata = self.parse_metadata_file(&metadata_file)?;
45-
on_compilation_finishes(metadata);
49+
let mut out = None;
50+
on_compilation_finishes(metadata, Some(AcceptFirstCompile(&mut out)));
4651

4752
let builder = self.clone();
4853
let thread = std::thread::spawn(move || {
@@ -57,12 +62,24 @@ impl SpirvBuilder {
5762
.parse_metadata_file(&file)
5863
.expect("Metadata file is correct");
5964
watcher.watch_leaf_deps(&metadata_file);
60-
on_compilation_finishes(metadata);
65+
on_compilation_finishes(metadata, None);
6166
}
6267
}
6368
});
6469
drop(thread);
65-
Ok(())
70+
Ok(out)
71+
}
72+
}
73+
74+
pub struct AcceptFirstCompile<'a, T>(&'a mut Option<T>);
75+
76+
impl<'a, T> AcceptFirstCompile<'a, T> {
77+
pub fn new(write: &'a mut Option<T>) -> Self {
78+
Self(write)
79+
}
80+
81+
pub fn submit(self, t: T) {
82+
*self.0 = Some(t);
6683
}
6784
}
6885

examples/runners/wgpu/src/lib.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -164,13 +164,7 @@ fn maybe_watch(
164164
// HACK(eddyb) needed because of `debugPrintf` instrumentation limitations
165165
// (see https://github.com/KhronosGroup/SPIRV-Tools/issues/4892).
166166
.multimodule(has_debug_printf);
167-
let initial_result = if let Some(mut f) = on_watch {
168-
builder
169-
.watch(move |compile_result| f(handle_compile_result(compile_result)))
170-
.expect("Configuration is correct for watching")
171-
} else {
172-
builder.build().unwrap()
173-
};
167+
174168
fn handle_compile_result(compile_result: CompileResult) -> CompiledShaderModules {
175169
let load_spv_module = |path| {
176170
let data = std::fs::read(path).unwrap();
@@ -194,7 +188,22 @@ fn maybe_watch(
194188
},
195189
}
196190
}
197-
handle_compile_result(initial_result)
191+
192+
if let Some(mut f) = on_watch {
193+
builder
194+
.watch(move |compile_result, accept| {
195+
let modules = handle_compile_result(compile_result);
196+
if let Some(accept) = accept {
197+
accept.submit(modules);
198+
} else {
199+
f(modules);
200+
}
201+
})
202+
.expect("Configuration is correct for watching")
203+
.unwrap()
204+
} else {
205+
handle_compile_result(builder.build().unwrap())
206+
}
198207
}
199208
#[cfg(any(target_os = "android", target_arch = "wasm32"))]
200209
{

0 commit comments

Comments
 (0)