Skip to content

Commit

Permalink
renamed PixelBuffer to AsyncReadBuffer + isolated gl-specific code
Browse files Browse the repository at this point in the history
  • Loading branch information
mrDIMAS committed Oct 6, 2024
1 parent fa2c087 commit 7259ec2
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 64 deletions.
1 change: 1 addition & 0 deletions fyrox-graphics/src/gl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod buffer;
pub mod framebuffer;
pub mod program;
pub mod query;
pub mod read_buffer;
pub mod server;
pub mod texture;

Expand Down
16 changes: 16 additions & 0 deletions fyrox-graphics/src/gl/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use crate::gpu_program::SamplerKind;
use crate::{
core::{
algebra::{Matrix2, Matrix3, Matrix4, Vector2, Vector3, Vector4},
Expand All @@ -42,6 +43,21 @@ use std::{
rc::{Rc, Weak},
};

impl SamplerKind {
pub fn glsl_name(&self) -> &str {
match self {
SamplerKind::Sampler1D => "sampler1D",
SamplerKind::Sampler2D => "sampler2D",
SamplerKind::Sampler3D => "sampler3D",
SamplerKind::SamplerCube => "samplerCube",
SamplerKind::USampler1D => "usampler1D",
SamplerKind::USampler2D => "usampler2D",
SamplerKind::USampler3D => "usampler3D",
SamplerKind::USamplerCube => "usamplerCube",
}
}
}

unsafe fn create_shader(
server: &GlGraphicsServer,
name: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,52 +18,56 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use crate::gl::framebuffer::GlFrameBuffer;
use crate::gl::server::GlGraphicsServer;
use crate::gl::ToGlConstant;
use crate::{
buffer::{Buffer, BufferKind, BufferUsage},
core::{algebra::Vector2, math::Rect},
error::FrameworkError,
framebuffer::FrameBuffer,
gl::buffer::GlBuffer,
gl::{buffer::GlBuffer, framebuffer::GlFrameBuffer, server::GlGraphicsServer, ToGlConstant},
gpu_texture::{image_2d_size_bytes, GpuTextureKind},
read_buffer::AsyncReadBuffer,
};
use bytemuck::Pod;
use glow::{HasContext, PixelPackData};
use std::marker::PhantomData;
use std::rc::Weak;

struct ReadRequest {
fence: glow::Fence,
}

pub struct PixelBuffer<T> {
pub struct GlAsyncReadBuffer {
server: Weak<GlGraphicsServer>,
buffer: GlBuffer,
request: Option<ReadRequest>,
pixel_count: usize,
phantom_data: PhantomData<T>,
pixel_size: usize,
}

impl<T> PixelBuffer<T> {
pub fn new(server: &GlGraphicsServer, pixel_count: usize) -> Result<Self, FrameworkError> {
let size_bytes = pixel_count * size_of::<T>();
impl GlAsyncReadBuffer {
pub fn new(
server: &GlGraphicsServer,
pixel_size: usize,
pixel_count: usize,
) -> Result<Self, FrameworkError> {
let size_bytes = pixel_count * pixel_size;
let buffer = GlBuffer::new(
server,
size_bytes,
BufferKind::PixelRead,
BufferUsage::StreamRead,
)?;
Ok(Self {
server: server.weak(),
buffer,
request: None,
pixel_count,
phantom_data: Default::default(),
pixel_size,
})
}
}

pub fn schedule_pixels_transfer(
impl AsyncReadBuffer for GlAsyncReadBuffer {
fn schedule_pixels_transfer(
&mut self,
server: &GlGraphicsServer,
framebuffer: &dyn FrameBuffer,
color_buffer_index: u32,
rect: Option<Rect<i32>>,
Expand All @@ -72,6 +76,8 @@ impl<T> PixelBuffer<T> {
return Ok(());
}

let server = self.server.upgrade().unwrap();

let framebuffer = framebuffer
.as_any()
.downcast_ref::<GlFrameBuffer>()
Expand Down Expand Up @@ -106,7 +112,7 @@ impl<T> PixelBuffer<T> {
color_attachment_size.x,
color_attachment_size.y,
);
let self_bytes_count = self.pixel_count * size_of::<T>();
let self_bytes_count = self.pixel_count * self.pixel_size;
if actual_size != self_bytes_count {
return Err(FrameworkError::Custom(format!(
"Pixel buffer size {} does not match the size {} of the color \
Expand Down Expand Up @@ -164,24 +170,23 @@ impl<T> PixelBuffer<T> {
}
}

pub fn is_request_running(&self) -> bool {
fn is_request_running(&self) -> bool {
self.request.is_some()
}

pub fn try_read(&mut self, server: &GlGraphicsServer) -> Option<Vec<T>>
where
T: Pod + Default + Copy,
{
fn try_read(&mut self) -> Option<Vec<u8>> {
let server = self.server.upgrade()?;

let request = self.request.as_ref()?;

let mut buffer = vec![T::default(); self.pixel_count];
let mut buffer = vec![0; self.pixel_count * self.pixel_size];

unsafe {
// For some reason, glGetSynciv still blocks execution and produces GPU stall, ruining
// the performance. glClientWaitSync with timeout=0 does not have this issue.
let fence_state = server.gl.client_wait_sync(request.fence, 0, 0);
if fence_state != glow::TIMEOUT_EXPIRED && fence_state != glow::WAIT_FAILED {
self.read_internal(&mut buffer);
self.buffer.read_data(&mut buffer).unwrap();

server.gl.delete_sync(request.fence);
self.request = None;
Expand All @@ -192,12 +197,4 @@ impl<T> PixelBuffer<T> {
}
}
}

fn read_internal(&self, buffer: &mut [T])
where
T: Pod,
{
let gl_buffer = &self.buffer as &dyn Buffer;
gl_buffer.read_data_of_type(buffer).unwrap()
}
}
14 changes: 14 additions & 0 deletions fyrox-graphics/src/gl/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
// SOFTWARE.

use crate::gl::program::GlProgram;
use crate::gl::read_buffer::GlAsyncReadBuffer;
use crate::gl::ToGlConstant;
use crate::gpu_program::{GpuProgram, PropertyDefinition};
use crate::read_buffer::AsyncReadBuffer;
use crate::server::{GraphicsServer, ServerCapabilities};
use crate::{
buffer::{Buffer, BufferKind, BufferUsage},
Expand Down Expand Up @@ -1131,6 +1133,18 @@ impl GraphicsServer for GlGraphicsServer {
)?))
}

fn create_async_read_buffer(
&self,
pixel_size: usize,
pixel_count: usize,
) -> Result<Box<dyn AsyncReadBuffer>, FrameworkError> {
Ok(Box::new(GlAsyncReadBuffer::new(
self,
pixel_size,
pixel_count,
)?))
}

fn as_any(&self) -> &dyn Any {
self
}
Expand Down
15 changes: 0 additions & 15 deletions fyrox-graphics/src/gpu_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,21 +133,6 @@ pub enum SamplerKind {
USamplerCube,
}

impl SamplerKind {
pub fn glsl_name(&self) -> &str {
match self {
SamplerKind::Sampler1D => "sampler1D",
SamplerKind::Sampler2D => "sampler2D",
SamplerKind::Sampler3D => "sampler3D",
SamplerKind::SamplerCube => "samplerCube",
SamplerKind::USampler1D => "usampler1D",
SamplerKind::USampler2D => "usampler2D",
SamplerKind::USampler3D => "usampler3D",
SamplerKind::USamplerCube => "usamplerCube",
}
}
}

/// Shader property with default value.
#[derive(Serialize, Deserialize, Debug, PartialEq, Reflect, Visit)]
pub enum PropertyKind {
Expand Down
2 changes: 1 addition & 1 deletion fyrox-graphics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ pub mod geometry_buffer;
pub mod gl;
pub mod gpu_program;
pub mod gpu_texture;
pub mod pixel_buffer;
pub mod query;
pub mod read_buffer;
pub mod server;
pub mod stats;
pub mod uniform;
Expand Down
51 changes: 51 additions & 0 deletions fyrox-graphics/src/read_buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use crate::{core::math::Rect, error::FrameworkError, framebuffer::FrameBuffer};
use bytemuck::Pod;

pub trait AsyncReadBuffer {
fn schedule_pixels_transfer(
&mut self,
framebuffer: &dyn FrameBuffer,
color_buffer_index: u32,
rect: Option<Rect<i32>>,
) -> Result<(), FrameworkError>;
fn is_request_running(&self) -> bool;
fn try_read(&mut self) -> Option<Vec<u8>>;
}

impl dyn AsyncReadBuffer {
pub fn try_read_of_type<T>(&mut self) -> Option<Vec<T>>
where
T: Pod,
{
let mut bytes = self.try_read()?;
let typed = unsafe {
Some(Vec::from_raw_parts(
bytes.as_mut_ptr() as *mut T,
bytes.len() / size_of::<T>(),
bytes.capacity() / size_of::<T>(),
))
};
std::mem::forget(bytes);
typed
}
}
8 changes: 7 additions & 1 deletion fyrox-graphics/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use crate::gpu_program::{GpuProgram, PropertyDefinition};
use crate::{
buffer::{Buffer, BufferKind, BufferUsage},
error::FrameworkError,
framebuffer::{Attachment, FrameBuffer},
gpu_program::{GpuProgram, PropertyDefinition},
gpu_texture::{GpuTexture, GpuTextureKind, MagnificationFilter, MinificationFilter, PixelKind},
query::Query,
read_buffer::AsyncReadBuffer,
stats::PipelineStatistics,
};
use std::{
Expand Down Expand Up @@ -91,6 +92,11 @@ pub trait GraphicsServer: Any {
fragment_source: &str,
properties: &[PropertyDefinition],
) -> Result<Box<dyn GpuProgram>, FrameworkError>;
fn create_async_read_buffer(
&self,
pixel_size: usize,
pixel_count: usize,
) -> Result<Box<dyn AsyncReadBuffer>, FrameworkError>;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn weak(self: Rc<Self>) -> Weak<dyn GraphicsServer>;
Expand Down
3 changes: 1 addition & 2 deletions fyrox-impl/src/renderer/gbuffer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,7 @@ impl GBuffer {
let view_projection = camera.view_projection_matrix();

if quality_settings.use_occlusion_culling {
self.occlusion_tester
.try_query_visibility_results(server, graph);
self.occlusion_tester.try_query_visibility_results(graph);
};

let viewport = Rect::new(0, 0, self.width, self.height);
Expand Down
6 changes: 2 additions & 4 deletions fyrox-impl/src/renderer/occlusion/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,8 @@ impl OcclusionTester {
})
}

pub fn try_query_visibility_results(&mut self, server: &GlGraphicsServer, graph: &Graph) {
let Some(visibility_buffer) = self
.visibility_buffer_optimizer
.read_visibility_mask(server)
pub fn try_query_visibility_results(&mut self, graph: &Graph) {
let Some(visibility_buffer) = self.visibility_buffer_optimizer.read_visibility_mask()
else {
return;
};
Expand Down
Loading

0 comments on commit 7259ec2

Please sign in to comment.