gl: very not nicely make dsa a runtime prop

This commit is contained in:
chyyran 2022-11-30 17:21:32 -05:00
parent 8d940d6f79
commit 759cd4bc28
16 changed files with 333 additions and 324 deletions

View file

@ -9,7 +9,7 @@ use crate::util::{gl_get_version, gl_u16_to_version};
use gl::types::{GLint, GLuint}; use gl::types::{GLint, GLuint};
use crate::binding::BufferStorage; use crate::binding::BufferStorage;
use crate::gl::{DrawQuad, Framebuffer, GLInterface, LoadLut, UboRing}; use crate::gl::{DrawQuad, Framebuffer, FramebufferInterface, GLInterface, LoadLut, UboRing};
use crate::options::{FilterChainOptions, FrameOptions}; use crate::options::{FilterChainOptions, FrameOptions};
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::texture::Texture; use crate::texture::Texture;
@ -30,20 +30,75 @@ use spirv_cross::spirv::Decoration;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::path::Path; use std::path::Path;
pub struct FilterChain<T: GLInterface> { pub struct FilterChain {
filter: FilterChainInner
}
impl FilterChain {
pub fn load_from_preset(
preset: ShaderPreset,
options: Option<&FilterChainOptions>,
) -> Result<Self> {
if let Some(options) = options && options.use_dsa {
return Ok(Self {
filter: FilterChainInner::DSA(FilterChainImpl::load_from_preset(preset, Some(options))?)
})
}
return Ok(Self {
filter: FilterChainInner::Compatibility(FilterChainImpl::load_from_preset(preset, options)?)
})
}
/// Load the shader preset at the given path into a filter chain.
pub fn load_from_path(
path: impl AsRef<Path>,
options: Option<&FilterChainOptions>,
) -> Result<Self> {
// load passes from preset
let preset = ShaderPreset::try_parse(path)?;
Self::load_from_preset(preset, options)
}
/// Process a frame with the input image.
///
/// When this frame returns, GL_FRAMEBUFFER is bound to 0.
pub fn frame(
&mut self,
count: usize,
viewport: &Viewport,
input: &GLImage,
options: Option<&FrameOptions>,
) -> Result<()> {
match &mut self.filter {
FilterChainInner::DSA(p) => {
p.frame(count, viewport, input, options)
}
FilterChainInner::Compatibility(p) => {
p.frame(count, viewport, input, options)
}
}
}
}
enum FilterChainInner {
DSA(FilterChainImpl<crate::gl::gl46::DirectStateAccessGL>),
Compatibility(FilterChainImpl<crate::gl::gl3::CompatibilityGL>)
}
struct FilterChainImpl<T: GLInterface> {
passes: Box<[FilterPass<T>]>, passes: Box<[FilterPass<T>]>,
common: FilterCommon, common: FilterCommon,
pub(crate) draw_quad: T::DrawQuad, pub(crate) draw_quad: T::DrawQuad,
output_framebuffers: Box<[T::Framebuffer]>, output_framebuffers: Box<[Framebuffer]>,
feedback_framebuffers: Box<[T::Framebuffer]>, feedback_framebuffers: Box<[Framebuffer]>,
history_framebuffers: VecDeque<T::Framebuffer>, history_framebuffers: VecDeque<Framebuffer>,
} }
pub struct FilterCommon { pub(crate) struct FilterCommon {
// semantics: ReflectSemantics, // semantics: ReflectSemantics,
pub(crate) config: FilterMutable, pub config: FilterMutable,
pub(crate) luts: FxHashMap<usize, Texture>, pub luts: FxHashMap<usize, Texture>,
pub(crate) samplers: SamplerSet, pub samplers: SamplerSet,
pub output_textures: Box<[Texture]>, pub output_textures: Box<[Texture]>,
pub feedback_textures: Box<[Texture]>, pub feedback_textures: Box<[Texture]>,
pub history_textures: Box<[Texture]>, pub history_textures: Box<[Texture]>,
@ -54,7 +109,7 @@ pub struct FilterMutable {
pub(crate) parameters: FxHashMap<String, f32>, pub(crate) parameters: FxHashMap<String, f32>,
} }
impl<T: GLInterface> FilterChain<T> { impl<T: GLInterface> FilterChainImpl<T> {
fn reflect_uniform_location(pipeline: GLuint, meta: &impl UniformMeta) -> VariableLocation { fn reflect_uniform_location(pipeline: GLuint, meta: &impl UniformMeta) -> VariableLocation {
// todo: support both ubo and pushco // todo: support both ubo and pushco
// todo: fix this. // todo: fix this.
@ -91,9 +146,9 @@ type ShaderPassMeta = (
>, >,
); );
impl<T: GLInterface> FilterChain<T> { impl<T: GLInterface> FilterChainImpl<T> {
/// Load a filter chain from a pre-parsed `ShaderPreset`. /// Load a filter chain from a pre-parsed `ShaderPreset`.
pub fn load_from_preset( pub(crate) fn load_from_preset(
preset: ShaderPreset, preset: ShaderPreset,
options: Option<&FilterChainOptions>, options: Option<&FilterChainOptions>,
) -> Result<Self> { ) -> Result<Self> {
@ -116,13 +171,13 @@ impl<T: GLInterface> FilterChain<T> {
// initialize output framebuffers // initialize output framebuffers
let mut output_framebuffers = Vec::new(); let mut output_framebuffers = Vec::new();
output_framebuffers.resize_with(filters.len(), || Framebuffer::new(1)); output_framebuffers.resize_with(filters.len(), || T::FramebufferInterface::new(1));
let mut output_textures = Vec::new(); let mut output_textures = Vec::new();
output_textures.resize_with(filters.len(), Texture::default); output_textures.resize_with(filters.len(), Texture::default);
// initialize feedback framebuffers // initialize feedback framebuffers
let mut feedback_framebuffers = Vec::new(); let mut feedback_framebuffers = Vec::new();
feedback_framebuffers.resize_with(filters.len(), || Framebuffer::new(1)); feedback_framebuffers.resize_with(filters.len(), || T::FramebufferInterface::new(1));
let mut feedback_textures = Vec::new(); let mut feedback_textures = Vec::new();
feedback_textures.resize_with(filters.len(), Texture::default); feedback_textures.resize_with(filters.len(), Texture::default);
@ -130,12 +185,12 @@ impl<T: GLInterface> FilterChain<T> {
let luts = T::LoadLut::load_luts(&preset.textures)?; let luts = T::LoadLut::load_luts(&preset.textures)?;
let (history_framebuffers, history_textures) = let (history_framebuffers, history_textures) =
FilterChain::init_history(&filters, default_filter, default_wrap); FilterChainImpl::init_history(&filters, default_filter, default_wrap);
// create vertex objects // create vertex objects
let draw_quad = T::DrawQuad::new(); let draw_quad = T::DrawQuad::new();
Ok(FilterChain { Ok(FilterChainImpl {
passes: filters, passes: filters,
output_framebuffers: output_framebuffers.into_boxed_slice(), output_framebuffers: output_framebuffers.into_boxed_slice(),
feedback_framebuffers: feedback_framebuffers.into_boxed_slice(), feedback_framebuffers: feedback_framebuffers.into_boxed_slice(),
@ -159,16 +214,6 @@ impl<T: GLInterface> FilterChain<T> {
}) })
} }
/// Load the shader preset at the given path into a filter chain.
pub fn load_from_path(
path: impl AsRef<Path>,
options: Option<&FilterChainOptions>,
) -> Result<Self> {
// load passes from preset
let preset = ShaderPreset::try_parse(path)?;
Self::load_from_preset(preset, options)
}
fn load_preset( fn load_preset(
passes: Vec<ShaderPassConfig>, passes: Vec<ShaderPassConfig>,
textures: &[TextureConfig], textures: &[TextureConfig],
@ -363,7 +408,7 @@ impl<T: GLInterface> FilterChain<T> {
filters: &[FilterPass<T>], filters: &[FilterPass<T>],
filter: FilterMode, filter: FilterMode,
wrap_mode: WrapMode, wrap_mode: WrapMode,
) -> (VecDeque<T::Framebuffer>, Box<[Texture]>) { ) -> (VecDeque<Framebuffer>, Box<[Texture]>) {
let mut required_images = 0; let mut required_images = 0;
for pass in filters { for pass in filters {
@ -397,7 +442,7 @@ impl<T: GLInterface> FilterChain<T> {
eprintln!("[history] using frame history with {required_images} images"); eprintln!("[history] using frame history with {required_images} images");
let mut framebuffers = VecDeque::with_capacity(required_images); let mut framebuffers = VecDeque::with_capacity(required_images);
framebuffers.resize_with(required_images, || Framebuffer::new(1)); framebuffers.resize_with(required_images, || T::FramebufferInterface::new(1));
let mut history_textures = Vec::new(); let mut history_textures = Vec::new();
history_textures.resize_with(required_images, || Texture { history_textures.resize_with(required_images, || Texture {
@ -412,12 +457,12 @@ impl<T: GLInterface> FilterChain<T> {
fn push_history(&mut self, input: &GLImage) -> Result<()> { fn push_history(&mut self, input: &GLImage) -> Result<()> {
if let Some(mut back) = self.history_framebuffers.pop_back() { if let Some(mut back) = self.history_framebuffers.pop_back() {
if back.size() != input.size || (input.format != 0 && input.format != back.format()) { if back.size != input.size || (input.format != 0 && input.format != back.format) {
eprintln!("[history] resizing"); eprintln!("[history] resizing");
back.init(input.size, input.format)?; T::FramebufferInterface::init(&mut back, input.size, input.format)?;
} }
back.copy_from(input)?; back.copy_from::<T::FramebufferInterface>(input)?;
self.history_framebuffers.push_front(back) self.history_framebuffers.push_front(back)
} }
@ -431,7 +476,7 @@ impl<T: GLInterface> FilterChain<T> {
pub fn frame( pub fn frame(
&mut self, &mut self,
count: usize, count: usize,
viewport: &Viewport<T::Framebuffer>, viewport: &Viewport,
input: &GLImage, input: &GLImage,
options: Option<&FrameOptions>, options: Option<&FrameOptions>,
) -> Result<()> { ) -> Result<()> {
@ -440,7 +485,7 @@ impl<T: GLInterface> FilterChain<T> {
if let Some(options) = options { if let Some(options) = options {
if options.clear_history { if options.clear_history {
for framebuffer in &self.history_framebuffers { for framebuffer in &self.history_framebuffers {
framebuffer.clear::<true>() framebuffer.clear::<T::FramebufferInterface, true>()
} }
} }
} }
@ -490,7 +535,7 @@ impl<T: GLInterface> FilterChain<T> {
// rescale render buffers to ensure all bindings are valid. // rescale render buffers to ensure all bindings are valid.
for (index, pass) in passes.iter_mut().enumerate() { for (index, pass) in passes.iter_mut().enumerate() {
self.output_framebuffers[index].scale( self.output_framebuffers[index].scale::<T::FramebufferInterface>(
pass.config.scaling.clone(), pass.config.scaling.clone(),
pass.get_format(), pass.get_format(),
viewport, viewport,
@ -498,7 +543,7 @@ impl<T: GLInterface> FilterChain<T> {
&source, &source,
)?; )?;
self.feedback_framebuffers[index].scale( self.feedback_framebuffers[index].scale::<T::FramebufferInterface>(
pass.config.scaling.clone(), pass.config.scaling.clone(),
pass.get_format(), pass.get_format(),
viewport, viewport,

View file

@ -14,7 +14,7 @@ use rustc_hash::FxHashMap;
use crate::binding::{BufferStorage, UniformLocation, VariableLocation}; use crate::binding::{BufferStorage, UniformLocation, VariableLocation};
use crate::filter_chain::FilterCommon; use crate::filter_chain::FilterCommon;
use crate::framebuffer::Viewport; use crate::framebuffer::Viewport;
use crate::gl::{BindTexture, Framebuffer, GLInterface, UboRing}; use crate::gl::{BindTexture, FramebufferInterface, GLInterface, UboRing};
use crate::render_target::RenderTarget; use crate::render_target::RenderTarget;
use crate::texture::Texture; use crate::texture::Texture;
@ -39,15 +39,15 @@ impl<T: GLInterface> FilterPass<T> {
parent: &FilterCommon, parent: &FilterCommon,
frame_count: u32, frame_count: u32,
frame_direction: i32, frame_direction: i32,
viewport: &Viewport<T::Framebuffer>, viewport: &Viewport,
original: &Texture, original: &Texture,
source: &Texture, source: &Texture,
output: RenderTarget<T::Framebuffer>, output: RenderTarget,
) { ) {
let framebuffer = output.framebuffer; let framebuffer = output.framebuffer;
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle()); gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle);
gl::UseProgram(self.program); gl::UseProgram(self.program);
} }
@ -57,7 +57,7 @@ impl<T: GLInterface> FilterPass<T> {
output.mvp, output.mvp,
frame_count, frame_count,
frame_direction, frame_direction,
framebuffer.size(), framebuffer.size,
viewport, viewport,
original, original,
source, source,
@ -73,9 +73,9 @@ impl<T: GLInterface> FilterPass<T> {
unsafe { unsafe {
// can't use framebuffer.clear because it will unbind. // can't use framebuffer.clear because it will unbind.
framebuffer.clear::<false>(); framebuffer.clear::<T::FramebufferInterface, false>();
let framebuffer_size = framebuffer.size(); let framebuffer_size = framebuffer.size;
gl::Viewport( gl::Viewport(
output.x, output.x,
output.y, output.y,
@ -83,7 +83,7 @@ impl<T: GLInterface> FilterPass<T> {
framebuffer_size.height as GLsizei, framebuffer_size.height as GLsizei,
); );
if framebuffer.format() == gl::SRGB8_ALPHA8 { if framebuffer.format == gl::SRGB8_ALPHA8 {
gl::Enable(gl::FRAMEBUFFER_SRGB); gl::Enable(gl::FRAMEBUFFER_SRGB);
} else { } else {
gl::Disable(gl::FRAMEBUFFER_SRGB); gl::Disable(gl::FRAMEBUFFER_SRGB);
@ -120,7 +120,7 @@ impl<T: GLInterface> FilterPass<T> {
frame_count: u32, frame_count: u32,
frame_direction: i32, frame_direction: i32,
fb_size: Size<u32>, fb_size: Size<u32>,
viewport: &Viewport<T::Framebuffer>, viewport: &Viewport,
original: &Texture, original: &Texture,
source: &Texture, source: &Texture,
) { ) {
@ -145,7 +145,7 @@ impl<T: GLInterface> FilterPass<T> {
.get(&VariableSemantics::FinalViewport.into()) .get(&VariableSemantics::FinalViewport.into())
{ {
self.uniform_storage self.uniform_storage
.bind_vec4(*offset, viewport.output.size(), location.location()); .bind_vec4(*offset, viewport.output.size, location.location());
} }
// bind FrameCount // bind FrameCount

View file

@ -1,13 +1,13 @@
use gl::types::{GLenum, GLuint}; use gl::types::{GLenum, GLuint};
use librashader_common::Size; use librashader_common::Size;
use crate::gl::Framebuffer; use crate::gl::{Framebuffer, FramebufferInterface};
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Viewport<'a, T: Framebuffer + ?Sized> { pub struct Viewport<'a> {
pub x: i32, pub x: i32,
pub y: i32, pub y: i32,
pub output: &'a T, pub output: &'a Framebuffer,
pub mvp: Option<&'a [f32; 16]>, pub mvp: Option<&'a [f32; 16]>,
} }

View file

@ -0,0 +1,81 @@
use crate::error::Result;
use crate::framebuffer::GLImage;
use crate::gl::FramebufferInterface;
use crate::texture::Texture;
use crate::Viewport;
use gl::types::{GLenum, GLuint};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D;
#[derive(Debug)]
pub struct Framebuffer {
pub image: GLuint,
pub handle: GLuint,
pub size: Size<u32>,
pub format: GLenum,
pub max_levels: u32,
pub mip_levels: u32,
pub is_raw: bool,
}
impl Framebuffer {
pub fn new<T: FramebufferInterface>(max_levels: u32) -> Self {
T::new(max_levels)
}
pub fn new_from_raw<T: FramebufferInterface>(
texture: GLuint,
handle: GLuint,
format: GLenum,
size: Size<u32>,
mip_levels: u32,
) -> Self {
T::new_from_raw(texture, handle, format, size, mip_levels)
}
pub fn clear<T: FramebufferInterface, const REBIND: bool>(&self) {
T::clear::<REBIND>(&self)
}
pub fn scale<T: FramebufferInterface>(
&mut self,
scaling: Scale2D,
format: ImageFormat,
viewport: &Viewport,
original: &Texture,
source: &Texture,
) -> Result<Size<u32>> {
T::scale(self, scaling, format, viewport, original, source)
}
pub fn copy_from<T: FramebufferInterface>(&mut self, image: &GLImage) -> Result<()> {
T::copy_from(self, image)
}
pub fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> Texture {
Texture {
image: GLImage {
handle: self.image,
format: self.format,
size: self.size,
padded_size: Default::default(),
},
filter,
mip_filter: filter,
wrap_mode,
}
}
}
impl Drop for Framebuffer {
fn drop(&mut self) {
unsafe {
if self.handle != 0 {
gl::DeleteFramebuffers(1, &self.handle);
}
if self.image != 0 {
gl::DeleteTextures(1, &self.image);
}
}
}
}

View file

@ -1,40 +1,17 @@
use crate::error::{FilterChainError, Result}; use crate::error::{FilterChainError, Result};
use crate::framebuffer::{GLImage, Viewport}; use crate::framebuffer::{GLImage, Viewport};
use crate::gl::Framebuffer; use crate::gl::framebuffer::Framebuffer;
use crate::gl::FramebufferInterface;
use crate::texture::Texture; use crate::texture::Texture;
use gl::types::{GLenum, GLint, GLsizei, GLuint}; use gl::types::{GLenum, GLint, GLsizei, GLuint};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D; use librashader_presets::Scale2D;
#[derive(Debug)] #[derive(Debug)]
pub struct Gl3Framebuffer { pub struct Gl3Framebuffer;
image: GLuint,
handle: GLuint,
size: Size<u32>,
format: GLenum,
max_levels: u32,
mip_levels: u32,
is_raw: bool,
}
impl Framebuffer for Gl3Framebuffer { impl FramebufferInterface for Gl3Framebuffer {
fn handle(&self) -> GLuint { fn new(max_levels: u32) -> Framebuffer {
self.handle
}
fn size(&self) -> Size<u32> {
self.size
}
fn image(&self) -> GLuint {
self.image
}
fn format(&self) -> GLenum {
self.format
}
fn new(max_levels: u32) -> Gl3Framebuffer {
let mut framebuffer = 0; let mut framebuffer = 0;
unsafe { unsafe {
gl::GenFramebuffers(1, &mut framebuffer); gl::GenFramebuffers(1, &mut framebuffer);
@ -42,7 +19,7 @@ impl Framebuffer for Gl3Framebuffer {
gl::BindFramebuffer(gl::FRAMEBUFFER, 0); gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
} }
Gl3Framebuffer { Framebuffer {
image: 0, image: 0,
size: Size { size: Size {
width: 1, width: 1,
@ -61,8 +38,8 @@ impl Framebuffer for Gl3Framebuffer {
format: GLenum, format: GLenum,
size: Size<u32>, size: Size<u32>,
miplevels: u32, miplevels: u32,
) -> Gl3Framebuffer { ) -> Framebuffer {
Gl3Framebuffer { Framebuffer {
image: texture, image: texture,
size, size,
format, format,
@ -72,38 +49,27 @@ impl Framebuffer for Gl3Framebuffer {
is_raw: true, is_raw: true,
} }
} }
fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> Texture {
Texture {
image: GLImage {
handle: self.image,
format: self.format,
size: self.size,
padded_size: Default::default(),
},
filter,
mip_filter: filter,
wrap_mode,
}
}
fn scale( fn scale(
&mut self, fb: &mut Framebuffer,
scaling: Scale2D, scaling: Scale2D,
format: ImageFormat, format: ImageFormat,
viewport: &Viewport<Self>, viewport: &Viewport,
_original: &Texture, _original: &Texture,
source: &Texture, source: &Texture,
) -> Result<Size<u32>> { ) -> Result<Size<u32>> {
if self.is_raw { if fb.is_raw {
return Ok(self.size); return Ok(fb.size);
} }
let size = let size =
librashader_runtime::scaling::scale(scaling, source.image.size, viewport.output.size); librashader_runtime::scaling::scale(scaling, source.image.size, viewport.output.size);
if self.size != size { if fb.size != size {
self.size = size; fb.size = size;
self.init( Self::init(
fb,
size, size,
if format == ImageFormat::Unknown { if format == ImageFormat::Unknown {
ImageFormat::R8G8B8A8Unorm ImageFormat::R8G8B8A8Unorm
@ -114,10 +80,10 @@ impl Framebuffer for Gl3Framebuffer {
} }
Ok(size) Ok(size)
} }
fn clear<const REBIND: bool>(&self) { fn clear<const REBIND: bool>(fb: &Framebuffer) {
unsafe { unsafe {
if REBIND { if REBIND {
gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle); gl::BindFramebuffer(gl::FRAMEBUFFER, fb.handle);
} }
gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE);
gl::ClearColor(0.0, 0.0, 0.0, 0.0); gl::ClearColor(0.0, 0.0, 0.0, 0.0);
@ -127,14 +93,15 @@ impl Framebuffer for Gl3Framebuffer {
} }
} }
} }
fn copy_from(&mut self, image: &GLImage) -> Result<()> { fn copy_from(fb: &mut Framebuffer, image: &GLImage) -> Result<()> {
// todo: may want to use a shader and draw a quad to be faster. // todo: may want to use a shader and draw a quad to be faster.
if image.size != self.size || image.format != self.format { if image.size != fb.size || image.format != fb.format {
self.init(image.size, image.format)?; Self::init(
fb,image.size, image.format)?;
} }
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle); gl::BindFramebuffer(gl::FRAMEBUFFER, fb.handle);
gl::FramebufferTexture2D( gl::FramebufferTexture2D(
gl::READ_FRAMEBUFFER, gl::READ_FRAMEBUFFER,
@ -148,7 +115,7 @@ impl Framebuffer for Gl3Framebuffer {
gl::DRAW_FRAMEBUFFER, gl::DRAW_FRAMEBUFFER,
gl::COLOR_ATTACHMENT1, gl::COLOR_ATTACHMENT1,
gl::TEXTURE_2D, gl::TEXTURE_2D,
self.image, fb.image,
0, 0,
); );
gl::ReadBuffer(gl::COLOR_ATTACHMENT0); gl::ReadBuffer(gl::COLOR_ATTACHMENT0);
@ -156,12 +123,12 @@ impl Framebuffer for Gl3Framebuffer {
gl::BlitFramebuffer( gl::BlitFramebuffer(
0, 0,
0, 0,
self.size.width as GLint, fb.size.width as GLint,
self.size.height as GLint, fb.size.height as GLint,
0, 0,
0, 0,
self.size.width as GLint, fb.size.width as GLint,
self.size.height as GLint, fb.size.height as GLint,
gl::COLOR_BUFFER_BIT, gl::COLOR_BUFFER_BIT,
gl::NEAREST, gl::NEAREST,
); );
@ -188,7 +155,7 @@ impl Framebuffer for Gl3Framebuffer {
gl::FRAMEBUFFER, gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0, gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D, gl::TEXTURE_2D,
self.image, fb.image,
0, 0,
); );
@ -197,18 +164,18 @@ impl Framebuffer for Gl3Framebuffer {
Ok(()) Ok(())
} }
fn init(&mut self, mut size: Size<u32>, format: impl Into<GLenum>) -> Result<()> { fn init(fb: &mut Framebuffer, mut size: Size<u32>, format: impl Into<GLenum>) -> Result<()> {
if self.is_raw { if fb.is_raw {
return Ok(()); return Ok(());
} }
self.format = format.into(); fb.format = format.into();
self.size = size; fb.size = size;
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle); gl::BindFramebuffer(gl::FRAMEBUFFER, fb.handle);
// reset the framebuffer image // reset the framebuffer image
if self.image != 0 { if fb.image != 0 {
gl::FramebufferTexture2D( gl::FramebufferTexture2D(
gl::FRAMEBUFFER, gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0, gl::COLOR_ATTACHMENT0,
@ -216,11 +183,11 @@ impl Framebuffer for Gl3Framebuffer {
0, 0,
0, 0,
); );
gl::DeleteTextures(1, &self.image); gl::DeleteTextures(1, &fb.image);
} }
gl::GenTextures(1, &mut self.image); gl::GenTextures(1, &mut fb.image);
gl::BindTexture(gl::TEXTURE_2D, self.image); gl::BindTexture(gl::TEXTURE_2D, fb.image);
if size.width == 0 { if size.width == 0 {
size.width = 1; size.width = 1;
@ -229,18 +196,18 @@ impl Framebuffer for Gl3Framebuffer {
size.height = 1; size.height = 1;
} }
self.mip_levels = librashader_runtime::scaling::calc_miplevel(size); fb.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
if self.mip_levels > self.max_levels { if fb.mip_levels > fb.max_levels {
self.mip_levels = self.max_levels; fb.mip_levels = fb.max_levels;
} }
if self.mip_levels == 0 { if fb.mip_levels == 0 {
self.mip_levels = 1; fb.mip_levels = 1;
} }
gl::TexStorage2D( gl::TexStorage2D(
gl::TEXTURE_2D, gl::TEXTURE_2D,
self.mip_levels as GLsizei, fb.mip_levels as GLsizei,
self.format, fb.format,
size.width as GLsizei, size.width as GLsizei,
size.height as GLsizei, size.height as GLsizei,
); );
@ -249,7 +216,7 @@ impl Framebuffer for Gl3Framebuffer {
gl::FRAMEBUFFER, gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0, gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D, gl::TEXTURE_2D,
self.image, fb.image,
0, 0,
); );
@ -266,21 +233,21 @@ impl Framebuffer for Gl3Framebuffer {
0, 0,
0, 0,
); );
gl::DeleteTextures(1, &self.image); gl::DeleteTextures(1, &fb.image);
gl::GenTextures(1, &mut self.image); gl::GenTextures(1, &mut fb.image);
gl::BindTexture(gl::TEXTURE_2D, self.image); gl::BindTexture(gl::TEXTURE_2D, fb.image);
self.mip_levels = librashader_runtime::scaling::calc_miplevel(size); fb.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
if self.mip_levels > self.max_levels { if fb.mip_levels > fb.max_levels {
self.mip_levels = self.max_levels; fb.mip_levels = fb.max_levels;
} }
if self.mip_levels == 0 { if fb.mip_levels == 0 {
self.mip_levels = 1; fb.mip_levels = 1;
} }
gl::TexStorage2D( gl::TexStorage2D(
gl::TEXTURE_2D, gl::TEXTURE_2D,
self.mip_levels as GLsizei, fb.mip_levels as GLsizei,
ImageFormat::R8G8B8A8Unorm.into(), ImageFormat::R8G8B8A8Unorm.into(),
size.width as GLsizei, size.width as GLsizei,
size.height as GLsizei, size.height as GLsizei,
@ -289,10 +256,10 @@ impl Framebuffer for Gl3Framebuffer {
gl::FRAMEBUFFER, gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0, gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D, gl::TEXTURE_2D,
self.image, fb.image,
0, 0,
); );
// self.init = // fb.init =
// gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE; // gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE;
} }
_ => return Err(FilterChainError::FramebufferInit(status)), _ => return Err(FilterChainError::FramebufferInit(status)),
@ -306,16 +273,3 @@ impl Framebuffer for Gl3Framebuffer {
Ok(()) Ok(())
} }
} }
impl Drop for Gl3Framebuffer {
fn drop(&mut self) {
unsafe {
if self.handle != 0 {
gl::DeleteFramebuffers(1, &self.handle);
}
if self.image != 0 {
gl::DeleteTextures(1, &self.image);
}
}
}
}

View file

@ -10,7 +10,7 @@ use librashader_common::Size;
use crate::filter_chain::FilterChain; use crate::filter_chain::FilterChain;
use crate::framebuffer::{GLImage, Viewport}; use crate::framebuffer::{GLImage, Viewport};
use crate::gl::gl3::CompatibilityGL; use crate::gl::gl3::CompatibilityGL;
use crate::gl::{Framebuffer, GLInterface}; use crate::gl::{FramebufferInterface, GLInterface};
const WIDTH: u32 = 900; const WIDTH: u32 = 900;
const HEIGHT: u32 = 700; const HEIGHT: u32 = 700;
@ -267,7 +267,7 @@ pub fn do_loop(
events: Receiver<(f64, WindowEvent)>, events: Receiver<(f64, WindowEvent)>,
triangle_program: GLuint, triangle_program: GLuint,
triangle_vao: GLuint, triangle_vao: GLuint,
filter: &mut FilterChain<CompatibilityGL>, filter: &mut FilterChain,
) { ) {
let mut framecount = 0; let mut framecount = 0;
let mut rendered_framebuffer = 0; let mut rendered_framebuffer = 0;
@ -464,7 +464,7 @@ void main()
let (fb_width, fb_height) = window.get_framebuffer_size(); let (fb_width, fb_height) = window.get_framebuffer_size();
let (vp_width, vp_height) = window.get_size(); let (vp_width, vp_height) = window.get_size();
let output = <CompatibilityGL as GLInterface>::Framebuffer::new_from_raw( let output = <CompatibilityGL as GLInterface>::FramebufferInterface::new_from_raw(
output_texture, output_texture,
output_framebuffer_handle, output_framebuffer_handle,
gl::RGBA8, gl::RGBA8,

View file

@ -15,7 +15,7 @@ use ubo_ring::*;
pub struct CompatibilityGL; pub struct CompatibilityGL;
impl GLInterface for CompatibilityGL { impl GLInterface for CompatibilityGL {
type Framebuffer = Gl3Framebuffer; type FramebufferInterface = Gl3Framebuffer;
type UboRing = Gl3UboRing<16>; type UboRing = Gl3UboRing<16>;
type DrawQuad = Gl3DrawQuad; type DrawQuad = Gl3DrawQuad;
type LoadLut = Gl3LutLoad; type LoadLut = Gl3LutLoad;

View file

@ -1,46 +1,23 @@
use crate::error::{FilterChainError, Result}; use crate::error::{FilterChainError, Result};
use crate::framebuffer::{GLImage, Viewport}; use crate::framebuffer::{GLImage, Viewport};
use crate::gl::Framebuffer; use crate::gl::framebuffer::Framebuffer;
use crate::gl::FramebufferInterface;
use crate::texture::Texture; use crate::texture::Texture;
use gl::types::{GLenum, GLint, GLsizei, GLuint}; use gl::types::{GLenum, GLint, GLsizei, GLuint};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::Scale2D; use librashader_presets::Scale2D;
#[derive(Debug)] #[derive(Debug)]
pub struct Gl46Framebuffer { pub struct Gl46Framebuffer;
image: GLuint,
handle: GLuint,
size: Size<u32>,
format: GLenum,
max_levels: u32,
levels: u32,
is_raw: bool,
}
impl Framebuffer for Gl46Framebuffer { impl FramebufferInterface for Gl46Framebuffer {
fn handle(&self) -> GLuint { fn new(max_levels: u32) -> Framebuffer {
self.handle
}
fn size(&self) -> Size<u32> {
self.size
}
fn image(&self) -> GLuint {
self.image
}
fn format(&self) -> GLenum {
self.format
}
fn new(max_levels: u32) -> Gl46Framebuffer {
let mut framebuffer = 0; let mut framebuffer = 0;
unsafe { unsafe {
gl::CreateFramebuffers(1, &mut framebuffer); gl::CreateFramebuffers(1, &mut framebuffer);
} }
Gl46Framebuffer { Framebuffer {
image: 0, image: 0,
size: Size { size: Size {
width: 1, width: 1,
@ -48,7 +25,7 @@ impl Framebuffer for Gl46Framebuffer {
}, },
format: 0, format: 0,
max_levels, max_levels,
levels: 0, mip_levels: 0,
handle: framebuffer, handle: framebuffer,
is_raw: false, is_raw: false,
} }
@ -59,49 +36,38 @@ impl Framebuffer for Gl46Framebuffer {
format: GLenum, format: GLenum,
size: Size<u32>, size: Size<u32>,
miplevels: u32, miplevels: u32,
) -> Gl46Framebuffer { ) -> Framebuffer {
Gl46Framebuffer { Framebuffer {
image: texture, image: texture,
size, size,
format, format,
max_levels: miplevels, max_levels: miplevels,
levels: miplevels, mip_levels: miplevels,
handle, handle,
is_raw: true, is_raw: true,
} }
} }
fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> Texture {
Texture {
image: GLImage {
handle: self.image,
format: self.format,
size: self.size,
padded_size: Default::default(),
},
filter,
mip_filter: filter,
wrap_mode,
}
}
fn scale( fn scale(
&mut self, fb: &mut Framebuffer,
scaling: Scale2D, scaling: Scale2D,
format: ImageFormat, format: ImageFormat,
viewport: &Viewport<Self>, viewport: &Viewport,
_original: &Texture, _original: &Texture,
source: &Texture, source: &Texture,
) -> Result<Size<u32>> { ) -> Result<Size<u32>> {
if self.is_raw { if fb.is_raw {
return Ok(self.size); return Ok(fb.size);
} }
let size = let size =
librashader_runtime::scaling::scale(scaling, source.image.size, viewport.output.size); librashader_runtime::scaling::scale(scaling, source.image.size, viewport.output.size);
if self.size != size { if fb.size != size {
self.size = size; fb.size = size;
self.init( Self::init(
fb,
size, size,
if format == ImageFormat::Unknown { if format == ImageFormat::Unknown {
ImageFormat::R8G8B8A8Unorm ImageFormat::R8G8B8A8Unorm
@ -112,38 +78,40 @@ impl Framebuffer for Gl46Framebuffer {
} }
Ok(size) Ok(size)
} }
fn clear<const REBIND: bool>(&self) { fn clear<const REBIND: bool>(fb: &Framebuffer) {
unsafe { unsafe {
gl::ClearNamedFramebufferfv( gl::ClearNamedFramebufferfv(
self.handle, fb.handle,
gl::COLOR, gl::COLOR,
0, 0,
[0.0f32, 0.0, 0.0, 0.0].as_ptr().cast(), [0.0f32, 0.0, 0.0, 0.0].as_ptr().cast(),
); );
} }
} }
fn copy_from(&mut self, image: &GLImage) -> Result<()> { fn copy_from(fb: &mut Framebuffer, image: &GLImage) -> Result<()> {
// todo: may want to use a shader and draw a quad to be faster. // todo: may want to use a shader and draw a quad to be faster.
if image.size != self.size || image.format != self.format { if image.size != fb.size || image.format != fb.format {
self.init(image.size, image.format)?; Self::init(
fb,
image.size, image.format)?;
} }
unsafe { unsafe {
// gl::NamedFramebufferDrawBuffer(self.handle, gl::COLOR_ATTACHMENT1); // gl::NamedFramebufferDrawBuffer(fb.handle, gl::COLOR_ATTACHMENT1);
gl::NamedFramebufferReadBuffer(image.handle, gl::COLOR_ATTACHMENT0); gl::NamedFramebufferReadBuffer(image.handle, gl::COLOR_ATTACHMENT0);
gl::NamedFramebufferDrawBuffer(self.handle, gl::COLOR_ATTACHMENT1); gl::NamedFramebufferDrawBuffer(fb.handle, gl::COLOR_ATTACHMENT1);
gl::BlitNamedFramebuffer( gl::BlitNamedFramebuffer(
image.handle, image.handle,
self.handle, fb.handle,
0, 0,
0, 0,
image.size.width as GLint, image.size.width as GLint,
image.size.height as GLint, image.size.height as GLint,
0, 0,
0, 0,
self.size.width as GLint, fb.size.width as GLint,
self.size.height as GLint, fb.size.height as GLint,
gl::COLOR_BUFFER_BIT, gl::COLOR_BUFFER_BIT,
gl::NEAREST, gl::NEAREST,
); );
@ -151,21 +119,21 @@ impl Framebuffer for Gl46Framebuffer {
Ok(()) Ok(())
} }
fn init(&mut self, mut size: Size<u32>, format: impl Into<GLenum>) -> Result<()> { fn init(fb: &mut Framebuffer, mut size: Size<u32>, format: impl Into<GLenum>) -> Result<()> {
if self.is_raw { if fb.is_raw {
return Ok(()); return Ok(());
} }
self.format = format.into(); fb.format = format.into();
self.size = size; fb.size = size;
unsafe { unsafe {
// reset the framebuffer image // reset the framebuffer image
if self.image != 0 { if fb.image != 0 {
gl::NamedFramebufferTexture(self.handle, gl::COLOR_ATTACHMENT0, 0, 0); gl::NamedFramebufferTexture(fb.handle, gl::COLOR_ATTACHMENT0, 0, 0);
gl::DeleteTextures(1, &self.image); gl::DeleteTextures(1, &fb.image);
} }
gl::CreateTextures(gl::TEXTURE_2D, 1, &mut self.image); gl::CreateTextures(gl::TEXTURE_2D, 1, &mut fb.image);
if size.width == 0 { if size.width == 0 {
size.width = 1; size.width = 1;
@ -174,23 +142,23 @@ impl Framebuffer for Gl46Framebuffer {
size.height = 1; size.height = 1;
} }
self.levels = librashader_runtime::scaling::calc_miplevel(size); fb.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
if self.levels > self.max_levels { if fb.mip_levels > fb.max_levels {
self.levels = self.max_levels; fb.mip_levels = fb.max_levels;
} }
if self.levels == 0 { if fb.mip_levels == 0 {
self.levels = 1; fb.mip_levels = 1;
} }
gl::TextureStorage2D( gl::TextureStorage2D(
self.image, fb.image,
self.levels as GLsizei, fb.mip_levels as GLsizei,
self.format, fb.format,
size.width as GLsizei, size.width as GLsizei,
size.height as GLsizei, size.height as GLsizei,
); );
gl::NamedFramebufferTexture(self.handle, gl::COLOR_ATTACHMENT0, self.image, 0); gl::NamedFramebufferTexture(fb.handle, gl::COLOR_ATTACHMENT0, fb.image, 0);
let status = gl::CheckFramebufferStatus(gl::FRAMEBUFFER); let status = gl::CheckFramebufferStatus(gl::FRAMEBUFFER);
if status != gl::FRAMEBUFFER_COMPLETE { if status != gl::FRAMEBUFFER_COMPLETE {
@ -198,32 +166,27 @@ impl Framebuffer for Gl46Framebuffer {
gl::FRAMEBUFFER_UNSUPPORTED => { gl::FRAMEBUFFER_UNSUPPORTED => {
eprintln!("unsupported fbo"); eprintln!("unsupported fbo");
gl::NamedFramebufferTexture(self.handle, gl::COLOR_ATTACHMENT0, 0, 0); gl::NamedFramebufferTexture(fb.handle, gl::COLOR_ATTACHMENT0, 0, 0);
gl::DeleteTextures(1, &self.image); gl::DeleteTextures(1, &fb.image);
gl::CreateTextures(gl::TEXTURE_2D, 1, &mut self.image); gl::CreateTextures(gl::TEXTURE_2D, 1, &mut fb.image);
self.levels = librashader_runtime::scaling::calc_miplevel(size); fb.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
if self.levels > self.max_levels { if fb.mip_levels > fb.max_levels {
self.levels = self.max_levels; fb.mip_levels = fb.max_levels;
} }
if self.levels == 0 { if fb.mip_levels == 0 {
self.levels = 1; fb.mip_levels = 1;
} }
gl::TextureStorage2D( gl::TextureStorage2D(
self.image, fb.image,
self.levels as GLsizei, fb.mip_levels as GLsizei,
ImageFormat::R8G8B8A8Unorm.into(), ImageFormat::R8G8B8A8Unorm.into(),
size.width as GLsizei, size.width as GLsizei,
size.height as GLsizei, size.height as GLsizei,
); );
gl::NamedFramebufferTexture( gl::NamedFramebufferTexture(fb.handle, gl::COLOR_ATTACHMENT0, fb.image, 0);
self.handle, // fb.init =
gl::COLOR_ATTACHMENT0,
self.image,
0,
);
// self.init =
// gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE; // gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE;
} }
_ => return Err(FilterChainError::FramebufferInit(status)), _ => return Err(FilterChainError::FramebufferInit(status)),
@ -233,16 +196,3 @@ impl Framebuffer for Gl46Framebuffer {
Ok(()) Ok(())
} }
} }
impl Drop for Gl46Framebuffer {
fn drop(&mut self) {
unsafe {
if self.handle != 0 {
gl::DeleteFramebuffers(1, &self.handle);
}
if self.image != 0 {
gl::DeleteTextures(1, &self.image);
}
}
}
}

View file

@ -10,7 +10,7 @@ use librashader_common::Size;
use crate::filter_chain::FilterChain; use crate::filter_chain::FilterChain;
use crate::framebuffer::{GLImage, Viewport}; use crate::framebuffer::{GLImage, Viewport};
use crate::gl::gl46::DirectStateAccessGL; use crate::gl::gl46::DirectStateAccessGL;
use crate::gl::{Framebuffer, GLInterface}; use crate::gl::{FramebufferInterface, GLInterface};
const WIDTH: u32 = 900; const WIDTH: u32 = 900;
const HEIGHT: u32 = 700; const HEIGHT: u32 = 700;
@ -258,7 +258,7 @@ pub fn do_loop(
events: Receiver<(f64, WindowEvent)>, events: Receiver<(f64, WindowEvent)>,
triangle_program: GLuint, triangle_program: GLuint,
triangle_vao: GLuint, triangle_vao: GLuint,
filter: &mut FilterChain<DirectStateAccessGL>, filter: &mut FilterChain,
) { ) {
let mut framecount = 0; let mut framecount = 0;
let mut rendered_framebuffer = 0; let mut rendered_framebuffer = 0;
@ -455,7 +455,7 @@ void main()
let (fb_width, fb_height) = window.get_framebuffer_size(); let (fb_width, fb_height) = window.get_framebuffer_size();
let (vp_width, vp_height) = window.get_size(); let (vp_width, vp_height) = window.get_size();
let output = <DirectStateAccessGL as GLInterface>::Framebuffer::new_from_raw( let output = <DirectStateAccessGL as GLInterface>::FramebufferInterface::new_from_raw(
output_texture, output_texture,
output_framebuffer_handle, output_framebuffer_handle,
gl::RGBA8, gl::RGBA8,

View file

@ -16,7 +16,7 @@ use ubo_ring::*;
pub struct DirectStateAccessGL; pub struct DirectStateAccessGL;
impl GLInterface for DirectStateAccessGL { impl GLInterface for DirectStateAccessGL {
type Framebuffer = Gl46Framebuffer; type FramebufferInterface = Gl46Framebuffer;
type UboRing = Gl46UboRing<16>; type UboRing = Gl46UboRing<16>;
type DrawQuad = Gl46DrawQuad; type DrawQuad = Gl46DrawQuad;
type LoadLut = Gl46LutLoad; type LoadLut = Gl46LutLoad;

View file

@ -1,3 +1,4 @@
mod framebuffer;
pub(crate) mod gl3; pub(crate) mod gl3;
pub(crate) mod gl46; pub(crate) mod gl46;
@ -6,6 +7,7 @@ use crate::error::Result;
use crate::framebuffer::{GLImage, Viewport}; use crate::framebuffer::{GLImage, Viewport};
use crate::samplers::SamplerSet; use crate::samplers::SamplerSet;
use crate::texture::Texture; use crate::texture::Texture;
pub use framebuffer::Framebuffer;
use gl::types::{GLenum, GLuint}; use gl::types::{GLenum, GLuint};
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode}; use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
use librashader_presets::{Scale2D, TextureConfig}; use librashader_presets::{Scale2D, TextureConfig};
@ -33,31 +35,26 @@ pub trait UboRing<const SIZE: usize> {
); );
} }
pub trait Framebuffer { pub trait FramebufferInterface {
fn new(max_levels: u32) -> Self; fn new(max_levels: u32) -> Framebuffer;
fn new_from_raw( fn new_from_raw(
texture: GLuint, texture: GLuint,
handle: GLuint, handle: GLuint,
format: GLenum, format: GLenum,
size: Size<u32>, size: Size<u32>,
miplevels: u32, miplevels: u32,
) -> Self; ) -> Framebuffer;
fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> Texture;
fn scale( fn scale(
&mut self, fb: &mut Framebuffer,
scaling: Scale2D, scaling: Scale2D,
format: ImageFormat, format: ImageFormat,
viewport: &Viewport<Self>, viewport: &Viewport,
_original: &Texture, _original: &Texture,
source: &Texture, source: &Texture,
) -> Result<Size<u32>>; ) -> Result<Size<u32>>;
fn clear<const REBIND: bool>(&self); fn clear<const REBIND: bool>(fb: &Framebuffer);
fn copy_from(&mut self, image: &GLImage) -> Result<()>; fn copy_from(fb: &mut Framebuffer, image: &GLImage) -> Result<()>;
fn init(&mut self, size: Size<u32>, format: impl Into<GLenum>) -> Result<()>; fn init(fb: &mut Framebuffer, size: Size<u32>, format: impl Into<GLenum>) -> Result<()>;
fn handle(&self) -> GLuint;
fn image(&self) -> GLuint;
fn size(&self) -> Size<u32>;
fn format(&self) -> GLenum;
} }
pub trait BindTexture { pub trait BindTexture {
@ -65,7 +62,7 @@ pub trait BindTexture {
} }
pub trait GLInterface { pub trait GLInterface {
type Framebuffer: Framebuffer; type FramebufferInterface: FramebufferInterface;
type UboRing: UboRing<16>; type UboRing: UboRing<16>;
type DrawQuad: DrawQuad; type DrawQuad: DrawQuad;
type LoadLut: LoadLut; type LoadLut: LoadLut;

View file

@ -1,5 +1,6 @@
#![feature(strict_provenance)] #![feature(strict_provenance)]
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
#![feature(let_chains)]
mod binding; mod binding;
mod filter_chain; mod filter_chain;
@ -9,42 +10,29 @@ mod render_target;
mod util; mod util;
mod gl; mod gl;
pub mod options;
mod samplers; mod samplers;
mod texture; mod texture;
pub mod options;
pub mod error; pub mod error;
pub use filter_chain::FilterChain; pub use filter_chain::FilterChain;
pub use framebuffer::Viewport; pub use framebuffer::Viewport;
pub use framebuffer::GLImage;
pub mod gl3 {
pub use super::framebuffer::GLImage;
pub type FilterChain = super::filter_chain::FilterChain<super::gl::gl3::CompatibilityGL>;
pub type Viewport<'a> = super::framebuffer::Viewport<
'a,
<super::gl::gl3::CompatibilityGL as super::gl::GLInterface>::Framebuffer,
>;
}
pub mod gl46 {
pub use super::framebuffer::GLImage;
pub type FilterChain = super::filter_chain::FilterChain<super::gl::gl46::DirectStateAccessGL>;
pub type Viewport<'a> = super::framebuffer::Viewport<
'a,
<super::gl::gl46::DirectStateAccessGL as super::gl::GLInterface>::Framebuffer,
>;
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::filter_chain::FilterChain; use crate::filter_chain::FilterChain;
use crate::options::FilterChainOptions;
#[test] #[test]
fn triangle_gl() { fn triangle_gl() {
let (glfw, window, events, shader, vao) = gl::gl3::hello_triangle::setup(); let (glfw, window, events, shader, vao) = gl::gl3::hello_triangle::setup();
let mut filter = let mut filter =
FilterChain::load_from_path("../test/slang-shaders/vhs/VHSPro.slangp", None) FilterChain::load_from_path("../test/slang-shaders/vhs/VHSPro.slangp", Some(&FilterChainOptions {
gl_version: 0,
use_dsa: false,
}))
// FilterChain::load_from_path("../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", None) // FilterChain::load_from_path("../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", None)
.unwrap(); .unwrap();
gl::gl3::hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter); gl::gl3::hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter);
@ -54,7 +42,10 @@ mod tests {
fn triangle_gl46() { fn triangle_gl46() {
let (glfw, window, events, shader, vao) = gl::gl46::hello_triangle::setup(); let (glfw, window, events, shader, vao) = gl::gl46::hello_triangle::setup();
let mut filter = let mut filter =
FilterChain::load_from_path("../test/slang-shaders/vhs/VHSPro.slangp", None) FilterChain::load_from_path("../test/slang-shaders/vhs/VHSPro.slangp", Some(&FilterChainOptions {
gl_version: 0,
use_dsa: true,
}))
// FilterChain::load_from_path("../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", None) // FilterChain::load_from_path("../test/slang-shaders/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp", None)
.unwrap(); .unwrap();
gl::gl46::hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter); gl::gl46::hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter);

View file

@ -8,4 +8,5 @@ pub struct FrameOptions {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct FilterChainOptions { pub struct FilterChainOptions {
pub gl_version: u16, pub gl_version: u16,
pub use_dsa: bool
} }

View file

@ -1,5 +1,5 @@
use crate::framebuffer::Viewport; use crate::framebuffer::Viewport;
use crate::gl::Framebuffer; use crate::gl::{Framebuffer, FramebufferInterface};
#[rustfmt::skip] #[rustfmt::skip]
static DEFAULT_MVP: &[f32; 16] = &[ static DEFAULT_MVP: &[f32; 16] = &[
@ -10,15 +10,15 @@ static DEFAULT_MVP: &[f32; 16] = &[
]; ];
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub(crate) struct RenderTarget<'a, T: Framebuffer> { pub(crate) struct RenderTarget<'a> {
pub mvp: &'a [f32; 16], pub mvp: &'a [f32; 16],
pub framebuffer: &'a T, pub framebuffer: &'a Framebuffer,
pub x: i32, pub x: i32,
pub y: i32, pub y: i32,
} }
impl<'a, T: Framebuffer> RenderTarget<'a, T> { impl<'a> RenderTarget<'a> {
pub fn new(backbuffer: &'a T, mvp: Option<&'a [f32; 16]>, x: i32, y: i32) -> Self { pub fn new(backbuffer: &'a Framebuffer, mvp: Option<&'a [f32; 16]>, x: i32, y: i32) -> Self {
if let Some(mvp) = mvp { if let Some(mvp) = mvp {
RenderTarget { RenderTarget {
framebuffer: backbuffer, framebuffer: backbuffer,
@ -37,8 +37,8 @@ impl<'a, T: Framebuffer> RenderTarget<'a, T> {
} }
} }
impl<'a, T: Framebuffer> From<&Viewport<'a, T>> for RenderTarget<'a, T> { impl<'a> From<&Viewport<'a>> for RenderTarget<'a> {
fn from(value: &Viewport<'a, T>) -> Self { fn from(value: &Viewport<'a>) -> Self {
RenderTarget::new(value.output, value.mvp, value.x, value.y) RenderTarget::new(value.output, value.mvp, value.x, value.y)
} }
} }

View file

@ -101,6 +101,7 @@ pub fn gl_get_version() -> GlVersion {
pub fn gl_u16_to_version(version: u16) -> GlVersion { pub fn gl_u16_to_version(version: u16) -> GlVersion {
match version { match version {
0 => gl_get_version(),
300 => GlVersion::V1_30, 300 => GlVersion::V1_30,
310 => GlVersion::V1_40, 310 => GlVersion::V1_40,
320 => GlVersion::V1_50, 320 => GlVersion::V1_50,

View file

@ -31,18 +31,7 @@ pub mod targets {
/// Shader runtime for OpenGL. /// Shader runtime for OpenGL.
pub mod runtime { pub mod runtime {
pub use librashader_runtime_gl::error; pub use librashader_runtime_gl::*;
pub use librashader_runtime_gl::options::*;
pub use librashader_runtime_gl::FilterChain;
pub use librashader_runtime_gl::Viewport;
pub mod gl3 {
pub use librashader_runtime_gl::gl3::*;
}
pub mod gl46 {
pub use librashader_runtime_gl::gl46::*;
}
} }
} }