engine/resources/
loader.rs1use platform::Platform;
6
7use crate::{allocators::LinearAllocator, collections::Queue};
8
9use super::{
10 file_reader::{FileReadError, FileReader},
11 ChunkData, ResourceDatabase, SpriteChunkData,
12};
13
14#[derive(Debug, PartialEq, Eq)]
15enum LoadCategory {
16 Chunk,
17 SpriteChunk,
18}
19
20#[derive(Debug)]
21struct ChunkReadInfo {
22 chunk_index: u32,
23 category: LoadCategory,
24}
25
26pub struct ResourceLoader {
38 file_reader: FileReader,
39 queued_reads: Queue<'static, ChunkReadInfo>,
40}
41
42impl ResourceLoader {
43 #[track_caller]
48 pub fn new(
49 arena: &'static LinearAllocator,
50 file_reader: FileReader,
51 resource_db: &ResourceDatabase,
52 ) -> Option<ResourceLoader> {
53 assert!(
54 file_reader.staging_buffer_size() as u64 >= resource_db.largest_chunk_source(),
55 "resource loader file reader's staging buffer size is smaller than the resource database's largest chunk source",
56 );
57
58 let total_chunks = resource_db.chunks.array_len() + resource_db.sprite_chunks.array_len();
59 Some(ResourceLoader {
60 file_reader,
61 queued_reads: Queue::new(arena, total_chunks)?,
62 })
63 }
64
65 pub fn queue_chunk(&mut self, chunk_index: u32, resources: &ResourceDatabase) {
71 self.queue_load(chunk_index, LoadCategory::Chunk, resources);
72 }
73
74 pub fn queue_sprite_chunk(&mut self, chunk_index: u32, resources: &ResourceDatabase) {
80 self.queue_load(chunk_index, LoadCategory::SpriteChunk, resources);
81 }
82
83 fn queue_load(
84 &mut self,
85 chunk_index: u32,
86 category: LoadCategory,
87 resources: &ResourceDatabase,
88 ) {
89 profiling::function_scope!();
90
91 if (category == LoadCategory::Chunk && resources.chunks.get(chunk_index).is_some())
93 || (category == LoadCategory::SpriteChunk
94 && resources.sprite_chunks.get(chunk_index).is_some())
95 {
96 return;
97 }
98
99 let already_queued =
101 |read: &ChunkReadInfo| read.chunk_index == chunk_index && read.category == category;
102 if self.queued_reads.iter().any(already_queued) {
103 return;
104 }
105
106 let chunk_source = match category {
107 LoadCategory::Chunk => &resources.chunk_descriptors[chunk_index as usize].source_bytes,
108 LoadCategory::SpriteChunk => {
109 &resources.sprite_chunk_descriptors[chunk_index as usize].source_bytes
110 }
111 };
112 let first_byte = resources.chunk_data_offset + chunk_source.start;
113 let size = (chunk_source.end - chunk_source.start) as usize;
114 if !self.queued_reads.is_full() && self.file_reader.push_read(first_byte, size) {
116 self.queued_reads
117 .push_back(ChunkReadInfo {
118 chunk_index,
119 category,
120 })
121 .unwrap();
122 }
123 }
124
125 pub fn dispatch_reads(&mut self, platform: &dyn Platform) {
127 self.file_reader.dispatch_reads(platform);
128 }
129
130 pub fn finish_reads(
136 &mut self,
137 resources: &mut ResourceDatabase,
138 platform: &dyn Platform,
139 max_reads: usize,
140 ) {
141 profiling::function_scope!();
142 for _ in 0..max_reads {
143 let read_result = self.file_reader.pop_read(platform, false, |source_bytes| {
144 profiling::scope!("process file read");
145 let ChunkReadInfo {
146 chunk_index,
147 category,
148 ..
149 } = self.queued_reads.pop_front().unwrap();
150
151 match category {
152 LoadCategory::Chunk => {
153 let desc = &resources.chunk_descriptors[chunk_index as usize];
154 let init_fn = || Some(ChunkData::empty());
155 if let Some(dst) = resources.chunks.insert(chunk_index, init_fn) {
156 dst.update(desc, source_bytes);
157 }
158 }
159
160 LoadCategory::SpriteChunk => {
161 let desc = &resources.sprite_chunk_descriptors[chunk_index as usize];
162 let init_fn = || SpriteChunkData::empty(platform);
163 if let Some(dst) = resources.sprite_chunks.insert(chunk_index, init_fn) {
164 dst.update(desc, source_bytes, platform);
165 }
166 }
167 }
168 });
169
170 match read_result {
171 Ok(_) => {}
172 Err(FileReadError::NoReadsQueued | FileReadError::WouldBlock) => break,
173 Err(err) => {
174 let info = self.queued_reads.pop_front().unwrap();
175 platform.println(format_args!(
176 "resource loader read ({info:?}) failed: {err:?}"
177 ));
178 }
179 }
180 }
181 }
182}