1
1
use std:: {
2
+ collections:: BTreeMap ,
2
3
error:: Error ,
3
4
path:: { Path , PathBuf } ,
4
5
str:: FromStr ,
5
6
} ;
6
7
8
+ use rust_gpu_builder_shared:: { RustGpuBuilderModules , RustGpuBuilderOutput } ;
9
+
7
10
use clap:: { error:: ErrorKind , Parser } ;
8
11
9
12
use async_channel:: { unbounded, Receiver , Sender } ;
@@ -25,6 +28,8 @@ use tracing::{error, info};
25
28
struct ShaderBuilder {
26
29
/// Shader crate to compile.
27
30
path_to_crate : PathBuf ,
31
+ /// If set, combined SPIR-V and entrypoint metadata will be written to this file on succesful compile.
32
+ output_path : Option < PathBuf > ,
28
33
/// rust-gpu compile target.
29
34
#[ arg( short, long, default_value = "spirv-unknown-vulkan1.2" ) ]
30
35
target : String ,
@@ -184,6 +189,66 @@ async fn async_watch<P: AsRef<Path>>(
184
189
Ok ( ( ) )
185
190
}
186
191
192
+ async fn handle_compile_result ( result : CompileResult , output_path : Option < PathBuf > ) {
193
+ info ! ( "Entry Points:" ) ;
194
+ for entry in & result. entry_points {
195
+ println ! ( "{entry:}" ) ;
196
+ }
197
+
198
+ let entry_points = result. entry_points ;
199
+
200
+ println ! ( ) ;
201
+
202
+ info ! ( "Modules:" ) ;
203
+ match & result. module {
204
+ spirv_builder:: ModuleResult :: SingleModule ( single) => {
205
+ println ! ( "{single:?}" ) ;
206
+ }
207
+
208
+ spirv_builder:: ModuleResult :: MultiModule ( multi) => {
209
+ for ( k, module) in multi {
210
+ println ! ( "{k:}: {module:?}" ) ;
211
+ }
212
+ }
213
+ } ;
214
+
215
+ let Some ( output_path) = output_path else {
216
+ return
217
+ } ;
218
+
219
+ let modules = match result. module {
220
+ spirv_builder:: ModuleResult :: SingleModule ( single) => {
221
+ let module = async_fs:: read ( single)
222
+ . await
223
+ . expect ( "Failed to read module file" ) ;
224
+ RustGpuBuilderModules :: Single ( module)
225
+ }
226
+
227
+ spirv_builder:: ModuleResult :: MultiModule ( multi) => {
228
+ let mut out = BTreeMap :: default ( ) ;
229
+ for ( k, module) in multi {
230
+ let module = async_fs:: read ( module)
231
+ . await
232
+ . expect ( "Failed to read module file" ) ;
233
+ out. insert ( k, module) ;
234
+ }
235
+ RustGpuBuilderModules :: Multi ( out)
236
+ }
237
+ } ;
238
+
239
+ let out = RustGpuBuilderOutput {
240
+ entry_points,
241
+ modules,
242
+ } ;
243
+
244
+ let out = serde_json:: to_string_pretty ( & out) . expect ( "Failed to serialize output" ) ;
245
+ async_fs:: write ( & output_path, out)
246
+ . await
247
+ . expect ( "Failed to write output" ) ;
248
+ println ! ( ) ;
249
+ info ! ( "Wrote output to {output_path:?}" ) ;
250
+ }
251
+
187
252
fn main ( ) {
188
253
tracing_subscriber:: fmt ( ) . init ( ) ;
189
254
@@ -194,8 +259,9 @@ fn main() {
194
259
println ! ( ) ;
195
260
196
261
info ! ( "Building shader..." ) ;
197
- if args. build_shader ( ) . is_ok ( ) {
198
- info ! ( "Build complete!" ) ;
262
+ println ! ( ) ;
263
+ if let Ok ( result) = args. build_shader ( ) {
264
+ future:: block_on ( handle_compile_result ( result, args. output_path . clone ( ) ) ) ;
199
265
} else {
200
266
error ! ( "Build failed!" ) ;
201
267
}
@@ -227,7 +293,9 @@ fn main() {
227
293
Ok ( Msg :: Change ) => {
228
294
if !building {
229
295
building = true ;
296
+ println ! ( ) ;
230
297
info ! ( "Building shader..." ) ;
298
+ println ! ( ) ;
231
299
ex. spawn ( {
232
300
let build_tx = build_tx. clone ( ) ;
233
301
let args = args. clone ( ) ;
@@ -242,8 +310,10 @@ fn main() {
242
310
}
243
311
}
244
312
Ok ( Msg :: Build ( result) ) => {
245
- if result. is_ok ( ) {
246
- info ! ( "Build complete!" ) ;
313
+ if let Ok ( result) = result {
314
+ let output_path = args. output_path . clone ( ) ;
315
+ ex. spawn ( handle_compile_result ( result, output_path) )
316
+ . detach ( ) ;
247
317
} else {
248
318
error ! ( "Build failed!" ) ;
249
319
}
0 commit comments