fyrox_graphics_gl/
geometry_buffer.rs1use crate::{buffer::GlBuffer, server::GlGraphicsServer, ToGlConstant};
22use fyrox_graphics::{
23 buffer::{BufferKind, GpuBufferDescriptor, GpuBufferTrait},
24 core::{array_as_u8_slice, math::TriangleDefinition},
25 error::FrameworkError,
26 geometry_buffer::{
27 AttributeKind, ElementsDescriptor, GpuGeometryBufferDescriptor, GpuGeometryBufferTrait,
28 },
29 ElementKind,
30};
31use glow::HasContext;
32use std::{cell::Cell, marker::PhantomData, rc::Weak};
33
34impl ToGlConstant for AttributeKind {
35 fn into_gl(self) -> u32 {
36 match self {
37 AttributeKind::Float => glow::FLOAT,
38 AttributeKind::UnsignedByte => glow::UNSIGNED_BYTE,
39 AttributeKind::UnsignedShort => glow::UNSIGNED_SHORT,
40 AttributeKind::UnsignedInt => glow::UNSIGNED_INT,
41 }
42 }
43}
44
45pub struct GlGeometryBuffer {
46 pub state: Weak<GlGraphicsServer>,
47 pub vertex_array_object: glow::VertexArray,
48 pub buffers: Vec<GlBuffer>,
49 pub element_buffer: GlBuffer,
50 pub element_count: Cell<usize>,
51 pub element_kind: ElementKind,
52 thread_mark: PhantomData<*const u8>,
54}
55
56impl GlGeometryBuffer {
57 pub fn new(
58 server: &GlGraphicsServer,
59 desc: GpuGeometryBufferDescriptor,
60 ) -> Result<Self, FrameworkError> {
61 let vao = unsafe { server.gl.create_vertex_array()? };
62
63 server.set_vertex_array_object(Some(vao));
64 #[cfg(not(target_arch = "wasm32"))]
65 if server.gl.supports_debug() && server.named_objects.get() {
66 unsafe {
67 server
68 .gl
69 .object_label(glow::VERTEX_ARRAY, vao.0.get(), Some(desc.name));
70 }
71 }
72
73 let element_buffer = GlBuffer::new(
74 server,
75 GpuBufferDescriptor {
76 name: &format!("{}ElementBuffer", desc.name),
77 size: 0,
78 kind: BufferKind::Index,
79 usage: desc.usage,
80 },
81 )?;
82
83 let (element_count, data) = match desc.elements {
84 ElementsDescriptor::Triangles(triangles) => {
85 (triangles.len(), array_as_u8_slice(triangles))
86 }
87 ElementsDescriptor::Lines(lines) => (lines.len(), array_as_u8_slice(lines)),
88 ElementsDescriptor::Points(points) => (points.len(), array_as_u8_slice(points)),
89 };
90
91 element_buffer.write_data(data)?;
92
93 let mut buffers = Vec::new();
94 for (i, buffer) in desc.buffers.iter().enumerate() {
95 unsafe {
96 let data_size = buffer.data.bytes.map(|bytes| bytes.len()).unwrap_or(0);
97
98 let native_buffer = GlBuffer::new(
99 server,
100 GpuBufferDescriptor {
101 name: &format!("{}VertexBuffer{i}", desc.name),
102 size: data_size,
103 kind: BufferKind::Vertex,
104 usage: buffer.usage,
105 },
106 )?;
107
108 if let Some(data) = buffer.data.bytes {
109 native_buffer.write_data(data)?;
110 }
111
112 let target = native_buffer.kind.into_gl();
113 server.gl.bind_buffer(target, Some(native_buffer.id));
114
115 let mut offset = 0usize;
116 for definition in buffer.attributes {
117 server.gl.vertex_attrib_pointer_f32(
118 definition.location,
119 definition.component_count as i32,
120 definition.kind.into_gl(),
121 definition.normalized,
122 buffer.data.element_size as i32,
123 offset as i32,
124 );
125 server
126 .gl
127 .vertex_attrib_divisor(definition.location, definition.divisor);
128 server.gl.enable_vertex_attrib_array(definition.location);
129
130 offset += definition.kind.size() * definition.component_count;
131
132 if offset > buffer.data.element_size {
133 return Err(FrameworkError::InvalidAttributeDescriptor);
134 }
135 }
136
137 buffers.push(native_buffer);
138 }
139 }
140
141 server.set_vertex_array_object(None);
142
143 Ok(GlGeometryBuffer {
144 state: server.weak(),
145 vertex_array_object: vao,
146 buffers,
147 element_buffer,
148 element_count: Cell::new(element_count),
149 element_kind: desc.elements.element_kind(),
150 thread_mark: PhantomData,
151 })
152 }
153
154 fn set_elements(&self, data: &[u8]) {
155 self.state
156 .upgrade()
157 .unwrap()
158 .set_vertex_array_object(Some(self.vertex_array_object));
159 self.element_buffer.write_data(data).unwrap()
160 }
161
162 pub fn mode(&self) -> u32 {
163 match self.element_kind {
164 ElementKind::Triangle => glow::TRIANGLES,
165 ElementKind::Line => glow::LINES,
166 ElementKind::Point => glow::POINTS,
167 }
168 }
169}
170
171impl GpuGeometryBufferTrait for GlGeometryBuffer {
172 fn set_buffer_data(&self, buffer: usize, data: &[u8]) {
173 self.state
174 .upgrade()
175 .unwrap()
176 .set_vertex_array_object(Some(self.vertex_array_object));
177 self.buffers[buffer]
178 .write_data(array_as_u8_slice(data))
179 .unwrap();
180 }
181
182 fn element_count(&self) -> usize {
183 self.element_count.get()
184 }
185
186 fn set_triangles(&self, triangles: &[TriangleDefinition]) {
187 assert_eq!(self.element_kind, ElementKind::Triangle);
188 self.element_count.set(triangles.len());
189 self.set_elements(array_as_u8_slice(triangles));
190 }
191
192 fn set_lines(&self, lines: &[[u32; 2]]) {
193 assert_eq!(self.element_kind, ElementKind::Line);
194 self.element_count.set(lines.len());
195 self.set_elements(array_as_u8_slice(lines));
196 }
197
198 fn set_points(&self, points: &[u32]) {
199 assert_eq!(self.element_kind, ElementKind::Point);
200 self.element_count.set(points.len());
201 self.set_elements(array_as_u8_slice(points));
202 }
203}
204
205impl Drop for GlGeometryBuffer {
206 fn drop(&mut self) {
207 if let Some(state) = self.state.upgrade() {
208 self.buffers.clear();
209 state.delete_vertex_array_object(self.vertex_array_object);
210 }
211 }
212}