#![warn(missing_docs)]
use crate::{
buffer::{GpuBuffer, GpuBufferDescriptor},
error::FrameworkError,
framebuffer::{Attachment, GpuFrameBuffer},
geometry_buffer::{GpuGeometryBuffer, GpuGeometryBufferDescriptor},
gpu_program::{GpuProgram, GpuShader, ShaderKind, ShaderResourceDefinition},
gpu_texture::{GpuTexture, GpuTextureDescriptor, GpuTextureKind, PixelKind},
query::GpuQuery,
read_buffer::GpuAsyncReadBuffer,
sampler::{GpuSampler, GpuSamplerDescriptor},
stats::PipelineStatistics,
PolygonFace, PolygonFillMode,
};
use fyrox_core::define_as_any_trait;
use std::fmt::{Display, Formatter};
use std::rc::{Rc, Weak};
#[derive(Debug)]
pub struct ServerCapabilities {
pub max_uniform_block_size: usize,
pub uniform_buffer_offset_alignment: usize,
pub max_lod_bias: f32,
}
#[derive(Default, Debug, Clone)]
pub struct ServerMemoryUsage {
pub textures: usize,
pub buffers: usize,
}
impl Display for ServerMemoryUsage {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
const MEGABYTE: f32 = 1024.0 * 1024.0;
write!(
f,
"Textures: {:.3} Mb\nBuffers: {:.3} Mb",
self.textures as f32 / MEGABYTE,
self.buffers as f32 / MEGABYTE
)
}
}
pub type SharedGraphicsServer = Rc<dyn GraphicsServer>;
define_as_any_trait!(GraphicsServerAsAny => GraphicsServer);
pub struct RenderingScope {
server: Weak<dyn GraphicsServer>,
}
impl Drop for RenderingScope {
fn drop(&mut self) {
if let Some(server) = self.server.upgrade() {
server.pop_debug_group();
}
}
}
pub trait GraphicsServer: GraphicsServerAsAny {
fn create_buffer(&self, desc: GpuBufferDescriptor) -> Result<GpuBuffer, FrameworkError>;
fn create_texture(&self, desc: GpuTextureDescriptor) -> Result<GpuTexture, FrameworkError>;
fn create_sampler(&self, desc: GpuSamplerDescriptor) -> Result<GpuSampler, FrameworkError>;
fn create_frame_buffer(
&self,
depth_attachment: Option<Attachment>,
color_attachments: Vec<Attachment>,
) -> Result<GpuFrameBuffer, FrameworkError>;
fn back_buffer(&self) -> GpuFrameBuffer;
fn create_query(&self) -> Result<GpuQuery, FrameworkError>;
fn create_shader(
&self,
name: String,
kind: ShaderKind,
source: String,
resources: &[ShaderResourceDefinition],
line_offset: isize,
) -> Result<GpuShader, FrameworkError>;
fn create_program(
&self,
name: &str,
vertex_source: String,
vertex_source_line_offset: isize,
fragment_source: String,
fragment_source_line_offset: isize,
resources: &[ShaderResourceDefinition],
) -> Result<GpuProgram, FrameworkError>;
fn create_program_from_shaders(
&self,
name: &str,
vertex_shader: &GpuShader,
fragment_shader: &GpuShader,
resources: &[ShaderResourceDefinition],
) -> Result<GpuProgram, FrameworkError>;
fn create_async_read_buffer(
&self,
name: &str,
pixel_size: usize,
pixel_count: usize,
) -> Result<GpuAsyncReadBuffer, FrameworkError>;
fn create_geometry_buffer(
&self,
desc: GpuGeometryBufferDescriptor,
) -> Result<GpuGeometryBuffer, FrameworkError>;
fn weak(&self) -> Weak<dyn GraphicsServer>;
fn flush(&self);
fn finish(&self);
fn invalidate_resource_bindings_cache(&self);
fn pipeline_statistics(&self) -> PipelineStatistics;
fn swap_buffers(&self) -> Result<(), FrameworkError>;
fn set_frame_size(&self, new_size: (u32, u32));
fn capabilities(&self) -> ServerCapabilities;
fn set_polygon_fill_mode(&self, polygon_face: PolygonFace, polygon_fill_mode: PolygonFillMode);
fn generate_mipmap(&self, texture: &GpuTexture);
fn memory_usage(&self) -> ServerMemoryUsage;
fn push_debug_group(&self, name: &str);
fn pop_debug_group(&self);
fn begin_scope(&self, name: &str) -> RenderingScope {
self.push_debug_group(name);
RenderingScope {
server: self.weak(),
}
}
fn create_2d_render_target(
&self,
name: &str,
pixel_kind: PixelKind,
width: usize,
height: usize,
) -> Result<GpuTexture, FrameworkError> {
self.create_texture(GpuTextureDescriptor {
name,
kind: GpuTextureKind::Rectangle { width, height },
pixel_kind,
..Default::default()
})
}
fn create_cube_render_target(
&self,
name: &str,
pixel_kind: PixelKind,
size: usize,
) -> Result<GpuTexture, FrameworkError> {
self.create_texture(GpuTextureDescriptor {
name,
kind: GpuTextureKind::Cube { size },
pixel_kind,
..Default::default()
})
}
}