1mod backend;
4
5use dotrix_math::Mat4;
6use backend::Context as Backend;
7
8use crate::{ Pipeline, Color, Assets, Globals, Window };
9use crate::assets::{ Mesh, Shader };
10use crate::ecs::{ Const, Mut };
11
12pub use backend::{
13 Bindings,
14 PipelineBackend,
15 Sampler,
16 ShaderModule,
17 TextureBuffer,
18 UniformBuffer,
19 VertexBuffer,
20};
21
22pub const OPENGL_TO_WGPU_MATRIX: Mat4 = Mat4::new(
24 1.0, 0.0, 0.0, 0.0,
25 0.0, 1.0, 0.0, 0.0,
26 0.0, 0.0, 0.5, 0.0,
27 0.0, 0.0, 0.5, 1.0,
28);
29
30const RENDERER_STARTUP: &str =
31 "Please, use `renderer::startup` as a first system on the `startup` run level";
32
33pub struct ScissorsRect {
35 pub clip_min_x: u32,
37 pub clip_min_y: u32,
39 pub width: u32,
41 pub height: u32,
43}
44
45#[derive(Default)]
47pub struct Options {
48 pub scissors_rect: Option<ScissorsRect>,
50}
51
52pub struct Renderer {
54 clear_color: Color,
55 cycle: usize,
56 backend: Option<Backend>,
57 loaded: bool,
58}
59
60impl Renderer {
61 fn backend(&self) -> &Backend {
62 self.backend.as_ref().expect(RENDERER_STARTUP)
63 }
64
65 fn backend_mut(&mut self) -> &mut Backend {
66 self.backend.as_mut().expect(RENDERER_STARTUP)
67 }
68
69 pub fn cycle(&self) -> usize {
71 self.cycle
72 }
73
74 pub fn load_vertex_buffer<'a>(
76 &self,
77 buffer: &mut VertexBuffer,
78 attributes: &'a [u8],
79 indices: Option<&'a [u8]>,
80 count: usize,
81 ) {
82 buffer.load(self.backend(), attributes, indices, count as u32);
83 }
84
85 pub fn load_texture_buffer<'a>(
87 &self,
88 buffer: &mut TextureBuffer,
89 width: u32,
90 height: u32,
91 layers: &'a[&'a [u8]],
92 ) {
93 buffer.load(self.backend(), width, height, layers);
94 }
95
96 pub fn load_uniform_buffer<'a>(&self, buffer: &mut UniformBuffer, data: &'a [u8]) {
98 buffer.load(self.backend(), data);
99 }
100
101 pub fn load_sampler(&self, sampler: &mut Sampler) {
103 sampler.load(self.backend());
104 }
105
106 pub fn load_shader_module(
108 &self,
109 shader_module: &mut ShaderModule,
110 name: &str,
111 code: &str
112 ) {
113 shader_module.load(self.backend(), name, code);
114 }
115
116 pub fn reload(&mut self) {
118 self.loaded = false;
119 }
120
121 pub fn bind(&mut self, pipeline: &mut Pipeline, layout: PipelineLayout) {
123 if !self.backend().has_pipeline(pipeline.shader) {
124 let pipeline_backend = PipelineBackend::new(self.backend(), &layout);
125 self.backend_mut().add_pipeline(pipeline.shader, pipeline_backend);
126 }
127
128 let pipeline_backend = self.backend()
129 .pipeline(pipeline.shader)
130 .unwrap();
131
132 let mut bindings = Bindings::default();
133 bindings.load(self.backend(), pipeline_backend, layout.bindings);
134 pipeline.bindings = bindings;
135 }
136
137 pub fn run(&mut self, pipeline: &mut Pipeline, mesh: &Mesh) {
139 self.backend_mut().run_pipeline(
142 pipeline.shader,
143 &mesh.vertex_buffer,
144 &pipeline.bindings,
145 &pipeline.options,
146 );
147 }
149}
150
151impl Default for Renderer {
152 fn default() -> Self {
154 Renderer {
155 clear_color: Color::from([0.1, 0.2, 0.3, 1.0]),
156 cycle: 1,
157 backend: None,
158 loaded: false,
159 }
160 }
161}
162
163unsafe impl Send for Renderer {}
164unsafe impl Sync for Renderer {}
165
166pub fn startup(mut renderer: Mut<Renderer>, mut globals: Mut<Globals>, window: Mut<Window>) {
168 if renderer.backend.is_none() {
170 renderer.backend = Some(futures::executor::block_on(backend::init(window.get())));
171 }
172
173 let mut sampler = Sampler::default();
175 renderer.load_sampler(&mut sampler);
176 globals.set(sampler);
177}
178
179pub fn bind(mut renderer: Mut<Renderer>, mut assets: Mut<Assets>) {
181 let clear_color = renderer.clear_color;
182 renderer.backend_mut().bind_frame(&clear_color);
183
184 if renderer.loaded {
185 return;
186 }
187
188 let mut loaded = true;
189
190 for (_id, shader) in assets.iter_mut::<Shader>() {
191 shader.load(&renderer);
192 if !shader.loaded() {
193 loaded = false;
194 }
195 }
196
197 renderer.loaded = loaded;
198}
199
200pub fn release(mut renderer: Mut<Renderer>) {
202 renderer.backend_mut().release_frame();
203 renderer.cycle += 1;
204 if renderer.cycle == 0 {
205 renderer.cycle = 1;
206 }
207}
208
209pub fn resize(mut renderer: Mut<Renderer>, window: Const<Window>) {
211 let size = window.inner_size();
212 renderer.backend_mut().resize(size.x, size.y);
213}
214
215pub struct PipelineOptions {
217 pub depth_buffer_mode: DepthBufferMode,
219 pub disable_cull_mode: bool,
221}
222
223impl Default for PipelineOptions {
224 fn default() -> Self {
225 Self {
226 depth_buffer_mode: DepthBufferMode::Write,
227 disable_cull_mode: false,
228 }
229 }
230}
231
232pub struct PipelineLayout<'a> {
234 pub label: String,
236 pub mesh: &'a Mesh,
238 pub shader: &'a Shader,
240 pub bindings: &'a [BindGroup<'a>],
242 pub options: PipelineOptions,
244}
245
246
247#[derive(Debug, Eq, PartialEq, Copy, Clone)]
249pub enum DepthBufferMode {
250 Read,
252 Write,
254 Disabled
256}
257
258#[derive(Debug)]
260pub enum AttributeFormat {
261 Float32,
263 Float32x2,
265 Float32x3,
267 Float32x4,
269 Uint16x2,
271 Uint16x4,
273 Uint32,
275 Uint32x2,
277 Uint32x3,
279 Uint32x4,
281}
282
283impl AttributeFormat {
284 pub fn size(&self) -> usize {
286 match self {
287 AttributeFormat::Float32 => 4,
288 AttributeFormat::Float32x2 => 4 * 2,
289 AttributeFormat::Float32x3 => 4 * 3,
290 AttributeFormat::Float32x4 => 4 * 4,
291 AttributeFormat::Uint16x2 => 2 * 2,
292 AttributeFormat::Uint16x4 => 2 * 4,
293 AttributeFormat::Uint32 => 4,
294 AttributeFormat::Uint32x2 => 4 * 2,
295 AttributeFormat::Uint32x3 => 4 * 3,
296 AttributeFormat::Uint32x4 => 4 * 4,
297 }
298 }
299}
300
301pub enum Binding<'a> {
303 Uniform(&'a str, Stage, &'a UniformBuffer),
305 Texture(&'a str, Stage, &'a TextureBuffer),
307 Texture3D(&'a str, Stage, &'a TextureBuffer),
309 Sampler(&'a str, Stage, &'a Sampler),
311}
312
313pub enum Stage {
315 Vertex,
317 Fragment,
319 Compute,
321 All
323}
324
325pub struct BindGroup<'a> {
327 label: &'a str,
328 bindings: Vec<Binding<'a>>,
329}
330
331impl<'a> BindGroup<'a> {
332 pub fn new(label: &'a str, bindings: Vec<Binding<'a>>) -> Self {
334 Self {
335 label,
336 bindings,
337 }
338 }
339}
340