1use crate::*;
2use std::sync::atomic::{AtomicUsize, Ordering};
3use winit::window::Window;
4
5static MAXID: AtomicUsize = AtomicUsize::new(0);
6
7impl RenderID {
8 #[inline(always)]
10 pub fn gen() -> Self { RenderID(MAXID.fetch_add(1, Ordering::SeqCst)) }
11}
12
13async fn init_default_device(
14 window: Option<Arc<Window>>,
15) -> (DeviceHandler, Option<WindowHandler>) {
16 #[cfg(not(feature = "webgl"))]
17 let backends = Backends::PRIMARY;
18 #[cfg(feature = "webgl")]
19 let backends = Backends::all();
20 let instance = Instance::new(InstanceDescriptor {
21 backends,
22 ..Default::default()
23 });
24
25 let surface = window.as_ref().map(|window| {
26 instance
27 .create_surface(Arc::clone(window))
28 .expect("Failed to create `Surface`")
29 });
30
31 let adapter = instance
32 .request_adapter(&RequestAdapterOptions {
33 #[cfg(not(feature = "webgl"))]
34 power_preference: PowerPreference::HighPerformance,
35 #[cfg(feature = "webgl")]
36 power_preference: PowerPreference::LowPower,
37 compatible_surface: surface.as_ref(),
38 force_fallback_adapter: false,
39 })
40 .await
41 .expect("Failed to find an appropriate adapter");
42
43 let (device, queue) = adapter
44 .request_device(
45 &DeviceDescriptor {
46 required_features: Default::default(),
47 memory_hints: MemoryHints::Performance,
48 #[cfg(not(feature = "webgl"))]
49 required_limits: Limits::downlevel_defaults().using_resolution(adapter.limits()),
50 #[cfg(feature = "webgl")]
51 required_limits: Limits::downlevel_webgl2_defaults(),
52 label: None,
53 },
54 None,
55 )
56 .await
57 .expect("Failed to create device");
58 let device_handler = DeviceHandler {
59 adapter: Arc::new(adapter),
60 device: Arc::new(device),
61 queue: Arc::new(queue),
62 };
63 let window_handler = window.map(|window| WindowHandler {
64 window,
65 surface: Arc::new(surface.unwrap()),
66 });
67 (device_handler, window_handler)
68}
69
70impl DeviceHandler {
71 #[inline(always)]
73 pub const fn new(
74 adapter: Arc<Adapter>,
75 device: Arc<Device>,
76 queue: Arc<Queue>,
77 ) -> DeviceHandler {
78 DeviceHandler {
79 adapter,
80 device,
81 queue,
82 }
83 }
84 #[inline(always)]
86 pub const fn adapter(&self) -> &Arc<Adapter> { &self.adapter }
87 #[inline(always)]
89 pub const fn device(&self) -> &Arc<Device> { &self.device }
90 #[inline(always)]
92 pub const fn queue(&self) -> &Arc<Queue> { &self.queue }
93
94 pub async fn default_device() -> Self { init_default_device(None).await.0 }
96}
97
98impl Default for StudioConfig {
99 #[inline(always)]
100 fn default() -> StudioConfig {
101 StudioConfig {
102 background: Color::BLACK,
103 camera: Camera::default(),
104 lights: vec![Light::default()],
105 }
106 }
107}
108
109impl Default for BackendBufferConfig {
110 #[inline(always)]
111 fn default() -> BackendBufferConfig {
112 BackendBufferConfig {
113 depth_test: true,
114 sample_count: 1,
115 }
116 }
117}
118
119impl Default for RenderTextureConfig {
120 #[inline(always)]
121 fn default() -> RenderTextureConfig {
122 RenderTextureConfig {
123 canvas_size: (1024, 768),
124 format: TextureFormat::Rgba8Unorm,
125 }
126 }
127}
128
129impl RenderTextureConfig {
130 #[inline(always)]
132 pub fn compatible_surface_config(self) -> SurfaceConfiguration {
133 SurfaceConfiguration {
134 usage: TextureUsages::RENDER_ATTACHMENT,
135 format: self.format,
136 width: self.canvas_size.0,
137 height: self.canvas_size.1,
138 alpha_mode: CompositeAlphaMode::Auto,
139 present_mode: PresentMode::Fifo,
140 view_formats: Vec::new(),
141 desired_maximum_frame_latency: 2,
142 }
143 }
144}
145
146impl SceneDescriptor {
147 #[inline(always)]
159 pub fn camera_buffer(&self, device: &Device) -> BufferHandler {
160 let (width, height) = self.render_texture.canvas_size;
161 let as_rat = width as f64 / height as f64;
162 self.studio.camera.buffer(as_rat, device)
163 }
164
165 #[inline(always)]
182 pub fn lights_buffer(&self, device: &Device) -> BufferHandler {
183 let mut light_vec: Vec<_> = self.studio.lights.iter().map(Light::light_info).collect();
184 light_vec.resize(LIGHT_MAX, LightInfo::zeroed());
185 BufferHandler::from_slice(&light_vec, device, BufferUsages::UNIFORM)
186 }
187
188 #[inline(always)]
189 fn sampling_buffer(
190 device: &Device,
191 render_texture: RenderTextureConfig,
192 sample_count: u32,
193 ) -> Texture {
194 device.create_texture(&TextureDescriptor {
195 size: Extent3d {
196 width: render_texture.canvas_size.0,
197 height: render_texture.canvas_size.1,
198 depth_or_array_layers: 1,
199 },
200 mip_level_count: 1,
201 sample_count,
202 dimension: TextureDimension::D2,
203 format: render_texture.format,
204 usage: TextureUsages::RENDER_ATTACHMENT,
205 view_formats: &[],
206 label: None,
207 })
208 }
209
210 #[inline(always)]
211 fn depth_texture(device: &Device, size: (u32, u32), sample_count: u32) -> Texture {
212 device.create_texture(&TextureDescriptor {
213 size: Extent3d {
214 width: size.0,
215 height: size.1,
216 depth_or_array_layers: 1,
217 },
218 mip_level_count: 1,
219 sample_count,
220 dimension: TextureDimension::D2,
221 format: TextureFormat::Depth32Float,
222 usage: TextureUsages::RENDER_ATTACHMENT,
223 view_formats: &[],
224 label: None,
225 })
226 }
227
228 fn backend_buffers(&self, device: &Device) -> (Option<Texture>, Option<Texture>) {
229 let foward_depth = if self.backend_buffer.depth_test {
230 Some(Self::depth_texture(
231 device,
232 self.render_texture.canvas_size,
233 self.backend_buffer.sample_count,
234 ))
235 } else {
236 None
237 };
238 let sampling_buffer = if self.backend_buffer.sample_count > 1 {
239 Some(Self::sampling_buffer(
240 device,
241 self.render_texture,
242 self.backend_buffer.sample_count,
243 ))
244 } else {
245 None
246 };
247 (foward_depth, sampling_buffer)
248 }
249}
250
251#[derive(Debug)]
255pub struct SceneDescriptorMut<'a>(&'a mut Scene);
256
257impl<'a> std::ops::Deref for SceneDescriptorMut<'a> {
258 type Target = SceneDescriptor;
259 #[inline(always)]
260 fn deref(&self) -> &SceneDescriptor { &self.0.scene_desc }
261}
262
263impl<'a> std::ops::DerefMut for SceneDescriptorMut<'a> {
264 #[inline(always)]
265 fn deref_mut(&mut self) -> &mut SceneDescriptor { &mut self.0.scene_desc }
266}
267
268impl<'a> Drop for SceneDescriptorMut<'a> {
269 fn drop(&mut self) {
270 let (forward_depth, sampling_buffer) = self.backend_buffers(self.0.device());
271 self.0.foward_depth = forward_depth;
272 self.0.sampling_buffer = sampling_buffer;
273 }
274}
275
276impl Scene {
277 #[inline(always)]
278 fn camera_bgl_entry() -> PreBindGroupLayoutEntry {
279 PreBindGroupLayoutEntry {
280 visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
281 ty: BindingType::Buffer {
282 ty: BufferBindingType::Uniform,
283 has_dynamic_offset: false,
284 min_binding_size: None,
285 },
286 count: None,
287 }
288 }
289
290 #[inline(always)]
291 fn lights_bgl_entry() -> PreBindGroupLayoutEntry {
292 PreBindGroupLayoutEntry {
293 visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
294 ty: BindingType::Buffer {
295 ty: BufferBindingType::Uniform,
296 has_dynamic_offset: false,
297 min_binding_size: None,
298 },
299 count: None,
300 }
301 }
302
303 #[inline(always)]
304 fn scene_bgl_entry() -> PreBindGroupLayoutEntry {
305 PreBindGroupLayoutEntry {
306 visibility: ShaderStages::VERTEX | ShaderStages::FRAGMENT,
307 ty: BindingType::Buffer {
308 ty: BufferBindingType::Uniform,
309 has_dynamic_offset: false,
310 min_binding_size: None,
311 },
312 count: None,
313 }
314 }
315
316 #[inline(always)]
317 fn init_scene_bind_group_layout(device: &Device) -> BindGroupLayout {
318 bind_group_util::create_bind_group_layout(
319 device,
320 &[
321 Self::camera_bgl_entry(),
322 Self::lights_bgl_entry(),
323 Self::scene_bgl_entry(),
324 ],
325 )
326 }
327
328 #[inline(always)]
332 pub fn new(device_handler: DeviceHandler, scene_desc: &SceneDescriptor) -> Scene {
333 let device = device_handler.device();
334 let (foward_depth, sampling_buffer) = scene_desc.backend_buffers(device);
335 let bind_group_layout = Self::init_scene_bind_group_layout(device);
336 Scene {
337 objects: Default::default(),
338 bind_group_layout,
339 foward_depth,
340 sampling_buffer,
341 clock: TimeInstant::now(),
342 scene_desc: scene_desc.clone(),
343 device_handler,
344 }
345 }
346
347 pub async fn from_default_device(scene_desc: &SceneDescriptor) -> Scene {
351 Scene::new(DeviceHandler::default_device().await, scene_desc)
352 }
353
354 #[inline(always)]
359 pub fn compatible_texture(&self) -> Texture {
360 let config = self.scene_desc.render_texture;
361 self.device().create_texture(&TextureDescriptor {
362 label: None,
363 size: Extent3d {
364 width: config.canvas_size.0,
365 height: config.canvas_size.1,
366 depth_or_array_layers: 1,
367 },
368 mip_level_count: 1,
369 sample_count: 1,
370 dimension: TextureDimension::D2,
371 format: config.format,
372 view_formats: &[],
373 usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::COPY_SRC,
374 })
375 }
376
377 #[inline(always)]
379 pub const fn device_handler(&self) -> &DeviceHandler { &self.device_handler }
380
381 #[inline(always)]
383 pub const fn device(&self) -> &Arc<Device> { &self.device_handler.device }
384
385 #[inline(always)]
387 pub const fn queue(&self) -> &Arc<Queue> { &self.device_handler.queue }
388
389 #[inline(always)]
391 pub fn elapsed(&self) -> std::time::Duration { self.clock.elapsed() }
392
393 #[inline(always)]
395 pub const fn descriptor(&self) -> &SceneDescriptor { &self.scene_desc }
396
397 #[inline(always)]
404 pub fn descriptor_mut(&mut self) -> SceneDescriptorMut<'_> { SceneDescriptorMut(self) }
405
406 #[inline(always)]
408 pub const fn studio_config(&self) -> &StudioConfig { &self.scene_desc.studio }
409
410 #[inline(always)]
412 pub fn studio_config_mut(&mut self) -> &mut StudioConfig { &mut self.scene_desc.studio }
413
414 #[inline(always)]
416 pub const fn bind_group_layout(&self) -> &BindGroupLayout { &self.bind_group_layout }
417
418 #[inline(always)]
430 pub fn camera_buffer(&self) -> BufferHandler { self.scene_desc.camera_buffer(self.device()) }
431
432 #[inline(always)]
449 pub fn lights_buffer(&self) -> BufferHandler { self.scene_desc.lights_buffer(self.device()) }
450
451 #[inline(always)]
464 pub fn scene_status_buffer(&self) -> BufferHandler {
465 let bk = self.scene_desc.studio.background;
466 let size = self.scene_desc.render_texture.canvas_size;
467 let scene_info = SceneInfo {
468 background_color: [bk.r as f32, bk.g as f32, bk.b as f32, bk.a as f32],
469 resolution: [size.0, size.1],
470 time: self.elapsed().as_secs_f32(),
471 num_of_lights: self.scene_desc.studio.lights.len() as u32,
472 };
473 BufferHandler::from_slice(&[scene_info], self.device(), BufferUsages::UNIFORM)
474 }
475
476 #[inline(always)]
501 pub fn scene_bind_group(&self) -> BindGroup {
502 bind_group_util::create_bind_group(
503 self.device(),
504 &self.bind_group_layout,
505 vec![
506 self.camera_buffer().binding_resource(),
507 self.lights_buffer().binding_resource(),
508 self.scene_status_buffer().binding_resource(),
509 ],
510 )
511 }
512
513 #[inline(always)]
518 pub fn add_object<R: Rendered>(&mut self, object: &R) -> bool {
519 let render_object = object.render_object(self);
520 self.objects
521 .insert(object.render_id(), render_object)
522 .is_none()
523 }
524 #[inline(always)]
528 pub fn set_visibility<R: Rendered>(&mut self, object: &R, visible: bool) -> bool {
529 self.objects
530 .get_mut(&object.render_id())
531 .map(|obj| obj.visible = visible)
532 .is_some()
533 }
534 #[inline(always)]
539 pub fn add_objects<'a, R, I>(&mut self, objects: I) -> bool
540 where
541 R: 'a + Rendered,
542 I: IntoIterator<Item = &'a R>, {
543 let closure = move |flag, object| flag && self.add_object(object);
544 objects.into_iter().fold(true, closure)
545 }
546 #[inline(always)]
550 pub fn remove_object<R: Rendered>(&mut self, object: &R) -> bool {
551 self.objects.remove(&object.render_id()).is_some()
552 }
553 #[inline(always)]
557 pub fn remove_objects<'a, R, I>(&mut self, objects: I) -> bool
558 where
559 R: 'a + Rendered,
560 I: IntoIterator<Item = &'a R>, {
561 let closure = move |flag, object| flag && self.remove_object(object);
562 objects.into_iter().fold(true, closure)
563 }
564
565 #[inline(always)]
567 pub fn clear_objects(&mut self) { self.objects.clear() }
568
569 #[inline(always)]
571 pub fn number_of_objects(&self) -> usize { self.objects.len() }
572
573 #[inline(always)]
578 pub fn update_vertex_buffer<R: Rendered>(&mut self, object: &R) -> bool {
579 let (handler, objects) = (&self.device_handler, &mut self.objects);
580 match objects.get_mut(&object.render_id()) {
581 None => false,
582 Some(render_object) => {
583 let (vb, ib) = object.vertex_buffer(handler);
584 render_object.vertex_buffer = vb;
585 render_object.index_buffer = ib;
586 true
587 }
588 }
589 }
590
591 #[inline(always)]
596 pub fn update_vertex_buffers<'a, R, I>(&mut self, objects: I) -> bool
597 where
598 R: 'a + Rendered,
599 I: IntoIterator<Item = &'a R>, {
600 let closure = move |flag, object: &R| flag && self.update_vertex_buffer(object);
601 objects.into_iter().fold(true, closure)
602 }
603
604 #[inline(always)]
609 pub fn update_bind_group<R: Rendered>(&mut self, object: &R) -> bool {
610 let (handler, objects) = (&self.device_handler, &mut self.objects);
611 match objects.get_mut(&object.render_id()) {
612 Some(render_object) => {
613 let bind_group = object.bind_group(handler, &render_object.bind_group_layout);
614 render_object.bind_group = bind_group;
615 true
616 }
617 _ => false,
618 }
619 }
620 #[inline(always)]
625 pub fn update_bind_groups<'a, R, I>(&mut self, objects: I) -> bool
626 where
627 R: 'a + Rendered,
628 I: IntoIterator<Item = &'a R>, {
629 let closure = move |flag, object: &R| flag && self.update_bind_group(object);
630 objects.into_iter().fold(true, closure)
631 }
632 #[inline(always)]
637 pub fn update_pipeline<R: Rendered>(&mut self, object: &R) -> bool {
638 let (handler, objects) = (&self.device_handler, &mut self.objects);
639 match objects.get_mut(&object.render_id()) {
640 Some(render_object) => {
641 let device = handler.device();
642 let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor {
643 bind_group_layouts: &[
644 &self.bind_group_layout,
645 &render_object.bind_group_layout,
646 ],
647 push_constant_ranges: &[],
648 label: None,
649 });
650 render_object.pipeline =
651 object.pipeline(handler, &pipeline_layout, &self.scene_desc);
652 true
653 }
654 _ => false,
655 }
656 }
657 #[inline(always)]
662 pub fn update_pipelines<'a, R, I>(&mut self, objects: I) -> bool
663 where
664 R: 'a + Rendered,
665 I: IntoIterator<Item = &'a R>, {
666 let closure = move |flag, object: &R| flag && self.update_pipeline(object);
667 objects.into_iter().fold(true, closure)
668 }
669 #[inline(always)]
670 fn depth_stencil_attachment_descriptor(
671 depth_view: &TextureView,
672 ) -> RenderPassDepthStencilAttachment<'_> {
673 RenderPassDepthStencilAttachment {
674 view: depth_view,
675 depth_ops: Some(Operations {
676 load: LoadOp::Clear(1.0),
677 store: StoreOp::Store,
678 }),
679 stencil_ops: None,
680 }
681 }
682
683 pub fn render(&self, view: &TextureView) {
685 let bind_group = self.scene_bind_group();
686 let depth_view = self
687 .foward_depth
688 .as_ref()
689 .map(|tex| tex.create_view(&Default::default()));
690 let sampled_view = self
691 .sampling_buffer
692 .as_ref()
693 .map(|tex| tex.create_view(&Default::default()));
694 let mut encoder = self
695 .device()
696 .create_command_encoder(&CommandEncoderDescriptor { label: None });
697 {
698 let (attachment, resolve_target) = match sampled_view.as_ref() {
699 Some(sampled_view) => (sampled_view, Some(view)),
700 None => (view, None),
701 };
702 let mut rpass = encoder.begin_render_pass(&RenderPassDescriptor {
703 color_attachments: &[Some(RenderPassColorAttachment {
704 view: attachment,
705 resolve_target,
706 ops: Operations {
707 load: LoadOp::Clear(self.scene_desc.studio.background),
708 store: StoreOp::Store,
709 },
710 })],
711 depth_stencil_attachment: depth_view
712 .as_ref()
713 .map(Self::depth_stencil_attachment_descriptor),
714 ..Default::default()
715 });
716 rpass.set_bind_group(0, &bind_group, &[]);
717 for (_, object) in &self.objects {
718 if !object.visible {
719 continue;
720 }
721 rpass.set_pipeline(&object.pipeline);
722 rpass.set_bind_group(1, &object.bind_group, &[]);
723 rpass.set_vertex_buffer(0, object.vertex_buffer.buffer.slice(..));
724 match object.index_buffer {
725 Some(ref index_buffer) => {
726 rpass.set_index_buffer(index_buffer.buffer.slice(..), IndexFormat::Uint32);
727 let index_size = index_buffer.size as u32 / size_of::<u32>() as u32;
728 rpass.draw_indexed(0..index_size, 0, 0..1);
729 }
730 None => rpass.draw(
731 0..(object.vertex_buffer.size / object.vertex_buffer.stride) as u32,
732 0..1,
733 ),
734 }
735 }
736 }
737 self.queue().submit(vec![encoder.finish()]);
738 }
739
740 pub async fn render_to_buffer(&self) -> Vec<u8> {
742 let texture = self.compatible_texture();
743 let view = texture.create_view(&Default::default());
744 self.render(&view);
745 let (device, queue) = (self.device(), self.queue());
746
747 let (width, height) = self.scene_desc.render_texture.canvas_size;
748 let size = (width * height * 4) as u64;
749 let buffer = device.create_buffer(&BufferDescriptor {
750 label: None,
751 mapped_at_creation: false,
752 usage: BufferUsages::COPY_DST | BufferUsages::MAP_READ,
753 size,
754 });
755 let mut encoder = device.create_command_encoder(&CommandEncoderDescriptor { label: None });
756 encoder.copy_texture_to_buffer(
757 ImageCopyTexture {
758 texture: &texture,
759 mip_level: 0,
760 origin: Origin3d::ZERO,
761 aspect: TextureAspect::All,
762 },
763 ImageCopyBuffer {
764 buffer: &buffer,
765 layout: ImageDataLayout {
766 offset: 0,
767 bytes_per_row: Some(width * 4),
768 rows_per_image: Some(height),
769 },
770 },
771 Extent3d {
772 width,
773 height,
774 depth_or_array_layers: 1,
775 },
776 );
777 queue.submit(Some(encoder.finish()));
778 let buffer_slice = buffer.slice(..);
779 let (sender, receiver) = futures_intrusive::channel::shared::oneshot_channel();
780 buffer_slice.map_async(MapMode::Read, move |v| sender.send(v).unwrap());
781 device.poll(Maintain::Wait);
782 match receiver.receive().await {
783 Some(Ok(_)) => buffer_slice.get_mapped_range().iter().copied().collect(),
784 Some(Err(e)) => panic!("{}", e),
785 None => panic!("Asynchronous processing fails"),
786 }
787 }
788}
789
790impl WindowScene {
791 pub async fn from_window(window: Arc<Window>, scene_desc: &WindowSceneDescriptor) -> Self {
793 let size = window.inner_size();
794 let got = init_default_device(Some(window)).await;
795 let (device_handler, window_handler) = (got.0, got.1.unwrap());
796 let (device, surface) = (&device_handler.device, &window_handler.surface);
797 let render_texture = RenderTextureConfig {
798 canvas_size: size.into(),
799 format: TextureFormat::Bgra8Unorm,
800 };
801 let config = render_texture.compatible_surface_config();
802 surface.configure(device, &config);
803
804 Self {
805 scene: Scene::new(
806 device_handler,
807 &SceneDescriptor {
808 studio: scene_desc.studio.clone(),
809 backend_buffer: scene_desc.backend_buffer,
810 render_texture,
811 },
812 ),
813 window_handler,
814 }
815 }
816 #[inline(always)]
818 pub const fn window(&self) -> &Arc<Window> { &self.window_handler.window }
819 #[inline(always)]
821 pub const fn surface(&self) -> &Arc<Surface<'_>> { &self.window_handler.surface }
822 pub fn size_alignment(&mut self) {
824 let size = self.window().inner_size();
825 let canvas_size = self.scene.scene_desc.render_texture.canvas_size;
826 if canvas_size != (size.width, size.height) {
827 let mut desc = self.scene.descriptor_mut();
828 desc.render_texture.canvas_size = size.into();
829 let config = desc.render_texture.compatible_surface_config();
830 drop(desc);
831 self.surface().configure(self.device(), &config);
832 }
833 }
834 pub fn render_frame(&mut self) {
836 self.size_alignment();
837 let surface = self.surface();
838 let surface_texture = match surface.get_current_texture() {
839 Ok(got) => got,
840 Err(_) => {
841 let config = self
842 .scene
843 .scene_desc
844 .render_texture
845 .compatible_surface_config();
846 surface.configure(self.device(), &config);
847 surface
848 .get_current_texture()
849 .expect("Failed to acquire next surface texture!")
850 }
851 };
852 let view = surface_texture
853 .texture
854 .create_view(&TextureViewDescriptor::default());
855 self.render(&view);
856 surface_texture.present();
857 }
858}