Skip to content

Commit 6463391

Browse files
committed
Store AssetSource as Arc in AssetSources.
1 parent 7ad5fb7 commit 6463391

File tree

5 files changed

+75
-46
lines changed

5 files changed

+75
-46
lines changed

crates/bevy_asset/src/io/source.rs

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,15 @@ impl AssetSourceBuilder {
165165
}
166166
}
167167

168-
/// Builds a new [`AssetSource`] with the given `id`. If `watch` is true, the unprocessed source will watch for changes.
169-
/// If `watch_processed` is true, the processed source will watch for changes.
170-
pub fn build(
168+
/// Builds a new [`AssetSource`] with the given `id`. If `watch` is true, the unprocessed source
169+
/// will watch for changes. If `watch_processed` is true, the processed source will watch for
170+
/// changes. If `processing_state` is [`Some`], the processed reader will be gated on the state.
171+
pub(crate) fn build(
171172
&mut self,
172173
id: AssetSourceId<'static>,
173174
watch: bool,
174175
watch_processed: bool,
176+
processing_state: Option<Arc<ProcessingState>>,
175177
) -> AssetSource {
176178
let reader = self.reader.as_mut()();
177179
let writer = self.writer.as_mut().and_then(|w| w(false));
@@ -222,6 +224,13 @@ impl AssetSourceBuilder {
222224
}
223225
}
224226
}
227+
228+
if source.should_process()
229+
&& let Some(processing_state) = processing_state
230+
{
231+
source.gate_on_processor(processing_state);
232+
}
233+
225234
source
226235
}
227236

@@ -355,25 +364,41 @@ impl AssetSourceBuilders {
355364
}
356365
}
357366

358-
/// Builds a new [`AssetSources`] collection. If `watch` is true, the unprocessed sources will watch for changes.
359-
/// If `watch_processed` is true, the processed sources will watch for changes.
360-
pub fn build_sources(&mut self, watch: bool, watch_processed: bool) -> AssetSources {
367+
/// Builds a new [`AssetSources`] collection. If `watch` is true, the unprocessed sources will
368+
/// watch for changes. If `watch_processed` is true, the processed sources will watch for
369+
/// changes. If `processing_state` is [`Some`], the processed readers will be gated on the
370+
/// processing state.
371+
pub(crate) fn build_sources(
372+
&mut self,
373+
watch: bool,
374+
watch_processed: bool,
375+
processing_state: Option<Arc<ProcessingState>>,
376+
) -> AssetSources {
361377
let mut sources = <HashMap<_, _>>::default();
362378
for (id, source) in &mut self.sources {
363379
let source = source.build(
364380
AssetSourceId::Name(id.clone_owned()),
365381
watch,
366382
watch_processed,
383+
processing_state.clone(),
367384
);
368-
sources.insert(id.clone_owned(), source);
385+
sources.insert(id.clone_owned(), Arc::new(source));
369386
}
370387

371388
AssetSources {
372389
sources,
373390
default: self
374391
.default
375392
.as_mut()
376-
.map(|p| p.build(AssetSourceId::Default, watch, watch_processed))
393+
.map(|p| {
394+
p.build(
395+
AssetSourceId::Default,
396+
watch,
397+
watch_processed,
398+
processing_state.clone(),
399+
)
400+
})
401+
.map(Arc::new)
377402
.expect(MISSING_DEFAULT_SOURCE),
378403
}
379404
}
@@ -591,60 +616,43 @@ impl AssetSource {
591616

592617
/// A collection of [`AssetSource`]s.
593618
pub struct AssetSources {
594-
sources: HashMap<CowArc<'static, str>, AssetSource>,
595-
default: AssetSource,
619+
sources: HashMap<CowArc<'static, str>, Arc<AssetSource>>,
620+
default: Arc<AssetSource>,
596621
}
597622

598623
impl AssetSources {
599624
/// Gets the [`AssetSource`] with the given `id`, if it exists.
600-
pub fn get<'a, 'b>(
601-
&'a self,
602-
id: impl Into<AssetSourceId<'b>>,
603-
) -> Result<&'a AssetSource, MissingAssetSourceError> {
625+
pub fn get<'a>(
626+
&self,
627+
id: impl Into<AssetSourceId<'a>>,
628+
) -> Result<Arc<AssetSource>, MissingAssetSourceError> {
604629
match id.into().into_owned() {
605-
AssetSourceId::Default => Ok(&self.default),
630+
AssetSourceId::Default => Ok(self.default.clone()),
606631
AssetSourceId::Name(name) => self
607632
.sources
608633
.get(&name)
634+
.cloned()
609635
.ok_or(MissingAssetSourceError(AssetSourceId::Name(name))),
610636
}
611637
}
612638

613639
/// Iterates all asset sources in the collection (including the default source).
614-
pub fn iter(&self) -> impl Iterator<Item = &AssetSource> {
640+
pub fn iter(&self) -> impl Iterator<Item = &Arc<AssetSource>> {
615641
self.sources.values().chain(Some(&self.default))
616642
}
617643

618-
/// Mutably iterates all asset sources in the collection (including the default source).
619-
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut AssetSource> {
620-
self.sources.values_mut().chain(Some(&mut self.default))
621-
}
622-
623644
/// Iterates all processed asset sources in the collection (including the default source).
624-
pub fn iter_processed(&self) -> impl Iterator<Item = &AssetSource> {
645+
pub fn iter_processed(&self) -> impl Iterator<Item = &Arc<AssetSource>> {
625646
self.iter().filter(|p| p.should_process())
626647
}
627648

628-
/// Mutably iterates all processed asset sources in the collection (including the default source).
629-
pub fn iter_processed_mut(&mut self) -> impl Iterator<Item = &mut AssetSource> {
630-
self.iter_mut().filter(|p| p.should_process())
631-
}
632-
633649
/// Iterates over the [`AssetSourceId`] of every [`AssetSource`] in the collection (including the default source).
634650
pub fn ids(&self) -> impl Iterator<Item = AssetSourceId<'static>> + '_ {
635651
self.sources
636652
.keys()
637653
.map(|k| AssetSourceId::Name(k.clone_owned()))
638654
.chain(Some(AssetSourceId::Default))
639655
}
640-
641-
/// This will cause processed [`AssetReader`](crate::io::AssetReader) futures (such as [`AssetReader::read`](crate::io::AssetReader::read)) to wait until
642-
/// the [`AssetProcessor`](crate::AssetProcessor) has finished processing the requested asset.
643-
pub(crate) fn gate_on_processor(&mut self, processing_state: Arc<ProcessingState>) {
644-
for source in self.iter_processed_mut() {
645-
source.gate_on_processor(processing_state.clone());
646-
}
647-
}
648656
}
649657

650658
/// An error returned when an [`AssetSource`] does not exist for a given id.

crates/bevy_asset/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ impl Plugin for AssetPlugin {
372372
match self.mode {
373373
AssetMode::Unprocessed => {
374374
let mut builders = app.world_mut().resource_mut::<AssetSourceBuilders>();
375-
let sources = builders.build_sources(watch, false);
375+
let sources = builders.build_sources(watch, false, None);
376376

377377
app.insert_resource(AssetServer::new_with_meta_check(
378378
Arc::new(sources),
@@ -402,7 +402,7 @@ impl Plugin for AssetPlugin {
402402
.add_systems(bevy_app::Startup, AssetProcessor::start);
403403
} else {
404404
let mut builders = app.world_mut().resource_mut::<AssetSourceBuilders>();
405-
let sources = builders.build_sources(false, watch);
405+
let sources = builders.build_sources(false, watch, None);
406406
app.insert_resource(AssetServer::new_with_meta_check(
407407
Arc::new(sources),
408408
AssetServerMode::Processed,

crates/bevy_asset/src/loader_builders.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ impl<'builder, 'reader, T> NestedLoader<'_, '_, T, Immediate<'builder, 'reader>>
407407
.write_infos()
408408
.stats
409409
.started_load_tasks += 1;
410+
let source;
410411
let (mut meta, loader, mut reader) = if let Some(reader) = self.mode.reader {
411412
let loader = if let Some(asset_type_id) = asset_type_id {
412413
self.load_context
@@ -430,10 +431,18 @@ impl<'builder, 'reader, T> NestedLoader<'_, '_, T, Immediate<'builder, 'reader>>
430431
let meta = loader.default_meta();
431432
(meta, loader, ReaderRef::Borrowed(reader))
432433
} else {
434+
source = self
435+
.load_context
436+
.asset_server
437+
.get_source(path.source())
438+
.map_err(|err| LoadDirectError::LoadError {
439+
dependency: path.clone(),
440+
error: err.into(),
441+
})?;
433442
let (meta, loader, reader) = self
434443
.load_context
435444
.asset_server
436-
.get_meta_loader_and_reader(path, asset_type_id)
445+
.get_meta_loader_and_reader(path, asset_type_id, &source)
437446
.await
438447
.map_err(|error| LoadDirectError::LoadError {
439448
dependency: path.clone(),

crates/bevy_asset/src/processor/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@ impl AssetProcessor {
139139
watch_processed: bool,
140140
) -> (Self, Arc<AssetSources>) {
141141
let state = Arc::new(ProcessingState::new());
142-
let mut sources = sources.build_sources(true, watch_processed);
143-
sources.gate_on_processor(state.clone());
142+
let sources = sources.build_sources(true, watch_processed, Some(state.clone()));
144143
let sources = Arc::new(sources);
145144

146145
let data = Arc::new(AssetProcessorData::new(sources.clone(), state));
@@ -176,7 +175,7 @@ impl AssetProcessor {
176175
pub fn get_source<'a>(
177176
&self,
178177
id: impl Into<AssetSourceId<'a>>,
179-
) -> Result<&AssetSource, MissingAssetSourceError> {
178+
) -> Result<Arc<AssetSource>, MissingAssetSourceError> {
180179
self.data.sources.get(id.into())
181180
}
182181

@@ -298,7 +297,7 @@ impl AssetProcessor {
298297
return;
299298
};
300299
processor
301-
.handle_asset_source_event(source, event, &sender)
300+
.handle_asset_source_event(&source, event, &sender)
302301
.await;
303302
}
304303
})
@@ -374,7 +373,9 @@ impl AssetProcessor {
374373
let Ok(source) = processor.get_source(source_id) else {
375374
return;
376375
};
377-
processor.process_asset(source, path, new_task_sender).await;
376+
processor
377+
.process_asset(&source, path, new_task_sender)
378+
.await;
378379
// If the channel gets closed, that's ok. Just ignore it.
379380
let _ = task_finished_sender.send(()).await;
380381
})

crates/bevy_asset/src/server/mod.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ impl AssetServer {
182182
pub fn get_source<'a>(
183183
&self,
184184
source: impl Into<AssetSourceId<'a>>,
185-
) -> Result<&AssetSource, MissingAssetSourceError> {
185+
) -> Result<Arc<AssetSource>, MissingAssetSourceError> {
186186
self.data.sources.get(source.into())
187187
}
188188

@@ -711,8 +711,19 @@ impl AssetServer {
711711

712712
let path = path.into_owned();
713713
let path_clone = path.clone();
714+
let source = self.get_source(path.source()).inspect_err(|e| {
715+
// If there was an input handle, a "load" operation has already started, so we must
716+
// produce a "failure" event, if we cannot find the source.
717+
if let Some(handle) = &input_handle {
718+
self.send_asset_event(InternalAssetEvent::Failed {
719+
index: handle.try_into().unwrap(),
720+
path: path.clone_owned(),
721+
error: e.clone().into(),
722+
});
723+
}
724+
})?;
714725
let (mut meta, loader, mut reader) = self
715-
.get_meta_loader_and_reader(&path_clone, input_handle_type_id)
726+
.get_meta_loader_and_reader(&path_clone, input_handle_type_id, &source)
716727
.await
717728
.inspect_err(|e| {
718729
// if there was an input handle, a "load" operation has already started, so we must produce a "failure" event, if
@@ -1418,6 +1429,7 @@ impl AssetServer {
14181429
&'a self,
14191430
asset_path: &'a AssetPath<'_>,
14201431
asset_type_id: Option<TypeId>,
1432+
source: &'a AssetSource,
14211433
) -> Result<
14221434
(
14231435
Box<dyn AssetMetaDyn>,
@@ -1426,7 +1438,6 @@ impl AssetServer {
14261438
),
14271439
AssetLoadError,
14281440
> {
1429-
let source = self.get_source(asset_path.source())?;
14301441
// NOTE: We grab the asset byte reader first to ensure this is transactional for AssetReaders like ProcessorGatedReader
14311442
// The asset byte reader will "lock" the processed asset, preventing writes for the duration of the lock.
14321443
// Then the meta reader, if meta exists, will correspond to the meta for the current "version" of the asset.

0 commit comments

Comments
 (0)