1use crate::scene::mesh::surface::SurfaceData;
2use crate::{
3 core::{math::TriangleDefinition, scope_profile},
4 renderer::framework::{error::FrameworkError, state::PipelineState},
5 scene::mesh::buffer::{VertexAttributeDataType, VertexBuffer},
6 utils::array_as_u8_slice,
7};
8use glow::HasContext;
9use std::{cell::Cell, marker::PhantomData, mem::size_of};
10
11struct NativeBuffer {
12 state: *mut PipelineState,
13 id: glow::Buffer,
14 kind: GeometryBufferKind,
15 element_size: usize,
16 size_bytes: usize,
17 thread_mark: PhantomData<*const u8>,
19}
20
21impl Drop for NativeBuffer {
22 fn drop(&mut self) {
23 unsafe {
24 (*self.state).gl.delete_buffer(self.id);
25 }
26 }
27}
28
29pub struct GeometryBuffer {
30 state: *mut PipelineState,
31 vertex_array_object: glow::VertexArray,
32 buffers: Vec<NativeBuffer>,
33 element_buffer_object: glow::Buffer,
34 element_count: Cell<usize>,
35 element_kind: ElementKind,
36 thread_mark: PhantomData<*const u8>,
38}
39
40#[derive(Copy, Clone)]
41#[allow(dead_code)]
42pub enum AttributeKind {
43 Float,
44 Float2,
45 Float3,
46 Float4,
47
48 UnsignedByte,
49 UnsignedByte2,
50 UnsignedByte3,
51 UnsignedByte4,
52
53 UnsignedShort,
54 UnsignedShort2,
55 UnsignedShort3,
56 UnsignedShort4,
57
58 UnsignedInt,
59 UnsignedInt2,
60 UnsignedInt3,
61 UnsignedInt4,
62}
63
64pub struct AttributeDefinition {
65 pub location: u32,
66 pub kind: AttributeKind,
67 pub normalized: bool,
68 pub divisor: u32,
69}
70
71impl AttributeKind {
72 pub fn size_bytes(self) -> usize {
73 match self {
74 AttributeKind::Float => size_of::<f32>(),
75 AttributeKind::Float2 => size_of::<f32>() * 2,
76 AttributeKind::Float3 => size_of::<f32>() * 3,
77 AttributeKind::Float4 => size_of::<f32>() * 4,
78
79 AttributeKind::UnsignedByte => size_of::<u8>(),
80 AttributeKind::UnsignedByte2 => size_of::<u8>() * 2,
81 AttributeKind::UnsignedByte3 => size_of::<u8>() * 3,
82 AttributeKind::UnsignedByte4 => size_of::<u8>() * 4,
83
84 AttributeKind::UnsignedShort => size_of::<u16>(),
85 AttributeKind::UnsignedShort2 => size_of::<u16>() * 2,
86 AttributeKind::UnsignedShort3 => size_of::<u16>() * 3,
87 AttributeKind::UnsignedShort4 => size_of::<u16>() * 4,
88
89 AttributeKind::UnsignedInt => size_of::<u32>(),
90 AttributeKind::UnsignedInt2 => size_of::<u32>() * 2,
91 AttributeKind::UnsignedInt3 => size_of::<u32>() * 3,
92 AttributeKind::UnsignedInt4 => size_of::<u32>() * 4,
93 }
94 }
95
96 fn get_type(self) -> u32 {
97 match self {
98 AttributeKind::Float
99 | AttributeKind::Float2
100 | AttributeKind::Float3
101 | AttributeKind::Float4 => glow::FLOAT,
102
103 AttributeKind::UnsignedByte
104 | AttributeKind::UnsignedByte2
105 | AttributeKind::UnsignedByte3
106 | AttributeKind::UnsignedByte4 => glow::UNSIGNED_BYTE,
107
108 AttributeKind::UnsignedShort
109 | AttributeKind::UnsignedShort2
110 | AttributeKind::UnsignedShort3
111 | AttributeKind::UnsignedShort4 => glow::UNSIGNED_SHORT,
112
113 AttributeKind::UnsignedInt
114 | AttributeKind::UnsignedInt2
115 | AttributeKind::UnsignedInt3
116 | AttributeKind::UnsignedInt4 => glow::UNSIGNED_INT,
117 }
118 }
119
120 fn length(self) -> usize {
121 match self {
122 AttributeKind::Float
123 | AttributeKind::UnsignedByte
124 | AttributeKind::UnsignedShort
125 | AttributeKind::UnsignedInt => 1,
126
127 AttributeKind::Float2
128 | AttributeKind::UnsignedByte2
129 | AttributeKind::UnsignedShort2
130 | AttributeKind::UnsignedInt2 => 2,
131
132 AttributeKind::Float3
133 | AttributeKind::UnsignedByte3
134 | AttributeKind::UnsignedShort3
135 | AttributeKind::UnsignedInt3 => 3,
136
137 AttributeKind::Float4
138 | AttributeKind::UnsignedByte4
139 | AttributeKind::UnsignedShort4
140 | AttributeKind::UnsignedInt4 => 4,
141 }
142 }
143}
144
145#[derive(Copy, Clone)]
146#[repr(u32)]
147pub enum GeometryBufferKind {
148 StaticDraw = glow::STATIC_DRAW,
149 DynamicDraw = glow::DYNAMIC_DRAW,
150}
151
152#[derive(Copy, Clone, PartialEq, Eq, Debug)]
153pub enum ElementKind {
154 Triangle,
155 Line,
156}
157
158impl ElementKind {
159 fn index_per_element(self) -> usize {
160 match self {
161 ElementKind::Triangle => 3,
162 ElementKind::Line => 2,
163 }
164 }
165}
166
167pub struct GeometryBufferBinding<'a> {
168 state: &'a mut PipelineState,
169 buffer: &'a GeometryBuffer,
170}
171
172#[derive(Copy, Clone, Default)]
173pub struct DrawCallStatistics {
174 pub triangles: usize,
175}
176
177impl<'a> GeometryBufferBinding<'a> {
178 pub fn set_triangles(self, triangles: &[TriangleDefinition]) -> Self {
179 scope_profile!();
180
181 assert_eq!(self.buffer.element_kind, ElementKind::Triangle);
182 self.buffer.element_count.set(triangles.len());
183
184 unsafe { self.set_elements(array_as_u8_slice(triangles)) }
185
186 self
187 }
188
189 pub fn set_lines(self, lines: &[[u32; 2]]) -> Self {
190 scope_profile!();
191
192 assert_eq!(self.buffer.element_kind, ElementKind::Line);
193 self.buffer.element_count.set(lines.len());
194
195 unsafe {
196 self.set_elements(array_as_u8_slice(lines));
197 }
198
199 self
200 }
201
202 unsafe fn set_elements(&self, data: &[u8]) {
203 scope_profile!();
204
205 self.state
206 .gl
207 .buffer_data_u8_slice(glow::ELEMENT_ARRAY_BUFFER, data, glow::DYNAMIC_DRAW);
208 }
209
210 pub fn draw_part(
211 &self,
212 offset: usize,
213 count: usize,
214 ) -> Result<DrawCallStatistics, FrameworkError> {
215 scope_profile!();
216
217 let last_triangle_index = offset + count;
218
219 if last_triangle_index > self.buffer.element_count.get() {
220 Err(FrameworkError::InvalidElementRange {
221 start: offset,
222 end: last_triangle_index,
223 total: self.buffer.element_count.get(),
224 })
225 } else {
226 let index_per_element = self.buffer.element_kind.index_per_element();
227 let start_index = offset * index_per_element;
228 let index_count = count * index_per_element;
229
230 unsafe {
231 self.draw_internal(start_index, index_count);
232 }
233
234 Ok(DrawCallStatistics { triangles: count })
235 }
236 }
237
238 fn mode(&self) -> u32 {
239 match self.buffer.element_kind {
240 ElementKind::Triangle => glow::TRIANGLES,
241 ElementKind::Line => glow::LINES,
242 }
243 }
244
245 pub fn draw(&self) -> DrawCallStatistics {
246 scope_profile!();
247
248 let start_index = 0;
249 let index_per_element = self.buffer.element_kind.index_per_element();
250 let index_count = self.buffer.element_count.get() * index_per_element;
251
252 unsafe { self.draw_internal(start_index, index_count) }
253
254 DrawCallStatistics {
255 triangles: self.buffer.element_count.get(),
256 }
257 }
258
259 unsafe fn draw_internal(&self, start_index: usize, index_count: usize) {
260 scope_profile!();
261
262 if index_count > 0 {
263 let indices = (start_index * size_of::<u32>()) as i32;
264 self.state.gl.draw_elements(
265 self.mode(),
266 index_count as i32,
267 glow::UNSIGNED_INT,
268 indices,
269 );
270 }
271 }
272
273 pub fn draw_instances(&self, count: usize) -> DrawCallStatistics {
274 let index_per_element = self.buffer.element_kind.index_per_element();
275 let index_count = self.buffer.element_count.get() * index_per_element;
276 if index_count > 0 {
277 unsafe {
278 self.state.gl.draw_elements_instanced(
279 self.mode(),
280 index_count as i32,
281 glow::UNSIGNED_INT,
282 0,
283 count as i32,
284 )
285 }
286 }
287 DrawCallStatistics {
288 triangles: self.buffer.element_count.get() * count,
289 }
290 }
291}
292
293impl GeometryBuffer {
294 pub fn from_surface_data(
295 data: &SurfaceData,
296 kind: GeometryBufferKind,
297 state: &mut PipelineState,
298 ) -> Self {
299 let geometry_buffer = GeometryBufferBuilder::new(ElementKind::Triangle)
300 .with_buffer_builder(BufferBuilder::from_vertex_buffer(&data.vertex_buffer, kind))
301 .build(state)
302 .unwrap();
303
304 geometry_buffer
305 .bind(state)
306 .set_triangles(data.geometry_buffer.triangles_ref());
307
308 geometry_buffer
309 }
310
311 pub fn set_buffer_data<T>(&mut self, state: &mut PipelineState, buffer: usize, data: &[T]) {
312 scope_profile!();
313
314 let buffer = &mut self.buffers[buffer];
315
316 assert_eq!(buffer.element_size % size_of::<T>(), 0);
317
318 state.set_vertex_buffer_object(Some(buffer.id));
319
320 let size = data.len() * size_of::<T>();
321 let usage = buffer.kind as u32;
322
323 unsafe {
324 if buffer.size_bytes < size {
325 state
326 .gl
327 .buffer_data_u8_slice(glow::ARRAY_BUFFER, array_as_u8_slice(data), usage);
328 } else {
329 state
330 .gl
331 .buffer_sub_data_u8_slice(glow::ARRAY_BUFFER, 0, array_as_u8_slice(data));
332 }
333 }
334
335 buffer.size_bytes = size;
336 }
337
338 pub fn bind<'a>(&'a self, state: &'a mut PipelineState) -> GeometryBufferBinding<'a> {
339 scope_profile!();
340
341 state.set_vertex_array_object(Some(self.vertex_array_object));
342
343 unsafe {
346 state
347 .gl
348 .bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.element_buffer_object));
349 }
350
351 GeometryBufferBinding {
352 state,
353 buffer: self,
354 }
355 }
356}
357
358impl Drop for GeometryBuffer {
359 fn drop(&mut self) {
360 unsafe {
361 self.buffers.clear();
362
363 (*self.state).gl.delete_buffer(self.element_buffer_object);
364 (*self.state)
365 .gl
366 .delete_vertex_array(self.vertex_array_object);
367 }
368 }
369}
370
371pub struct BufferBuilder {
372 element_size: usize,
373 kind: GeometryBufferKind,
374 attributes: Vec<AttributeDefinition>,
375 data: *const u8,
376 data_size: usize,
377}
378
379impl BufferBuilder {
380 pub fn new<T: Sized>(kind: GeometryBufferKind, data: Option<&[T]>) -> Self {
381 let (data, data_size) = if let Some(data) = data {
382 (data as *const _ as *const u8, data.len() * size_of::<T>())
383 } else {
384 (std::ptr::null(), 0)
385 };
386
387 Self {
388 kind,
389 attributes: Default::default(),
390 element_size: size_of::<T>(),
391 data,
392 data_size,
393 }
394 }
395
396 pub fn from_vertex_buffer(buffer: &VertexBuffer, kind: GeometryBufferKind) -> Self {
397 Self {
398 element_size: buffer.vertex_size() as usize,
399 kind,
400 attributes: buffer
401 .layout()
402 .iter()
403 .map(|a| AttributeDefinition {
404 location: a.shader_location as u32,
405 kind: match (a.data_type, a.size) {
406 (VertexAttributeDataType::F32, 1) => AttributeKind::Float,
407 (VertexAttributeDataType::F32, 2) => AttributeKind::Float2,
408 (VertexAttributeDataType::F32, 3) => AttributeKind::Float3,
409 (VertexAttributeDataType::F32, 4) => AttributeKind::Float4,
410 (VertexAttributeDataType::U32, 1) => AttributeKind::UnsignedInt,
411 (VertexAttributeDataType::U32, 2) => AttributeKind::UnsignedInt2,
412 (VertexAttributeDataType::U32, 3) => AttributeKind::UnsignedInt3,
413 (VertexAttributeDataType::U32, 4) => AttributeKind::UnsignedInt4,
414 (VertexAttributeDataType::U16, 1) => AttributeKind::UnsignedShort,
415 (VertexAttributeDataType::U16, 2) => AttributeKind::UnsignedShort2,
416 (VertexAttributeDataType::U16, 3) => AttributeKind::UnsignedShort3,
417 (VertexAttributeDataType::U16, 4) => AttributeKind::UnsignedShort4,
418 (VertexAttributeDataType::U8, 1) => AttributeKind::UnsignedByte,
419 (VertexAttributeDataType::U8, 2) => AttributeKind::UnsignedByte2,
420 (VertexAttributeDataType::U8, 3) => AttributeKind::UnsignedByte3,
421 (VertexAttributeDataType::U8, 4) => AttributeKind::UnsignedByte4,
422 _ => unreachable!(),
423 },
424 normalized: false,
425 divisor: 0,
426 })
427 .collect(),
428 data: buffer.raw_data().as_ptr(),
429 data_size: buffer.raw_data().len(),
430 }
431 }
432
433 pub fn with_attribute(mut self, attribute: AttributeDefinition) -> Self {
434 self.attributes.push(attribute);
435 self
436 }
437
438 fn build(self, state: &mut PipelineState) -> Result<NativeBuffer, FrameworkError> {
439 let vbo = unsafe { state.gl.create_buffer()? };
440
441 state.set_vertex_buffer_object(Some(vbo));
442
443 if self.data_size > 0 {
444 unsafe {
445 state.gl.buffer_data_u8_slice(
446 glow::ARRAY_BUFFER,
447 std::slice::from_raw_parts(self.data, self.data_size),
448 self.kind as u32,
449 );
450 }
451 }
452
453 let native_buffer = NativeBuffer {
454 state,
455 id: vbo,
456 kind: self.kind,
457 element_size: self.element_size,
458 size_bytes: self.data_size,
459 thread_mark: Default::default(),
460 };
461
462 let mut offset = 0usize;
463 for definition in self.attributes {
464 unsafe {
465 state.gl.vertex_attrib_pointer_f32(
466 definition.location,
467 definition.kind.length() as i32,
468 definition.kind.get_type(),
469 definition.normalized,
470 self.element_size as i32,
471 offset as i32,
472 );
473 state
474 .gl
475 .vertex_attrib_divisor(definition.location, definition.divisor);
476 state.gl.enable_vertex_attrib_array(definition.location);
477
478 offset += definition.kind.size_bytes();
479
480 if offset > self.element_size {
481 state.set_vertex_buffer_object(Default::default());
482 return Err(FrameworkError::InvalidAttributeDescriptor);
483 }
484 }
485 }
486
487 Ok(native_buffer)
488 }
489}
490
491pub struct GeometryBufferBuilder {
492 element_kind: ElementKind,
493 buffers: Vec<BufferBuilder>,
494}
495
496impl GeometryBufferBuilder {
497 pub fn new(element_kind: ElementKind) -> Self {
498 Self {
499 element_kind,
500 buffers: Default::default(),
501 }
502 }
503
504 pub fn with_buffer_builder(mut self, builder: BufferBuilder) -> Self {
505 self.buffers.push(builder);
506 self
507 }
508
509 pub fn build(self, state: &mut PipelineState) -> Result<GeometryBuffer, FrameworkError> {
510 scope_profile!();
511
512 let vao = unsafe { state.gl.create_vertex_array()? };
513 let ebo = unsafe { state.gl.create_buffer()? };
514
515 state.set_vertex_array_object(Some(vao));
516
517 let mut buffers = Vec::new();
518 for builder in self.buffers {
519 buffers.push(builder.build(state)?);
520 }
521
522 Ok(GeometryBuffer {
523 state,
524 vertex_array_object: vao,
525 buffers,
526 element_buffer_object: ebo,
527 element_count: Cell::new(0),
528 element_kind: self.element_kind,
529 thread_mark: PhantomData,
530 })
531 }
532}