rg3d/renderer/framework/
geometry_buffer.rs

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    // Force compiler to not implement Send and Sync, because OpenGL is not thread-safe.
18    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    // Force compiler to not implement Send and Sync, because OpenGL is not thread-safe.
37    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        // Element buffer object binding is stored inside vertex array object, so
344        // it does not modifies state.
345        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}