Skip to content

Commit

Permalink
isolated opengl-specific code of geometrybuffer
Browse files Browse the repository at this point in the history
  • Loading branch information
mrDIMAS committed Oct 8, 2024
1 parent 991a312 commit 4f2d505
Show file tree
Hide file tree
Showing 25 changed files with 310 additions and 227 deletions.
6 changes: 3 additions & 3 deletions editor/src/highlight.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void main()

pub struct HighlightRenderPass {
framebuffer: Box<dyn FrameBuffer>,
quad: GeometryBuffer,
quad: Box<dyn GeometryBuffer>,
edge_detect_shader: EdgeDetectShader,
pub scene_handle: Handle<Scene>,
pub nodes_to_highlight: FxHashSet<Handle<Node>>,
Expand Down Expand Up @@ -193,7 +193,7 @@ impl HighlightRenderPass {
pub fn new_raw(server: &GlGraphicsServer, width: usize, height: usize) -> Self {
Self {
framebuffer: Self::create_frame_buffer(server, width, height),
quad: GeometryBuffer::from_surface_data(
quad: <dyn GeometryBuffer>::from_surface_data(
&SurfaceData::make_unit_xy_quad(),
BufferUsage::StaticDraw,
server,
Expand Down Expand Up @@ -315,7 +315,7 @@ impl SceneRenderPass for HighlightRenderPass {
let shader = &self.edge_detect_shader;
let frame_texture = self.framebuffer.color_attachments()[0].texture.clone();
ctx.framebuffer.draw(
&self.quad,
&*self.quad,
ctx.viewport,
&*shader.program,
&DrawParameters {
Expand Down
6 changes: 3 additions & 3 deletions editor/src/overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl OverlayShader {
}

pub struct OverlayRenderPass {
quad: GeometryBuffer,
quad: Box<dyn GeometryBuffer>,
shader: OverlayShader,
sound_icon: TextureResource,
light_icon: TextureResource,
Expand All @@ -77,7 +77,7 @@ pub struct OverlayRenderPass {
impl OverlayRenderPass {
pub fn new(server: &GlGraphicsServer) -> Rc<RefCell<Self>> {
Rc::new(RefCell::new(Self {
quad: GeometryBuffer::from_surface_data(
quad: <dyn GeometryBuffer>::from_surface_data(
&SurfaceData::make_collapsed_xy_quad(),
BufferUsage::StaticDraw,
server,
Expand Down Expand Up @@ -136,7 +136,7 @@ impl SceneRenderPass for OverlayRenderPass {
let world_matrix = Matrix4::new_translation(&position);

ctx.framebuffer.draw(
&self.quad,
&*self.quad,
ctx.viewport,
&*shader.program,
&DrawParameters {
Expand Down
4 changes: 2 additions & 2 deletions fyrox-graphics/src/framebuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub trait FrameBuffer: Any {
);
fn draw(
&mut self,
geometry: &GeometryBuffer,
geometry: &dyn GeometryBuffer,
viewport: Rect<i32>,
program: &dyn GpuProgram,
params: &DrawParameters,
Expand All @@ -105,7 +105,7 @@ pub trait FrameBuffer: Any {
fn draw_instances(
&mut self,
count: usize,
geometry: &GeometryBuffer,
geometry: &dyn GeometryBuffer,
viewport: Rect<i32>,
program: &dyn GpuProgram,
params: &DrawParameters,
Expand Down
152 changes: 13 additions & 139 deletions fyrox-graphics/src/geometry_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,13 @@
// SOFTWARE.

use crate::{
buffer::{Buffer, BufferKind, BufferUsage},
buffer::BufferUsage,
core::{array_as_u8_slice, math::TriangleDefinition},
error::FrameworkError,
gl::{buffer::GlBuffer, server::GlGraphicsServer, ToGlConstant},
ElementKind,
};
use bytemuck::Pod;
use glow::HasContext;
use std::{cell::Cell, marker::PhantomData, mem::size_of, rc::Weak};

pub struct GeometryBuffer {
pub state: Weak<GlGraphicsServer>,
pub vertex_array_object: glow::VertexArray,
pub buffers: Vec<GlBuffer>,
pub element_buffer: GlBuffer,
pub element_count: Cell<usize>,
pub element_kind: ElementKind,
// Force compiler to not implement Send and Sync, because OpenGL is not thread-safe.
thread_mark: PhantomData<*const u8>,
}
use std::any::Any;
use std::mem::size_of;

#[derive(Copy, Clone)]
#[allow(dead_code)]
Expand Down Expand Up @@ -66,15 +53,6 @@ impl AttributeKind {
AttributeKind::UnsignedInt => size_of::<u32>(),
}
}

fn gl_type(self) -> u32 {
match self {
AttributeKind::Float => glow::FLOAT,
AttributeKind::UnsignedByte => glow::UNSIGNED_BYTE,
AttributeKind::UnsignedShort => glow::UNSIGNED_SHORT,
AttributeKind::UnsignedInt => glow::UNSIGNED_INT,
}
}
}

#[derive(Debug, Copy, Clone, Default)]
Expand Down Expand Up @@ -107,121 +85,17 @@ pub struct GeometryBufferDescriptor<'a> {
pub buffers: &'a [VertexBufferDescriptor<'a>],
}

impl GeometryBuffer {
pub fn new(
server: &GlGraphicsServer,
desc: GeometryBufferDescriptor,
) -> Result<Self, FrameworkError> {
let vao = unsafe { server.gl.create_vertex_array()? };

server.set_vertex_array_object(Some(vao));

let element_buffer = GlBuffer::new(server, 0, BufferKind::Index, BufferUsage::StaticDraw)?;

let mut buffers = Vec::new();
for buffer in desc.buffers {
unsafe {
let data_size = buffer.data.bytes.map(|bytes| bytes.len()).unwrap_or(0);

let native_buffer =
GlBuffer::new(server, data_size, BufferKind::Vertex, buffer.usage)?;

if let Some(data) = buffer.data.bytes {
native_buffer.write_data(data)?;
}

let target = native_buffer.kind.into_gl();
server.gl.bind_buffer(target, Some(native_buffer.id));

let mut offset = 0usize;
for definition in buffer.attributes {
server.gl.vertex_attrib_pointer_f32(
definition.location,
definition.component_count as i32,
definition.kind.gl_type(),
definition.normalized,
buffer.data.element_size as i32,
offset as i32,
);
server
.gl
.vertex_attrib_divisor(definition.location, definition.divisor);
server.gl.enable_vertex_attrib_array(definition.location);

offset += definition.kind.size() * definition.component_count;

if offset > buffer.data.element_size {
return Err(FrameworkError::InvalidAttributeDescriptor);
}
}

buffers.push(native_buffer);
}
}

server.set_vertex_array_object(None);

Ok(GeometryBuffer {
state: server.weak(),
vertex_array_object: vao,
buffers,
element_buffer,
element_count: Cell::new(0),
element_kind: desc.element_kind,
thread_mark: PhantomData,
})
}

pub fn set_buffer_data<T: bytemuck::Pod>(&mut self, buffer: usize, data: &[T]) {
self.state
.upgrade()
.unwrap()
.set_vertex_array_object(Some(self.vertex_array_object));
self.buffers[buffer]
.write_data(array_as_u8_slice(data))
.unwrap();
}

pub fn element_count(&self) -> usize {
self.element_count.get()
}

pub fn set_triangles(&self, triangles: &[TriangleDefinition]) {
assert_eq!(self.element_kind, ElementKind::Triangle);
self.element_count.set(triangles.len());
self.set_elements(array_as_u8_slice(triangles));
}

pub fn set_lines(&self, lines: &[[u32; 2]]) {
assert_eq!(self.element_kind, ElementKind::Line);
self.element_count.set(lines.len());
self.set_elements(array_as_u8_slice(lines));
}

fn set_elements(&self, data: &[u8]) {
self.state
.upgrade()
.unwrap()
.set_vertex_array_object(Some(self.vertex_array_object));
self.element_buffer.write_data(data).unwrap()
}

pub fn mode(&self) -> u32 {
match self.element_kind {
ElementKind::Triangle => glow::TRIANGLES,
ElementKind::Line => glow::LINES,
ElementKind::Point => glow::POINTS,
}
}
pub trait GeometryBuffer {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn set_buffer_data(&self, buffer: usize, data: &[u8]);
fn element_count(&self) -> usize;
fn set_triangles(&self, triangles: &[TriangleDefinition]);
fn set_lines(&self, lines: &[[u32; 2]]);
}

impl Drop for GeometryBuffer {
fn drop(&mut self) {
if let Some(state) = self.state.upgrade() {
unsafe {
self.buffers.clear();
state.gl.delete_vertex_array(self.vertex_array_object);
}
}
impl dyn GeometryBuffer {
pub fn set_buffer_data_of_type<T: Pod>(&mut self, buffer: usize, data: &[T]) {
self.set_buffer_data(buffer, array_as_u8_slice(data))
}
}
13 changes: 11 additions & 2 deletions fyrox-graphics/src/gl/framebuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// SOFTWARE.

use crate::framebuffer::BufferDataUsage;
use crate::gl::geometry_buffer::GlGeometryBuffer;
use crate::{
buffer::{Buffer, BufferKind},
core::{color::Color, math::Rect},
Expand Down Expand Up @@ -307,14 +308,18 @@ impl FrameBuffer for GlFrameBuffer {

fn draw(
&mut self,
geometry: &GeometryBuffer,
geometry: &dyn GeometryBuffer,
viewport: Rect<i32>,
program: &dyn GpuProgram,
params: &DrawParameters,
resources: &[ResourceBindGroup],
element_range: ElementRange,
) -> Result<DrawCallStatistics, FrameworkError> {
let server = self.state.upgrade().unwrap();
let geometry = geometry
.as_any()
.downcast_ref::<GlGeometryBuffer>()
.unwrap();

pre_draw(self.id(), &server, viewport, program, params, resources);

Expand Down Expand Up @@ -357,13 +362,17 @@ impl FrameBuffer for GlFrameBuffer {
fn draw_instances(
&mut self,
count: usize,
geometry: &GeometryBuffer,
geometry: &dyn GeometryBuffer,
viewport: Rect<i32>,
program: &dyn GpuProgram,
params: &DrawParameters,
resources: &[ResourceBindGroup],
) -> DrawCallStatistics {
let server = self.state.upgrade().unwrap();
let geometry = geometry
.as_any()
.downcast_ref::<GlGeometryBuffer>()
.unwrap();

pre_draw(self.id(), &server, viewport, program, params, resources);

Expand Down
Loading

0 comments on commit 4f2d505

Please sign in to comment.