1use std::{
2 rc::Rc,
3 sync::{Arc, Mutex},
4};
5
6use wgpu::{CommandEncoder, Device, Queue};
7
8use crate::window::TargetProperties;
9
10pub mod compute;
11pub mod drawable;
12mod primary_draw_pass;
13pub mod shader;
14pub mod vertex;
15pub use primary_draw_pass::PrimaryDrawPass;
16
17pub trait RenderPass {
18 fn render(
19 &mut self,
20 device: &Device,
21 encoder: &mut CommandEncoder,
22 queue: &Queue,
23 target: &wgpu::TextureView,
24 global_bind_group: &wgpu::BindGroup,
25 bind_group_layout: &wgpu::BindGroupLayout,
26 target_properties: &TargetProperties,
27 );
28
29 fn init(
30 &mut self,
31 device: &Device,
32 bind_group_layout: &wgpu::BindGroupLayout,
33 target_properties: &TargetProperties,
34 );
35}
36
37pub trait RenderPipeline {
38 fn render(
39 &mut self,
40 device: &Device,
41 encoder: &mut CommandEncoder,
42 queue: &Queue,
43 target: &wgpu::TextureView,
44 target_properties: &TargetProperties,
45 );
46
47 fn init(
48 &mut self,
49 device: &Device,
50 bind_group_layout: &wgpu::BindGroupLayout,
51 target_properties: &TargetProperties,
52 );
53}
54
55pub struct DefaultRenderPipeline {
56 render_passes: Vec<Arc<Mutex<dyn RenderPass>>>,
57 global_bind_group: Box<dyn GlobalBindGroup>,
58 initialized: bool,
59 #[allow(dead_code)]
60 name: String,
61}
62
63impl DefaultRenderPipeline {
64 pub fn new(global_bind_group: Box<dyn GlobalBindGroup>, name: &str) -> Self {
65 DefaultRenderPipeline {
66 render_passes: Vec::new(),
67 initialized: false,
68 global_bind_group,
69 name: name.to_string(),
70 }
71 }
72
73 pub fn add_render_pass(&mut self, render_pass: Arc<Mutex<dyn RenderPass>>) {
74 self.render_passes.push(render_pass);
75 }
76}
77
78impl RenderPipeline for DefaultRenderPipeline {
79 fn render(
80 &mut self,
81 device: &Device,
82 encoder: &mut CommandEncoder,
83 queue: &Queue,
84 target: &wgpu::TextureView,
85 target_properties: &TargetProperties,
86 ) {
87 if !self.initialized {
88 let bind_group_layout = self.global_bind_group.get_layout(device);
89 self.init(device, &bind_group_layout, target_properties);
90 self.initialized = true;
91 }
92 self.global_bind_group.pre_render(device, queue);
93 for render_pass in &mut self.render_passes {
94 render_pass.lock().unwrap().render(
95 device,
96 encoder,
97 queue,
98 target,
99 &self.global_bind_group.get_group(),
100 self.global_bind_group.get_layout(device).as_ref(),
101 target_properties,
102 )
103 }
104 }
105
106 fn init(
107 &mut self,
108 device: &Device,
109 bind_group_layout: &wgpu::BindGroupLayout,
110 target_properties: &TargetProperties,
111 ) {
112 self.global_bind_group.init(device);
113 for pass in self.render_passes.iter_mut() {
114 pass.lock()
115 .unwrap()
116 .init(device, bind_group_layout, target_properties);
117 }
118 }
119}
120
121pub trait GlobalBindGroup {
123 fn get_layout(&mut self, device: &wgpu::Device) -> Rc<wgpu::BindGroupLayout>;
124 fn init(&mut self, device: &wgpu::Device);
125 fn get_group(&mut self) -> Rc<wgpu::BindGroup>;
126 fn pre_render(&mut self, device: &wgpu::Device, queue: &wgpu::Queue);
127}