#![warn(missing_docs)]
use crate::sampler::GpuSampler;
use crate::{
buffer::GpuBuffer,
core::{color::Color, math::Rect},
define_shared_wrapper,
error::FrameworkError,
geometry_buffer::GpuGeometryBuffer,
gpu_program::GpuProgram,
gpu_texture::{CubeMapFace, GpuTexture},
DrawParameters, ElementRange,
};
use bytemuck::Pod;
use fyrox_core::define_as_any_trait;
use std::cell::Cell;
#[derive(Copy, Clone, PartialOrd, PartialEq, Hash, Debug, Eq)]
pub enum AttachmentKind {
Color,
DepthStencil,
Depth,
}
pub struct Attachment {
pub kind: AttachmentKind,
pub texture: GpuTexture,
level: Cell<usize>,
cube_map_face: Cell<Option<CubeMapFace>>,
}
impl Attachment {
pub fn level(&self) -> usize {
self.level.get()
}
pub fn cube_map_face(&self) -> Option<CubeMapFace> {
self.cube_map_face.get()
}
pub fn set_level(&self, level: usize) {
self.level.set(level)
}
pub fn set_cube_map_face(&self, face: Option<CubeMapFace>) {
self.cube_map_face.set(face)
}
pub fn color(texture: GpuTexture) -> Self {
Self {
kind: AttachmentKind::Color,
texture,
level: Cell::new(0),
cube_map_face: Cell::new(None),
}
}
pub fn color_with_level(texture: GpuTexture, level: usize) -> Self {
Self {
kind: AttachmentKind::Color,
texture,
level: Cell::new(level),
cube_map_face: Cell::new(None),
}
}
pub fn color_with_face(texture: GpuTexture, cube_map_face: CubeMapFace) -> Self {
Self {
kind: AttachmentKind::Color,
texture,
level: Cell::new(0),
cube_map_face: Cell::new(Some(cube_map_face)),
}
}
pub fn depth(texture: GpuTexture) -> Self {
Self {
kind: AttachmentKind::Depth,
texture,
level: Cell::new(0),
cube_map_face: Cell::new(None),
}
}
pub fn depth_stencil(texture: GpuTexture) -> Self {
Self {
kind: AttachmentKind::DepthStencil,
texture,
level: Cell::new(0),
cube_map_face: Cell::new(None),
}
}
}
#[derive(Default)]
pub enum BufferDataUsage {
#[default]
UseEverything,
UseSegment {
offset: usize,
size: usize,
},
}
pub enum ResourceBinding {
Texture {
texture: GpuTexture,
sampler: GpuSampler,
binding: usize,
},
Buffer {
buffer: GpuBuffer,
binding: usize,
data_usage: BufferDataUsage,
},
}
impl ResourceBinding {
pub fn texture(texture: &GpuTexture, sampler: &GpuSampler, binding: usize) -> Self {
Self::Texture {
texture: texture.clone(),
sampler: sampler.clone(),
binding,
}
}
pub fn buffer(buffer: &GpuBuffer, binding: usize, data_usage: BufferDataUsage) -> Self {
Self::Buffer {
buffer: buffer.clone(),
binding,
data_usage,
}
}
}
pub struct ResourceBindGroup<'a> {
pub bindings: &'a [ResourceBinding],
}
#[derive(Debug, Copy, Clone, Default)]
#[must_use]
pub struct DrawCallStatistics {
pub triangles: usize,
}
define_as_any_trait!(GpuFrameBufferAsAny => GpuFrameBufferTrait);
pub enum ReadTarget {
Depth,
Stencil,
Color(usize),
}
pub trait GpuFrameBufferTrait: GpuFrameBufferAsAny {
fn color_attachments(&self) -> &[Attachment];
fn depth_attachment(&self) -> Option<&Attachment>;
fn set_cubemap_face(&self, attachment_index: usize, face: CubeMapFace, level: usize);
fn blit_to(
&self,
dest: &GpuFrameBuffer,
src_x0: i32,
src_y0: i32,
src_x1: i32,
src_y1: i32,
dst_x0: i32,
dst_y0: i32,
dst_x1: i32,
dst_y1: i32,
copy_color: bool,
copy_depth: bool,
copy_stencil: bool,
);
fn clear(
&self,
viewport: Rect<i32>,
color: Option<Color>,
depth: Option<f32>,
stencil: Option<i32>,
);
fn read_pixels(&self, read_target: ReadTarget) -> Option<Vec<u8>>;
fn draw(
&self,
geometry: &GpuGeometryBuffer,
viewport: Rect<i32>,
program: &GpuProgram,
params: &DrawParameters,
resources: &[ResourceBindGroup],
element_range: ElementRange,
) -> Result<DrawCallStatistics, FrameworkError>;
fn draw_instances(
&self,
instance_count: usize,
geometry: &GpuGeometryBuffer,
viewport: Rect<i32>,
program: &GpuProgram,
params: &DrawParameters,
resources: &[ResourceBindGroup],
element_range: ElementRange,
) -> Result<DrawCallStatistics, FrameworkError>;
}
impl dyn GpuFrameBufferTrait {
pub fn read_pixels_of_type<T>(&self, read_target: ReadTarget) -> Option<Vec<T>>
where
T: Pod,
{
let mut bytes = self.read_pixels(read_target)?;
let typed = unsafe {
Vec::<T>::from_raw_parts(
bytes.as_mut_ptr() as *mut T,
bytes.len() / size_of::<T>(),
bytes.capacity() / size_of::<T>(),
)
};
std::mem::forget(bytes);
Some(typed)
}
}
define_shared_wrapper!(GpuFrameBuffer<dyn GpuFrameBufferTrait>);