1
1
//! Wrapper for extending a `Material` with `rust-gpu` shader functionality.
2
2
3
- use std:: { any:: TypeId , marker:: PhantomData , sync:: RwLock } ;
3
+ use std:: { any:: TypeId , marker:: PhantomData , path :: PathBuf , sync:: RwLock } ;
4
4
5
5
use bevy:: {
6
6
pbr:: MaterialPipelineKey ,
7
7
prelude:: {
8
8
default, info, warn, CoreStage , Image , IntoSystemDescriptor , Material , MaterialPlugin ,
9
- Plugin ,
9
+ Plugin , Handle , Shader , Deref , DerefMut , Resource ,
10
10
} ,
11
11
reflect:: TypeUuid ,
12
12
render:: render_resource:: { AsBindGroup , PreparedBindGroup , ShaderRef } ,
13
- utils:: HashMap ,
13
+ utils:: { HashMap , HashSet } ,
14
14
} ;
15
15
use once_cell:: sync:: Lazy ;
16
16
17
17
use crate :: {
18
18
load_rust_gpu_shader:: RustGpuShader ,
19
- prelude:: { EntryPoint , Export , ExportHandle , RustGpuMaterial , SHADER_META } ,
19
+ prelude:: { EntryPoint , RustGpuMaterial } ,
20
20
systems:: { reload_materials, shader_events} ,
21
21
} ;
22
22
68
68
}
69
69
}
70
70
71
+ /// A resource to track `rust-gpu` shaders that have been reloaded on a given frame
72
+ #[ derive( Debug , Default , Clone , Deref , DerefMut , Resource ) ]
73
+ pub struct ChangedShaders ( pub HashSet < Handle < Shader > > ) ;
74
+
71
75
/// Type-level RustGpu material settings
72
76
#[ derive( Debug , Default , Copy , Clone ) ]
73
77
pub struct RustGpuSettings {
86
90
pub vertex_shader : Option < RustGpuShader > ,
87
91
pub fragment_shader : Option < RustGpuShader > ,
88
92
pub iteration : usize ,
89
- #[ cfg( feature = "hot-rebuild" ) ]
90
- pub export_handle : Option < ExportHandle > ,
91
93
}
92
94
93
95
impl < M > Clone for RustGpuKey < M >
@@ -101,7 +103,6 @@ where
101
103
vertex_shader : self . vertex_shader . clone ( ) ,
102
104
fragment_shader : self . fragment_shader . clone ( ) ,
103
105
iteration : self . iteration . clone ( ) ,
104
- export_handle : self . export_handle . clone ( ) ,
105
106
}
106
107
}
107
108
}
@@ -154,10 +155,6 @@ pub struct RustGpu<M> {
154
155
155
156
/// Current reload iteration, used to drive hot-reloading.
156
157
pub iteration : usize ,
157
-
158
- /// If `Some`, active entry points will be reported to this handle.
159
- #[ cfg( feature = "hot-rebuild" ) ]
160
- pub export_handle : Option < ExportHandle > ,
161
158
}
162
159
163
160
impl < M > PartialEq for RustGpu < M >
@@ -237,8 +234,6 @@ where
237
234
vertex_shader : self . vertex_shader . clone ( ) ,
238
235
fragment_shader : self . fragment_shader . clone ( ) ,
239
236
iteration : self . iteration ,
240
- #[ cfg( feature = "hot-rebuild" ) ]
241
- export_handle : self . export_handle . clone ( ) ,
242
237
} ,
243
238
} )
244
239
}
@@ -329,7 +324,7 @@ where
329
324
330
325
#[ cfg( feature = "hot-reload" ) ]
331
326
{
332
- let metas = SHADER_META . read ( ) . unwrap ( ) ;
327
+ let metas = crate :: prelude :: SHADER_META . read ( ) . unwrap ( ) ;
333
328
if let Some ( vertex_meta) = metas. get ( & vertex_shader. 0 ) {
334
329
info ! ( "Vertex meta is valid" ) ;
335
330
info ! ( "Checking entry point {entry_point:}" ) ;
@@ -343,15 +338,25 @@ where
343
338
}
344
339
345
340
#[ cfg( feature = "hot-rebuild" ) ]
346
- if let Some ( sender) = & key. bind_group_data . export_handle {
341
+ ' hot_rebuild: {
342
+ let exports = crate :: prelude:: MATERIAL_EXPORTS . read ( ) . unwrap ( ) ;
343
+ let Some ( export) = exports. get ( & std:: any:: TypeId :: of :: < Self > ( ) ) else {
344
+ break ' hot_rebuild;
345
+ } ;
346
+
347
+ let handles = crate :: prelude:: EXPORT_HANDLES . read ( ) . unwrap ( ) ;
348
+ let Some ( handle) = handles. get ( export) else {
349
+ break ' hot_rebuild;
350
+ } ;
351
+
347
352
info ! ( "Entrypoint sender is valid" ) ;
348
- sender
349
- . send ( Export {
353
+ handle
354
+ . send ( crate :: prelude :: Export {
350
355
shader : M :: Vertex :: NAME ,
351
356
permutation : M :: Vertex :: permutation ( & shader_defs) ,
352
357
} )
353
358
. unwrap ( ) ;
354
- }
359
+ } ;
355
360
356
361
if apply {
357
362
info ! ( "Applying vertex shader and entry point" ) ;
@@ -382,7 +387,7 @@ where
382
387
#[ cfg( feature = "hot-reload" ) ]
383
388
{
384
389
info ! ( "Fragment meta is present" ) ;
385
- let metas = SHADER_META . read ( ) . unwrap ( ) ;
390
+ let metas = crate :: prelude :: SHADER_META . read ( ) . unwrap ( ) ;
386
391
if let Some ( fragment_meta) = metas. get ( & fragment_shader. 0 ) {
387
392
info ! ( "Fragment meta is valid" ) ;
388
393
info ! ( "Checking entry point {entry_point:}" ) ;
@@ -396,14 +401,25 @@ where
396
401
}
397
402
398
403
#[ cfg( feature = "hot-rebuild" ) ]
399
- if let Some ( sender) = & key. bind_group_data . export_handle {
400
- sender
401
- . send ( Export {
404
+ ' hot_rebuild: {
405
+ let exports = crate :: prelude:: MATERIAL_EXPORTS . read ( ) . unwrap ( ) ;
406
+ let Some ( export) = exports. get ( & std:: any:: TypeId :: of :: < Self > ( ) ) else {
407
+ break ' hot_rebuild;
408
+ } ;
409
+
410
+ let handles = crate :: prelude:: EXPORT_HANDLES . read ( ) . unwrap ( ) ;
411
+ let Some ( handle) = handles. get ( export) else {
412
+ break ' hot_rebuild;
413
+ } ;
414
+
415
+ info ! ( "Entrypoint sender is valid" ) ;
416
+ handle
417
+ . send ( crate :: prelude:: Export {
402
418
shader : M :: Fragment :: NAME ,
403
419
permutation : M :: Fragment :: permutation ( & shader_defs) ,
404
420
} )
405
421
. unwrap ( ) ;
406
- }
422
+ } ;
407
423
408
424
if apply {
409
425
info ! ( "Applying fragment shader and entry point" ) ;
@@ -431,4 +447,10 @@ where
431
447
let mut settings = MATERIAL_SETTINGS . write ( ) . unwrap ( ) ;
432
448
f ( & mut settings. entry ( TypeId :: of :: < Self > ( ) ) . or_default ( ) ) ;
433
449
}
450
+
451
+ #[ cfg( feature = "hot-rebuild" ) ]
452
+ pub fn export_to < P : Into < PathBuf > > ( path : P ) {
453
+ let mut handles = crate :: prelude:: MATERIAL_EXPORTS . write ( ) . unwrap ( ) ;
454
+ handles. insert ( std:: any:: TypeId :: of :: < Self > ( ) , path. into ( ) ) ;
455
+ }
434
456
}
0 commit comments