1use crate::buffer::*;
2use crate::commands::*;
3use crate::crevice::std140::{AsStd140, Std140};
4use crate::limits::Limits;
5use crate::pipeline::*;
6use crate::render_texture::*;
7use crate::renderer::Renderer;
8use crate::shader::*;
9use crate::texture::*;
10use parking_lot::RwLock;
11use std::sync::Arc;
12
13#[derive(Debug)]
15pub enum ResourceId {
16 Buffer(u64),
17 Texture(u64),
18 Pipeline(u64),
19 RenderTexture(u64),
20}
21
22#[derive(Clone, Copy, Default, Debug)]
24pub struct GpuStats {
25 pub draw_calls: usize,
27 pub read_pixels: usize,
29 pub texture_updates: usize,
31 pub texture_creation: usize,
33 pub buffer_updates: usize,
35 pub buffer_creation: usize,
37 pub misc: usize,
39}
40
41impl GpuStats {
42 pub fn total(&self) -> usize {
43 self.draw_calls + self.read_pixels + self.misc
44 }
45}
46
47pub trait DeviceBackend {
49 fn api_name(&self) -> &str;
51
52 fn limits(&self) -> Limits {
54 Default::default()
55 }
56
57 fn stats(&self) -> GpuStats;
59
60 fn reset_stats(&mut self);
62
63 fn create_pipeline(
65 &mut self,
66 vertex_source: &[u8],
67 fragment_source: &[u8],
68 vertex_attrs: &[VertexAttr],
69 texture_locations: &[(u32, String)],
70 options: PipelineOptions,
71 ) -> Result<u64, String>;
72
73 fn create_vertex_buffer(
75 &mut self,
76 attrs: &[VertexAttr],
77 step_mode: VertexStepMode,
78 ) -> Result<u64, String>;
79
80 fn create_index_buffer(&mut self, format: IndexFormat) -> Result<u64, String>;
82
83 fn create_uniform_buffer(&mut self, slot: u32, name: &str) -> Result<u64, String>;
85
86 fn set_buffer_data(&mut self, buffer: u64, data: &[u8]);
88
89 fn render(&mut self, commands: &[Commands], target: Option<u64>);
91
92 fn clean(&mut self, to_clean: &[ResourceId]);
94
95 fn set_size(&mut self, width: u32, height: u32);
97
98 fn set_dpi(&mut self, scale_factor: f64);
100
101 fn create_texture(
103 &mut self,
104 source: TextureSourceKind,
105 info: TextureInfo,
106 ) -> Result<(u64, TextureInfo), String>;
107
108 fn create_render_texture(&mut self, texture_id: u64, info: &TextureInfo)
110 -> Result<u64, String>;
111
112 fn update_texture(
114 &mut self,
115 texture: u64,
116 source: TextureUpdaterSourceKind,
117 opts: TextureUpdate,
118 ) -> Result<(), String>;
119
120 fn read_pixels(
122 &mut self,
123 texture: u64,
124 bytes: &mut [u8],
125 opts: &TextureRead,
126 ) -> Result<(), String>;
127
128 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
129}
130
131#[derive(Debug, Default)]
134pub(crate) struct DropManager {
135 dropped: RwLock<Vec<ResourceId>>,
136}
137
138impl DropManager {
139 pub fn push(&self, id: ResourceId) {
140 self.dropped.write().push(id);
141 }
142
143 pub fn clean(&self) {
144 self.dropped.write().clear();
145 }
146}
147
148pub struct Device {
149 size: (u32, u32),
150 dpi: f64,
151 backend: Box<dyn DeviceBackend>, drop_manager: Arc<DropManager>,
153}
154
155impl Device {
156 pub fn new(backend: Box<dyn DeviceBackend>) -> Result<Self, String> {
157 Ok(Self {
158 backend,
159 size: (1, 1),
160 dpi: 1.0,
161 drop_manager: Arc::new(Default::default()),
162 })
163 }
164
165 #[inline]
166 pub fn limits(&self) -> Limits {
167 self.backend.limits()
168 }
169
170 #[inline]
171 pub fn stats(&self) -> GpuStats {
172 self.backend.stats()
173 }
174
175 #[inline]
176 pub fn size(&self) -> (u32, u32) {
177 self.size
178 }
179
180 #[inline]
181 pub fn set_size(&mut self, width: u32, height: u32) {
182 self.size = (width, height);
183 self.backend.set_size(width, height);
184 }
185
186 #[inline]
187 pub fn dpi(&self) -> f64 {
188 self.dpi
189 }
190
191 #[inline]
192 pub fn set_dpi(&mut self, scale_factor: f64) {
193 self.dpi = scale_factor;
194 self.backend.set_dpi(scale_factor);
195 }
196
197 #[inline]
198 pub fn api_name(&self) -> &str {
199 self.backend.api_name()
200 }
201
202 #[inline]
203 pub fn create_renderer(&self) -> Renderer {
204 Renderer::new(self.size.0, self.size.1)
205 }
206
207 #[inline]
209 pub fn create_pipeline(&mut self) -> PipelineBuilder {
210 PipelineBuilder::new(self)
211 }
212
213 #[inline]
215 pub fn create_texture(&mut self) -> TextureBuilder {
216 TextureBuilder::new(self)
217 }
218
219 #[inline]
221 pub fn create_render_texture(&mut self, width: u32, height: u32) -> RenderTextureBuilder {
222 RenderTextureBuilder::new(self, width, height)
223 }
224
225 #[inline]
227 pub fn create_vertex_buffer(&mut self) -> VertexBufferBuilder {
228 VertexBufferBuilder::new(self)
229 }
230
231 #[inline]
233 pub fn create_index_buffer(&mut self) -> IndexBufferBuilder {
234 IndexBufferBuilder::new(self)
235 }
236
237 #[inline]
239 pub fn create_uniform_buffer(&mut self, slot: u32, name: &str) -> UniformBufferBuilder {
240 UniformBufferBuilder::new(self, slot, name)
241 }
242
243 #[inline]
245 pub fn update_texture<'a>(&'a mut self, texture: &'a mut Texture) -> TextureUpdater<'a> {
246 TextureUpdater::new(self, texture)
247 }
248
249 #[inline]
251 pub fn read_pixels<'a>(&'a mut self, texture: &'a Texture) -> TextureReader<'a> {
252 TextureReader::new(self, texture)
253 }
254
255 #[inline]
256 pub(crate) fn inner_create_pipeline_from_raw(
257 &mut self,
258 vertex_source: &[u8],
259 fragment_source: &[u8],
260 vertex_attrs: &[VertexAttr],
261 texture_locations: &[(u32, String)],
262 options: PipelineOptions,
263 ) -> Result<Pipeline, String> {
264 let stride = vertex_attrs
265 .iter()
266 .fold(0, |acc, data| acc + data.format.bytes()) as usize;
267
268 let id = self.backend.create_pipeline(
269 vertex_source,
270 fragment_source,
271 vertex_attrs,
272 texture_locations,
273 options,
274 )?;
275
276 Ok(Pipeline::new(
277 id,
278 stride,
279 options,
280 self.drop_manager.clone(),
281 ))
282 }
283
284 #[inline]
285 pub(crate) fn inner_create_pipeline(
286 &mut self,
287 vertex_source: &ShaderSource,
288 fragment_source: &ShaderSource,
289 vertex_attrs: &[VertexAttr],
290 texture_locations: &[(u32, String)],
291 options: PipelineOptions,
292 ) -> Result<Pipeline, String> {
293 let api = self.backend.api_name();
294 let vertex = match vertex_source.get_source(api) {
295 Some(v) => v,
296 None => {
297 log::warn!("Vertex shader for api '{api}' not available.");
298 &[]
299 }
300 };
301 let fragment = match fragment_source.get_source(api) {
302 Some(f) => f,
303 None => {
304 log::warn!("Fragment shader for api '{api}' not available.");
305 &[]
306 }
307 };
308 self.inner_create_pipeline_from_raw(
309 vertex,
310 fragment,
311 vertex_attrs,
312 texture_locations,
313 options,
314 )
315 }
316
317 #[inline(always)]
318 pub(crate) fn inner_create_vertex_buffer(
319 &mut self,
320 data: Option<&[f32]>,
321 attrs: &[VertexAttr],
322 step_mode: VertexStepMode,
323 ) -> Result<Buffer, String> {
324 let id = self.backend.create_vertex_buffer(attrs, step_mode)?;
325
326 let buffer = Buffer::new(id, BufferUsage::Vertex, None, self.drop_manager.clone());
327
328 if let Some(d) = data {
329 self.set_buffer_data(&buffer, d);
330 }
331
332 Ok(buffer)
333 }
334
335 #[inline]
336 pub(crate) fn inner_create_index_buffer(
337 &mut self,
338 data: Option<IndexBufferWrapper>,
339 format: IndexFormat,
340 ) -> Result<Buffer, String> {
341 let id = self.backend.create_index_buffer(format)?;
342 let buffer = Buffer::new(id, BufferUsage::Index, None, self.drop_manager.clone());
343 if let Some(d) = data {
344 match d {
345 IndexBufferWrapper::Uint16(s) => self.set_buffer_data(&buffer, s),
346 IndexBufferWrapper::Uint32(s) => self.set_buffer_data(&buffer, s),
347 }
348 }
349 Ok(buffer)
350 }
351
352 #[inline]
353 pub(crate) fn inner_create_uniform_buffer(
354 &mut self,
355 slot: u32,
356 name: &str,
357 data: Option<Vec<u8>>,
358 ) -> Result<Buffer, String> {
359 let id = self.backend.create_uniform_buffer(slot, name)?;
361 let buffer = Buffer::new(
362 id,
363 BufferUsage::Uniform(slot),
364 None,
365 self.drop_manager.clone(),
366 );
367
368 if let Some(d) = data {
369 self.set_buffer_data(&buffer, &d);
370 }
371
372 Ok(buffer)
373 }
374
375 #[inline]
376 pub(crate) fn inner_create_texture(
377 &mut self,
378 source: TextureSourceKind,
379 info: TextureInfo,
380 ) -> Result<Texture, String> {
381 let (id, info) = self.backend.create_texture(source, info)?;
382 Ok(Texture::new(id, info, self.drop_manager.clone()))
383 }
384
385 #[inline]
386 pub(crate) fn inner_create_render_texture(
387 &mut self,
388 info: TextureInfo,
389 ) -> Result<RenderTexture, String> {
390 let (tex_id, info) = self
391 .backend
392 .create_texture(TextureSourceKind::Empty, info)?;
393
394 let id = self.backend.create_render_texture(tex_id, &info)?;
395 let mut texture = Texture::new(tex_id, info, self.drop_manager.clone());
396 texture.is_render_texture = true;
397 Ok(RenderTexture::new(id, texture, self.drop_manager.clone()))
398 }
399
400 #[inline]
401 pub fn render(&mut self, commands: &[Commands]) {
402 self.backend.render(commands, None);
403 }
404
405 #[inline]
406 pub fn render_to(&mut self, target: &RenderTexture, commands: &[Commands]) {
407 self.backend.render(commands, Some(target.id()));
408 }
409
410 #[inline]
411 pub(crate) fn inner_update_texture(
412 &mut self,
413 texture: &mut Texture,
414 source: TextureUpdaterSourceKind,
415 opts: TextureUpdate,
416 ) -> Result<(), String> {
417 self.backend.update_texture(texture.id(), source, opts)
418 }
419
420 #[inline]
421 pub(crate) fn inner_read_pixels(
422 &mut self,
423 texture: &Texture,
424 bytes: &mut [u8],
425 opts: &TextureRead,
426 ) -> Result<(), String> {
427 if cfg!(debug_assertions) {
429 let size = (opts.width * opts.height) as usize;
430 let bpp = opts.format.bytes_per_pixel() as usize;
431 let len = size * bpp;
432 debug_assert!(
433 bytes.len() >= len,
434 "The provided buffer len of {} is less than the required {} when reading pixels from texture {}",
435 bytes.len(),
436 len,
437 texture.id()
438 );
439 }
440
441 self.backend.read_pixels(texture.id(), bytes, opts)
442 }
443
444 #[inline]
445 pub fn clean(&mut self) {
446 self.backend.reset_stats();
447
448 if self.drop_manager.dropped.read().is_empty() {
449 return;
450 }
451
452 self.backend.clean(&self.drop_manager.dropped.read());
453 self.drop_manager.clean();
454 }
455
456 #[inline]
457 pub fn set_buffer_data<T: BufferData>(&mut self, buffer: &Buffer, data: T) {
458 data.upload(self, buffer.id());
459 }
460
461 pub fn downcast_backend<B: DeviceBackend + 'static>(&mut self) -> Result<&mut B, String> {
462 self.backend
463 .as_any_mut()
464 .downcast_mut()
465 .ok_or_else(|| "Invalid backend type".to_string())
466 }
467}
468
469pub trait Uniform: AsStd140 {}
470pub trait BufferData {
471 fn upload(&self, device: &mut Device, id: u64);
472 fn save_as_bytes(&self, _data: &mut Vec<u8>) {}
473}
474
475impl<T> BufferData for &[T]
476where
477 T: bytemuck::Pod,
478{
479 #[inline]
480 fn upload(&self, device: &mut Device, id: u64) {
481 device
482 .backend
483 .set_buffer_data(id, bytemuck::cast_slice(self));
484 }
485
486 fn save_as_bytes(&self, data: &mut Vec<u8>) {
487 data.extend_from_slice(bytemuck::cast_slice(self));
488 }
489}
490
491impl<const N: usize, T> BufferData for &[T; N]
492where
493 T: bytemuck::Pod,
494{
495 #[inline]
496 fn upload(&self, device: &mut Device, id: u64) {
497 device
498 .backend
499 .set_buffer_data(id, bytemuck::cast_slice(self.as_slice()));
500 }
501
502 fn save_as_bytes(&self, data: &mut Vec<u8>) {
503 data.extend_from_slice(bytemuck::cast_slice(self.as_slice()));
504 }
505}
506
507impl<T> BufferData for &Vec<T>
508where
509 T: bytemuck::Pod,
510{
511 #[inline]
512 fn upload(&self, device: &mut Device, id: u64) {
513 device
514 .backend
515 .set_buffer_data(id, bytemuck::cast_slice(self.as_slice()));
516 }
517
518 fn save_as_bytes(&self, data: &mut Vec<u8>) {
519 data.extend_from_slice(bytemuck::cast_slice(self.as_slice()));
520 }
521}
522
523impl<T> BufferData for &T
524where
525 T: Uniform,
526{
527 #[inline]
528 fn upload(&self, device: &mut Device, id: u64) {
529 device
531 .backend
532 .set_buffer_data(id, self.as_std140().as_bytes());
533 }
534
535 fn save_as_bytes(&self, data: &mut Vec<u8>) {
536 data.extend_from_slice(self.as_std140().as_bytes());
537 }
538}
539
540macro_rules! uniform_impl {
541 ( $( $typ:ty, )* ) => {
542 $(
543 impl Uniform for $typ {}
544 )*
545 }
546}
547
548uniform_impl! {
549 notan_math::Vec2,
550 notan_math::Vec3,
551 notan_math::Vec4,
552
553 notan_math::IVec2,
554 notan_math::IVec3,
555 notan_math::IVec4,
556
557 notan_math::UVec2,
558 notan_math::UVec3,
559 notan_math::UVec4,
560
561 notan_math::DVec2,
562 notan_math::DVec3,
563 notan_math::DVec4,
564
565 notan_math::Mat2,
566 notan_math::Mat3,
567 notan_math::Mat4,
568
569 notan_math::DMat2,
570 notan_math::DMat3,
571 notan_math::DMat4,
572}