1
2use crate::prelude::*;
3use std::{
4 any::Any,
5 collections::BTreeMap,
6 ffi::c_void,
7 fmt::{self, Debug, Formatter},
8 marker::PhantomData,
9 mem::{size_of, align_of},
10 ptr::null,
11 rc::Rc,
12};
13
14pub trait VertexType: Copy + Clone + Sized + Default + Debug + Iterable {}
16impl<T> VertexType for T where T: Copy + Clone + Sized + Default + Debug + Iterable {}
17
18#[macro_export]
20macro_rules! derive_vertex_type {
21 ($item: item) => {
22 #[derive(Iterable, Default, Debug, Clone, Copy)]
23 $item
24 };
25}
26
27pub struct Pipeline<V: VertexType, I: VertexType> {
29 pub glcore: Rc<GLCore>,
30 name: u32,
31 pub mesh: Rc<dyn GenericMeshWithMaterial>,
32 pub shader: Rc<Shader>,
33 vertex_stride: usize,
34 instance_stride: usize,
35 _phantom_vertex_type: PhantomData<V>,
36 _phantom_instance_type: PhantomData<I>,
37}
38
39#[derive(Debug, Clone, Copy)]
41struct DataGlType {
42 data_type: u32,
43 size: u32,
44 rows: u32,
45}
46
47#[derive(Debug)]
49pub struct PipelineBind<'a, V: VertexType, I: VertexType> {
50 pub pipeline: &'a Pipeline<V, I>,
51}
52
53impl DataGlType {
54 fn is_integer(&self) -> bool {
56 matches!(self.data_type, GL_BYTE | GL_SHORT | GL_INT | GL_UNSIGNED_BYTE | GL_UNSIGNED_SHORT | GL_UNSIGNED_INT)
57 }
58
59 fn is_double(&self) -> bool {
61 matches!(self.data_type, GL_DOUBLE)
62 }
63
64 fn size_in_bytes(&self) -> usize {
66 match self.data_type {
67 GL_BYTE | GL_UNSIGNED_BYTE => (self.size as usize) * self.rows as usize,
68 GL_SHORT | GL_UNSIGNED_SHORT | GL_HALF_FLOAT => 2usize * self.size as usize * self.rows as usize,
69 GL_INT | GL_UNSIGNED_INT | GL_FLOAT => 4usize * self.size as usize * self.rows as usize,
70 GL_DOUBLE => 8usize * self.size as usize * self.rows as usize,
71 other => panic!("Invalid `data_type` ({other})"),
72 }
73 }
74}
75
76impl<V: VertexType, I: VertexType> Pipeline<V, I> {
77 pub fn get_name(&self) -> u32 {
79 self.name
80 }
81
82 pub fn new(glcore: Rc<GLCore>, mesh: Rc<dyn GenericMeshWithMaterial>, shader: Rc<Shader>) -> Self {
84 let mut name: u32 = 0;
85 glcore.glGenVertexArrays(1, &mut name as *mut u32);
86 let mut ret = Self {
87 glcore,
88 name,
89 mesh,
90 shader,
91 vertex_stride: size_of::<V>(),
92 instance_stride: size_of::<I>(),
93 _phantom_vertex_type: PhantomData,
94 _phantom_instance_type: PhantomData,
95 };
96 ret.establish_pipeline();
97 ret
98 }
99
100 fn establish_pipeline(&mut self) {
102 let program = self.shader.use_program();
103 let active_attribs = self.shader.get_active_attribs().unwrap();
104 let bind = self.bind();
105
106 let vb_bind = self.mesh.get_vertex_buffer().bind();
107 self.describe::<V>(&active_attribs, 0);
108 vb_bind.unbind();
109
110 if let Some(ib) = self.mesh.get_instance_buffer() {
111 let ib_bind = ib.bind();
112 self.describe::<I>(&active_attribs, 1);
113 ib_bind.unbind();
114 }
115
116 bind.unbind();
117 program.unuse();
118 }
119
120 fn describe<T: VertexType>(&self, active_attribs: &BTreeMap<String, ShaderInputVarType>, v_a_d: u32) {
122 let instance = T::default();
123 let stride = size_of::<T>();
124 let alignment = align_of::<T>();
125 let mut cur_offset: usize = 0;
126 for (field_name, field_value) in instance.iter() {
127 let typename = Self::get_typename_of_vertex_struct_member(field_value);
128 let datainfo = Self::get_vertex_struct_member_gltype(typename);
129 if let Some(attrib_type) = active_attribs.get(field_name) {
130 let (p_size, p_rows) = attrib_type.get_size_and_rows();
131 if p_size != datainfo.size || p_rows != datainfo.rows {
132 panic!("The size and rows of the shader attrib is {p_size}x{p_rows}, but the given member of the vertex struct is {}x{}", datainfo.size, datainfo.rows);
133 }
134 let location = self.shader.get_attrib_location(field_name);
135 if location >= 0 {
136 let location = location as u32;
137 for row in 0..datainfo.rows {
138 let location = location + row;
139 let do_normalize = if field_name.contains("normalized") && field_name.contains("_") {
140 1
141 } else {
142 0
143 };
144 let ptr_param = cur_offset as *const c_void;
145 self.glcore.glEnableVertexAttribArray(location);
146 if attrib_type.is_float() {self.glcore.glVertexAttribPointer(location, p_size as i32, attrib_type.get_base_type() as u32, do_normalize, stride as i32, ptr_param)} else
147 if attrib_type.is_integer() {self.glcore.glVertexAttribIPointer(location, p_size as i32, attrib_type.get_base_type() as u32, stride as i32, ptr_param)} else
148 if attrib_type.is_double() {self.glcore.glVertexAttribLPointer(location, p_size as i32, attrib_type.get_base_type() as u32, stride as i32, ptr_param)} else
149 {panic!("Unknown data type of the attrib `{} {field_name}`", attrib_type.get_type())}
150 self.glcore.glVertexAttribDivisor(location, v_a_d);
151 }
152 } else {
153 eprintln!("Attrib `{typename} {field_name}` is active, but can't get its location.");
154 }
155 } else {
156 eprintln!("Attrib `{typename} {field_name}` is not active.");
157 }
158 cur_offset += datainfo.size_in_bytes();
159 cur_offset = ((cur_offset - 1) / alignment + 1) * alignment;
160 }
161 }
162
163 pub fn bind<'a>(&'a self) -> PipelineBind<'a, V, I> {
165 PipelineBind::new(self)
166 }
167
168 fn get_vertex_struct_member_gltype(member_type: &str) -> DataGlType {
170 match member_type {
171 "i8" => DataGlType{data_type: GL_BYTE, size: 1, rows: 1},
172 "i16" => DataGlType{data_type: GL_SHORT, size: 1, rows: 1},
173 "i32" => DataGlType{data_type: GL_INT, size: 1, rows: 1},
174 "u8" => DataGlType{data_type: GL_UNSIGNED_BYTE, size: 1, rows: 1},
175 "u16" => DataGlType{data_type: GL_UNSIGNED_SHORT, size: 1, rows: 1},
176 "u32" => DataGlType{data_type: GL_UNSIGNED_INT, size: 1, rows: 1},
177 "f16" => DataGlType{data_type: GL_HALF_FLOAT, size: 1, rows: 1},
178 "f32" => DataGlType{data_type: GL_FLOAT, size: 1, rows: 1},
179 "f64" => DataGlType{data_type: GL_DOUBLE, size: 1, rows: 1},
180 _ => {
181 if member_type.contains("vec") {
182 let data_type =
183 if member_type.starts_with("u32") {GL_UNSIGNED_INT}
184 else if member_type.starts_with("u16") {GL_UNSIGNED_SHORT}
185 else if member_type.starts_with("u8") {GL_UNSIGNED_BYTE}
186 else if member_type.starts_with("i32") {GL_INT}
187 else if member_type.starts_with("i16") {GL_SHORT}
188 else if member_type.starts_with("i8") {GL_BYTE}
189 else {
190 match member_type.chars().next().unwrap() {
191 'v' => GL_FLOAT,
192 'd' => GL_DOUBLE,
193 'b' => GL_BYTE,
194 'i' => GL_INT,
195 'u' => GL_UNSIGNED_INT,
196 _ => panic!("Unsupported type of member: `{member_type}`"),
197 }
198 };
199 let size = u32::from(member_type.chars().last().unwrap()) - u32::from('0');
200 DataGlType{data_type, size, rows: 1}
201 } else if member_type.contains("mat") {
202 let data_type = if member_type.starts_with("d") {
203 GL_DOUBLE
204 } else {
205 GL_FLOAT
206 };
207 let (size, rows) =
208 if member_type.ends_with("2x2") {(2, 2)}
209 else if member_type.ends_with("2x3") {(2, 3)}
210 else if member_type.ends_with("2x4") {(2, 4)}
211 else if member_type.ends_with("3x2") {(3, 2)}
212 else if member_type.ends_with("3x3") {(3, 3)}
213 else if member_type.ends_with("3x4") {(3, 4)}
214 else if member_type.ends_with("4x2") {(4, 2)}
215 else if member_type.ends_with("4x3") {(4, 3)}
216 else if member_type.ends_with("4x4") {(4, 4)}
217 else {
218 match member_type.chars().last().unwrap() {
219 '2' => (2, 2),
220 '3' => (3, 3),
221 '4' => (4, 4),
222 _ => panic!("Unsupported type of member: `{member_type}`"),
223 }
224 };
225 DataGlType{data_type, size, rows}
226 } else if member_type.contains("quat") {
227 let data_type = if member_type.starts_with("d") {
228 GL_DOUBLE
229 } else {
230 GL_FLOAT
231 };
232 DataGlType{data_type, size: 4, rows: 1}
233 } else {
234 panic!("Unsupported type of member: `{member_type}`")
235 }
236 }
237 }
238 }
239
240 pub fn get_typename_of_vertex_struct_member(data: &dyn Any) -> &str {
242 if data.is::<u8>() {"u8"}
243 else if data.is::<u16>() {"u16"}
244 else if data.is::<u32>() {"u32"}
245 else if data.is::<i8>() {"i8"}
246 else if data.is::<i16>() {"i16"}
247 else if data.is::<i32>() {"i32"}
248 else if data.is::<f16>() {"f16"}
249 else if data.is::<f32>() {"f32"}
250 else if data.is::<f64>() {"f64"}
251 else if data.is::<Vec1>() {"vec1"}
252 else if data.is::<Vec2>() {"vec2"}
253 else if data.is::<Vec3>() {"vec3"}
254 else if data.is::<Vec4>() {"vec4"}
255 else if data.is::<DVec1>() {"dvec1"}
256 else if data.is::<DVec2>() {"dvec2"}
257 else if data.is::<DVec3>() {"dvec3"}
258 else if data.is::<DVec4>() {"dvec4"}
259 else if data.is::<BVec1>() {"bvec1"}
260 else if data.is::<BVec2>() {"bvec2"}
261 else if data.is::<BVec3>() {"bvec3"}
262 else if data.is::<BVec4>() {"bvec4"}
263 else if data.is::<IVec1>() {"ivec1"}
264 else if data.is::<IVec2>() {"ivec2"}
265 else if data.is::<IVec3>() {"ivec3"}
266 else if data.is::<IVec4>() {"ivec4"}
267 else if data.is::<I8Vec1>() {"i8vec1"}
268 else if data.is::<I8Vec2>() {"i8vec2"}
269 else if data.is::<I8Vec3>() {"i8vec3"}
270 else if data.is::<I8Vec4>() {"i8vec4"}
271 else if data.is::<I16Vec1>() {"i16vec1"}
272 else if data.is::<I16Vec2>() {"i16vec2"}
273 else if data.is::<I16Vec3>() {"i16vec3"}
274 else if data.is::<I16Vec4>() {"i16vec4"}
275 else if data.is::<I32Vec1>() {"i32vec1"}
276 else if data.is::<I32Vec2>() {"i32vec2"}
277 else if data.is::<I32Vec3>() {"i32vec3"}
278 else if data.is::<I32Vec4>() {"i32vec4"}
279 else if data.is::<UVec1>() {"uvec1"}
280 else if data.is::<UVec2>() {"uvec2"}
281 else if data.is::<UVec3>() {"uvec3"}
282 else if data.is::<UVec4>() {"uvec4"}
283 else if data.is::<U8Vec1>() {"u8vec1"}
284 else if data.is::<U8Vec2>() {"u8vec2"}
285 else if data.is::<U8Vec3>() {"u8vec3"}
286 else if data.is::<U8Vec4>() {"u8vec4"}
287 else if data.is::<U16Vec1>() {"u16vec1"}
288 else if data.is::<U16Vec2>() {"u16vec2"}
289 else if data.is::<U16Vec3>() {"u16vec3"}
290 else if data.is::<U16Vec4>() {"u16vec4"}
291 else if data.is::<U32Vec1>() {"u32vec1"}
292 else if data.is::<U32Vec2>() {"u32vec2"}
293 else if data.is::<U32Vec3>() {"u32vec3"}
294 else if data.is::<U32Vec4>() {"u32vec4"}
295 else if data.is::<Quat>() {"quat"}
296 else if data.is::<DQuat>() {"dquat"}
297 else if data.is::<Mat2>() {"mat2"}
298 else if data.is::<Mat3>() {"mat3"}
299 else if data.is::<Mat4>() {"mat4"}
300 else if data.is::<Mat2x2>() {"mat2x2"}
301 else if data.is::<Mat2x3>() {"mat2x3"}
302 else if data.is::<Mat2x4>() {"mat2x4"}
303 else if data.is::<Mat3x2>() {"mat3x2"}
304 else if data.is::<Mat3x3>() {"mat3x3"}
305 else if data.is::<Mat3x4>() {"mat3x4"}
306 else if data.is::<Mat4x2>() {"mat4x2"}
307 else if data.is::<Mat4x3>() {"mat4x3"}
308 else if data.is::<Mat4x4>() {"mat4x4"}
309 else if data.is::<DMat2>() {"dmat2"}
310 else if data.is::<DMat3>() {"dmat3"}
311 else if data.is::<DMat4>() {"dmat4"}
312 else if data.is::<DMat2x2>() {"dmat2x2"}
313 else if data.is::<DMat2x3>() {"dmat2x3"}
314 else if data.is::<DMat2x4>() {"dmat2x4"}
315 else if data.is::<DMat3x2>() {"dmat3x2"}
316 else if data.is::<DMat3x3>() {"dmat3x3"}
317 else if data.is::<DMat3x4>() {"dmat3x4"}
318 else if data.is::<DMat4x2>() {"dmat4x2"}
319 else if data.is::<DMat4x3>() {"dmat4x3"}
320 else if data.is::<DMat4x4>() {"dmat4x4"}
321 else {panic!("Unsupported type of value: {data:?}")}
322 }
323}
324
325impl<'a, V: VertexType, I: VertexType> PipelineBind<'a, V, I> {
326 fn new(pipeline: &'a Pipeline<V, I>) -> Self {
328 pipeline.glcore.glBindVertexArray(pipeline.name);
329 Self {
330 pipeline,
331 }
332 }
333
334 pub fn draw(&self, fbo: Option<&Framebuffer>) {
336 let glcore = &self.pipeline.glcore;
337 let program = self.pipeline.shader.use_program();
338 let fbo_bind = fbo.map_or_else(
339 || {
340 glcore.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
341 None
342 },
343 |fbo| {
344 let bind = fbo.bind();
345 bind.setup(&self.pipeline.shader);
346 Some(bind)
347 });
348
349 if let Some(material) = self.pipeline.mesh.get_material() {
350 program.setup_material_uniforms(material, Some("i"), true);
351 } else {
352 let default_material = MaterialLegacy::default();
353 program.setup_material_uniforms(&default_material, Some("i"), true);
354 }
355
356 let mesh = &self.pipeline.mesh;
357 let element_buffer = mesh.get_element_buffer();
358 let e_bind = mesh.bind_element_buffer();
359
360 if let Some(command_buffer) = mesh.get_command_buffer() {
361 assert_eq!(command_buffer.get_target(), BufferTarget::DrawIndirectBuffer);
362 let c_bind = command_buffer.bind();
363 let num_commands = mesh.get_command_count();
364 if let Some(_) = element_buffer {
365 glcore.glMultiDrawElementsIndirect(mesh.get_primitive() as u32, mesh.get_element_type() as u32, null(), num_commands as i32, size_of::<DrawElementsCommand>() as i32);
366 } else {
367 glcore.glMultiDrawArraysIndirect(mesh.get_primitive() as u32, null(), num_commands as i32, size_of::<DrawArrayCommand>() as i32);
368 }
369 c_bind.unbind();
370 } else {
371 let num_vertices = mesh.get_vertex_count();
372 if let Some(_) = mesh.get_instance_buffer() {
373 let num_instances = mesh.get_instance_count();
374 if let Some(_) = element_buffer {
375 glcore.glDrawElementsInstanced(mesh.get_primitive() as u32, mesh.get_element_count() as i32, mesh.get_element_type() as u32, null(), num_instances as i32);
376 } else {
377 glcore.glDrawArraysInstanced(mesh.get_primitive() as u32, 0, num_vertices as i32, num_instances as i32);
378 }
379 } else if let Some(_) = element_buffer {
380 glcore.glDrawElements(mesh.get_primitive() as u32, mesh.get_element_count() as i32, mesh.get_element_type() as u32, null());
381 } else {
382 glcore.glDrawArrays(mesh.get_primitive() as u32, 0, num_vertices as i32);
383 }
384 }
385
386 if let Some(b) = e_bind { b.unbind() }
387 program.unuse();
388 if let Some(b) = fbo_bind { b.unbind() }
389 }
390
391 pub fn unbind(self) {}
393}
394
395impl<'a, V: VertexType, I: VertexType> Drop for PipelineBind<'a, V, I> {
396 fn drop(&mut self) {
397 self.pipeline.glcore.glBindVertexArray(0);
398 }
399}
400
401impl<V: VertexType, I: VertexType> Drop for Pipeline<V, I> {
402 fn drop(&mut self) {
403 self.glcore.glDeleteVertexArrays(1, &self.name as *const u32);
404 }
405}
406
407impl<V: VertexType, I: VertexType> Debug for Pipeline<V, I> {
408 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
409 f.debug_struct("Pipeline")
410 .field("name", &self.name)
411 .field("mesh", &self.mesh)
412 .field("shader", &self.shader)
413 .field("vertex_stride", &self.vertex_stride)
414 .field("instance_stride", &self.instance_stride)
415 .finish()
416 }
417}
418
419derive_vertex_type! {
420 pub struct UnusedType {}
422}