gl: very not nicely make dsa a runtime prop
This commit is contained in:
parent
8d940d6f79
commit
759cd4bc28
|
@ -9,7 +9,7 @@ use crate::util::{gl_get_version, gl_u16_to_version};
|
|||
use gl::types::{GLint, GLuint};
|
||||
|
||||
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::samplers::SamplerSet;
|
||||
use crate::texture::Texture;
|
||||
|
@ -30,20 +30,75 @@ use spirv_cross::spirv::Decoration;
|
|||
use std::collections::VecDeque;
|
||||
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>]>,
|
||||
common: FilterCommon,
|
||||
pub(crate) draw_quad: T::DrawQuad,
|
||||
output_framebuffers: Box<[T::Framebuffer]>,
|
||||
feedback_framebuffers: Box<[T::Framebuffer]>,
|
||||
history_framebuffers: VecDeque<T::Framebuffer>,
|
||||
output_framebuffers: Box<[Framebuffer]>,
|
||||
feedback_framebuffers: Box<[Framebuffer]>,
|
||||
history_framebuffers: VecDeque<Framebuffer>,
|
||||
}
|
||||
|
||||
pub struct FilterCommon {
|
||||
pub(crate) struct FilterCommon {
|
||||
// semantics: ReflectSemantics,
|
||||
pub(crate) config: FilterMutable,
|
||||
pub(crate) luts: FxHashMap<usize, Texture>,
|
||||
pub(crate) samplers: SamplerSet,
|
||||
pub config: FilterMutable,
|
||||
pub luts: FxHashMap<usize, Texture>,
|
||||
pub samplers: SamplerSet,
|
||||
pub output_textures: Box<[Texture]>,
|
||||
pub feedback_textures: Box<[Texture]>,
|
||||
pub history_textures: Box<[Texture]>,
|
||||
|
@ -54,7 +109,7 @@ pub struct FilterMutable {
|
|||
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 {
|
||||
// todo: support both ubo and pushco
|
||||
// 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`.
|
||||
pub fn load_from_preset(
|
||||
pub(crate) fn load_from_preset(
|
||||
preset: ShaderPreset,
|
||||
options: Option<&FilterChainOptions>,
|
||||
) -> Result<Self> {
|
||||
|
@ -116,13 +171,13 @@ impl<T: GLInterface> FilterChain<T> {
|
|||
|
||||
// initialize output framebuffers
|
||||
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();
|
||||
output_textures.resize_with(filters.len(), Texture::default);
|
||||
|
||||
// initialize feedback framebuffers
|
||||
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();
|
||||
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 (history_framebuffers, history_textures) =
|
||||
FilterChain::init_history(&filters, default_filter, default_wrap);
|
||||
FilterChainImpl::init_history(&filters, default_filter, default_wrap);
|
||||
|
||||
// create vertex objects
|
||||
let draw_quad = T::DrawQuad::new();
|
||||
|
||||
Ok(FilterChain {
|
||||
Ok(FilterChainImpl {
|
||||
passes: filters,
|
||||
output_framebuffers: output_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(
|
||||
passes: Vec<ShaderPassConfig>,
|
||||
textures: &[TextureConfig],
|
||||
|
@ -363,7 +408,7 @@ impl<T: GLInterface> FilterChain<T> {
|
|||
filters: &[FilterPass<T>],
|
||||
filter: FilterMode,
|
||||
wrap_mode: WrapMode,
|
||||
) -> (VecDeque<T::Framebuffer>, Box<[Texture]>) {
|
||||
) -> (VecDeque<Framebuffer>, Box<[Texture]>) {
|
||||
let mut required_images = 0;
|
||||
|
||||
for pass in filters {
|
||||
|
@ -397,7 +442,7 @@ impl<T: GLInterface> FilterChain<T> {
|
|||
|
||||
eprintln!("[history] using frame history with {required_images} 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();
|
||||
history_textures.resize_with(required_images, || Texture {
|
||||
|
@ -412,12 +457,12 @@ impl<T: GLInterface> FilterChain<T> {
|
|||
|
||||
fn push_history(&mut self, input: &GLImage) -> Result<()> {
|
||||
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");
|
||||
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)
|
||||
}
|
||||
|
@ -431,7 +476,7 @@ impl<T: GLInterface> FilterChain<T> {
|
|||
pub fn frame(
|
||||
&mut self,
|
||||
count: usize,
|
||||
viewport: &Viewport<T::Framebuffer>,
|
||||
viewport: &Viewport,
|
||||
input: &GLImage,
|
||||
options: Option<&FrameOptions>,
|
||||
) -> Result<()> {
|
||||
|
@ -440,7 +485,7 @@ impl<T: GLInterface> FilterChain<T> {
|
|||
if let Some(options) = options {
|
||||
if options.clear_history {
|
||||
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.
|
||||
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.get_format(),
|
||||
viewport,
|
||||
|
@ -498,7 +543,7 @@ impl<T: GLInterface> FilterChain<T> {
|
|||
&source,
|
||||
)?;
|
||||
|
||||
self.feedback_framebuffers[index].scale(
|
||||
self.feedback_framebuffers[index].scale::<T::FramebufferInterface>(
|
||||
pass.config.scaling.clone(),
|
||||
pass.get_format(),
|
||||
viewport,
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc_hash::FxHashMap;
|
|||
use crate::binding::{BufferStorage, UniformLocation, VariableLocation};
|
||||
use crate::filter_chain::FilterCommon;
|
||||
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::texture::Texture;
|
||||
|
@ -39,15 +39,15 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
parent: &FilterCommon,
|
||||
frame_count: u32,
|
||||
frame_direction: i32,
|
||||
viewport: &Viewport<T::Framebuffer>,
|
||||
viewport: &Viewport,
|
||||
original: &Texture,
|
||||
source: &Texture,
|
||||
output: RenderTarget<T::Framebuffer>,
|
||||
output: RenderTarget,
|
||||
) {
|
||||
let framebuffer = output.framebuffer;
|
||||
|
||||
unsafe {
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle());
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle);
|
||||
gl::UseProgram(self.program);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
output.mvp,
|
||||
frame_count,
|
||||
frame_direction,
|
||||
framebuffer.size(),
|
||||
framebuffer.size,
|
||||
viewport,
|
||||
original,
|
||||
source,
|
||||
|
@ -73,9 +73,9 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
|
||||
unsafe {
|
||||
// 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(
|
||||
output.x,
|
||||
output.y,
|
||||
|
@ -83,7 +83,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
framebuffer_size.height as GLsizei,
|
||||
);
|
||||
|
||||
if framebuffer.format() == gl::SRGB8_ALPHA8 {
|
||||
if framebuffer.format == gl::SRGB8_ALPHA8 {
|
||||
gl::Enable(gl::FRAMEBUFFER_SRGB);
|
||||
} else {
|
||||
gl::Disable(gl::FRAMEBUFFER_SRGB);
|
||||
|
@ -120,7 +120,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
frame_count: u32,
|
||||
frame_direction: i32,
|
||||
fb_size: Size<u32>,
|
||||
viewport: &Viewport<T::Framebuffer>,
|
||||
viewport: &Viewport,
|
||||
original: &Texture,
|
||||
source: &Texture,
|
||||
) {
|
||||
|
@ -145,7 +145,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
.get(&VariableSemantics::FinalViewport.into())
|
||||
{
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset, viewport.output.size(), location.location());
|
||||
.bind_vec4(*offset, viewport.output.size, location.location());
|
||||
}
|
||||
|
||||
// bind FrameCount
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use gl::types::{GLenum, GLuint};
|
||||
use librashader_common::Size;
|
||||
|
||||
use crate::gl::Framebuffer;
|
||||
use crate::gl::{Framebuffer, FramebufferInterface};
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Viewport<'a, T: Framebuffer + ?Sized> {
|
||||
pub struct Viewport<'a> {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub output: &'a T,
|
||||
pub output: &'a Framebuffer,
|
||||
pub mvp: Option<&'a [f32; 16]>,
|
||||
}
|
||||
|
||||
|
|
81
librashader-runtime-gl/src/gl/framebuffer.rs
Normal file
81
librashader-runtime-gl/src/gl/framebuffer.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +1,17 @@
|
|||
use crate::error::{FilterChainError, Result};
|
||||
use crate::framebuffer::{GLImage, Viewport};
|
||||
use crate::gl::Framebuffer;
|
||||
use crate::gl::framebuffer::Framebuffer;
|
||||
use crate::gl::FramebufferInterface;
|
||||
use crate::texture::Texture;
|
||||
use gl::types::{GLenum, GLint, GLsizei, GLuint};
|
||||
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||
use librashader_presets::Scale2D;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Gl3Framebuffer {
|
||||
image: GLuint,
|
||||
handle: GLuint,
|
||||
size: Size<u32>,
|
||||
format: GLenum,
|
||||
max_levels: u32,
|
||||
mip_levels: u32,
|
||||
is_raw: bool,
|
||||
}
|
||||
pub struct Gl3Framebuffer;
|
||||
|
||||
impl Framebuffer for Gl3Framebuffer {
|
||||
fn handle(&self) -> GLuint {
|
||||
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 {
|
||||
impl FramebufferInterface for Gl3Framebuffer {
|
||||
fn new(max_levels: u32) -> Framebuffer {
|
||||
let mut framebuffer = 0;
|
||||
unsafe {
|
||||
gl::GenFramebuffers(1, &mut framebuffer);
|
||||
|
@ -42,7 +19,7 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
Gl3Framebuffer {
|
||||
Framebuffer {
|
||||
image: 0,
|
||||
size: Size {
|
||||
width: 1,
|
||||
|
@ -61,8 +38,8 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
format: GLenum,
|
||||
size: Size<u32>,
|
||||
miplevels: u32,
|
||||
) -> Gl3Framebuffer {
|
||||
Gl3Framebuffer {
|
||||
) -> Framebuffer {
|
||||
Framebuffer {
|
||||
image: texture,
|
||||
size,
|
||||
format,
|
||||
|
@ -72,38 +49,27 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
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(
|
||||
&mut self,
|
||||
fb: &mut Framebuffer,
|
||||
scaling: Scale2D,
|
||||
format: ImageFormat,
|
||||
viewport: &Viewport<Self>,
|
||||
viewport: &Viewport,
|
||||
_original: &Texture,
|
||||
source: &Texture,
|
||||
) -> Result<Size<u32>> {
|
||||
if self.is_raw {
|
||||
return Ok(self.size);
|
||||
if fb.is_raw {
|
||||
return Ok(fb.size);
|
||||
}
|
||||
|
||||
let size =
|
||||
librashader_runtime::scaling::scale(scaling, source.image.size, viewport.output.size);
|
||||
|
||||
if self.size != size {
|
||||
self.size = size;
|
||||
if fb.size != size {
|
||||
fb.size = size;
|
||||
|
||||
self.init(
|
||||
Self::init(
|
||||
fb,
|
||||
size,
|
||||
if format == ImageFormat::Unknown {
|
||||
ImageFormat::R8G8B8A8Unorm
|
||||
|
@ -114,10 +80,10 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
}
|
||||
Ok(size)
|
||||
}
|
||||
fn clear<const REBIND: bool>(&self) {
|
||||
fn clear<const REBIND: bool>(fb: &Framebuffer) {
|
||||
unsafe {
|
||||
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::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.
|
||||
if image.size != self.size || image.format != self.format {
|
||||
self.init(image.size, image.format)?;
|
||||
if image.size != fb.size || image.format != fb.format {
|
||||
Self::init(
|
||||
fb,image.size, image.format)?;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle);
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, fb.handle);
|
||||
|
||||
gl::FramebufferTexture2D(
|
||||
gl::READ_FRAMEBUFFER,
|
||||
|
@ -148,7 +115,7 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
gl::DRAW_FRAMEBUFFER,
|
||||
gl::COLOR_ATTACHMENT1,
|
||||
gl::TEXTURE_2D,
|
||||
self.image,
|
||||
fb.image,
|
||||
0,
|
||||
);
|
||||
gl::ReadBuffer(gl::COLOR_ATTACHMENT0);
|
||||
|
@ -156,12 +123,12 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
gl::BlitFramebuffer(
|
||||
0,
|
||||
0,
|
||||
self.size.width as GLint,
|
||||
self.size.height as GLint,
|
||||
fb.size.width as GLint,
|
||||
fb.size.height as GLint,
|
||||
0,
|
||||
0,
|
||||
self.size.width as GLint,
|
||||
self.size.height as GLint,
|
||||
fb.size.width as GLint,
|
||||
fb.size.height as GLint,
|
||||
gl::COLOR_BUFFER_BIT,
|
||||
gl::NEAREST,
|
||||
);
|
||||
|
@ -188,7 +155,7 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
gl::FRAMEBUFFER,
|
||||
gl::COLOR_ATTACHMENT0,
|
||||
gl::TEXTURE_2D,
|
||||
self.image,
|
||||
fb.image,
|
||||
0,
|
||||
);
|
||||
|
||||
|
@ -197,18 +164,18 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
fn init(&mut self, mut size: Size<u32>, format: impl Into<GLenum>) -> Result<()> {
|
||||
if self.is_raw {
|
||||
fn init(fb: &mut Framebuffer, mut size: Size<u32>, format: impl Into<GLenum>) -> Result<()> {
|
||||
if fb.is_raw {
|
||||
return Ok(());
|
||||
}
|
||||
self.format = format.into();
|
||||
self.size = size;
|
||||
fb.format = format.into();
|
||||
fb.size = size;
|
||||
|
||||
unsafe {
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle);
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, fb.handle);
|
||||
|
||||
// reset the framebuffer image
|
||||
if self.image != 0 {
|
||||
if fb.image != 0 {
|
||||
gl::FramebufferTexture2D(
|
||||
gl::FRAMEBUFFER,
|
||||
gl::COLOR_ATTACHMENT0,
|
||||
|
@ -216,11 +183,11 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
0,
|
||||
0,
|
||||
);
|
||||
gl::DeleteTextures(1, &self.image);
|
||||
gl::DeleteTextures(1, &fb.image);
|
||||
}
|
||||
|
||||
gl::GenTextures(1, &mut self.image);
|
||||
gl::BindTexture(gl::TEXTURE_2D, self.image);
|
||||
gl::GenTextures(1, &mut fb.image);
|
||||
gl::BindTexture(gl::TEXTURE_2D, fb.image);
|
||||
|
||||
if size.width == 0 {
|
||||
size.width = 1;
|
||||
|
@ -229,18 +196,18 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
size.height = 1;
|
||||
}
|
||||
|
||||
self.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
|
||||
if self.mip_levels > self.max_levels {
|
||||
self.mip_levels = self.max_levels;
|
||||
fb.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
|
||||
if fb.mip_levels > fb.max_levels {
|
||||
fb.mip_levels = fb.max_levels;
|
||||
}
|
||||
if self.mip_levels == 0 {
|
||||
self.mip_levels = 1;
|
||||
if fb.mip_levels == 0 {
|
||||
fb.mip_levels = 1;
|
||||
}
|
||||
|
||||
gl::TexStorage2D(
|
||||
gl::TEXTURE_2D,
|
||||
self.mip_levels as GLsizei,
|
||||
self.format,
|
||||
fb.mip_levels as GLsizei,
|
||||
fb.format,
|
||||
size.width as GLsizei,
|
||||
size.height as GLsizei,
|
||||
);
|
||||
|
@ -249,7 +216,7 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
gl::FRAMEBUFFER,
|
||||
gl::COLOR_ATTACHMENT0,
|
||||
gl::TEXTURE_2D,
|
||||
self.image,
|
||||
fb.image,
|
||||
0,
|
||||
);
|
||||
|
||||
|
@ -266,21 +233,21 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
0,
|
||||
0,
|
||||
);
|
||||
gl::DeleteTextures(1, &self.image);
|
||||
gl::GenTextures(1, &mut self.image);
|
||||
gl::BindTexture(gl::TEXTURE_2D, self.image);
|
||||
gl::DeleteTextures(1, &fb.image);
|
||||
gl::GenTextures(1, &mut fb.image);
|
||||
gl::BindTexture(gl::TEXTURE_2D, fb.image);
|
||||
|
||||
self.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
|
||||
if self.mip_levels > self.max_levels {
|
||||
self.mip_levels = self.max_levels;
|
||||
fb.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
|
||||
if fb.mip_levels > fb.max_levels {
|
||||
fb.mip_levels = fb.max_levels;
|
||||
}
|
||||
if self.mip_levels == 0 {
|
||||
self.mip_levels = 1;
|
||||
if fb.mip_levels == 0 {
|
||||
fb.mip_levels = 1;
|
||||
}
|
||||
|
||||
gl::TexStorage2D(
|
||||
gl::TEXTURE_2D,
|
||||
self.mip_levels as GLsizei,
|
||||
fb.mip_levels as GLsizei,
|
||||
ImageFormat::R8G8B8A8Unorm.into(),
|
||||
size.width as GLsizei,
|
||||
size.height as GLsizei,
|
||||
|
@ -289,10 +256,10 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
gl::FRAMEBUFFER,
|
||||
gl::COLOR_ATTACHMENT0,
|
||||
gl::TEXTURE_2D,
|
||||
self.image,
|
||||
fb.image,
|
||||
0,
|
||||
);
|
||||
// self.init =
|
||||
// fb.init =
|
||||
// gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
_ => return Err(FilterChainError::FramebufferInit(status)),
|
||||
|
@ -306,16 +273,3 @@ impl Framebuffer for Gl3Framebuffer {
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use librashader_common::Size;
|
|||
use crate::filter_chain::FilterChain;
|
||||
use crate::framebuffer::{GLImage, Viewport};
|
||||
use crate::gl::gl3::CompatibilityGL;
|
||||
use crate::gl::{Framebuffer, GLInterface};
|
||||
use crate::gl::{FramebufferInterface, GLInterface};
|
||||
|
||||
const WIDTH: u32 = 900;
|
||||
const HEIGHT: u32 = 700;
|
||||
|
@ -267,7 +267,7 @@ pub fn do_loop(
|
|||
events: Receiver<(f64, WindowEvent)>,
|
||||
triangle_program: GLuint,
|
||||
triangle_vao: GLuint,
|
||||
filter: &mut FilterChain<CompatibilityGL>,
|
||||
filter: &mut FilterChain,
|
||||
) {
|
||||
let mut framecount = 0;
|
||||
let mut rendered_framebuffer = 0;
|
||||
|
@ -464,7 +464,7 @@ void main()
|
|||
let (fb_width, fb_height) = window.get_framebuffer_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_framebuffer_handle,
|
||||
gl::RGBA8,
|
||||
|
|
|
@ -15,7 +15,7 @@ use ubo_ring::*;
|
|||
|
||||
pub struct CompatibilityGL;
|
||||
impl GLInterface for CompatibilityGL {
|
||||
type Framebuffer = Gl3Framebuffer;
|
||||
type FramebufferInterface = Gl3Framebuffer;
|
||||
type UboRing = Gl3UboRing<16>;
|
||||
type DrawQuad = Gl3DrawQuad;
|
||||
type LoadLut = Gl3LutLoad;
|
||||
|
|
|
@ -1,46 +1,23 @@
|
|||
use crate::error::{FilterChainError, Result};
|
||||
use crate::framebuffer::{GLImage, Viewport};
|
||||
use crate::gl::Framebuffer;
|
||||
use crate::gl::framebuffer::Framebuffer;
|
||||
use crate::gl::FramebufferInterface;
|
||||
use crate::texture::Texture;
|
||||
use gl::types::{GLenum, GLint, GLsizei, GLuint};
|
||||
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||
use librashader_presets::Scale2D;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Gl46Framebuffer {
|
||||
image: GLuint,
|
||||
handle: GLuint,
|
||||
size: Size<u32>,
|
||||
format: GLenum,
|
||||
max_levels: u32,
|
||||
levels: u32,
|
||||
is_raw: bool,
|
||||
}
|
||||
pub struct Gl46Framebuffer;
|
||||
|
||||
impl Framebuffer for Gl46Framebuffer {
|
||||
fn handle(&self) -> GLuint {
|
||||
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 {
|
||||
impl FramebufferInterface for Gl46Framebuffer {
|
||||
fn new(max_levels: u32) -> Framebuffer {
|
||||
let mut framebuffer = 0;
|
||||
unsafe {
|
||||
gl::CreateFramebuffers(1, &mut framebuffer);
|
||||
}
|
||||
|
||||
Gl46Framebuffer {
|
||||
Framebuffer {
|
||||
image: 0,
|
||||
size: Size {
|
||||
width: 1,
|
||||
|
@ -48,7 +25,7 @@ impl Framebuffer for Gl46Framebuffer {
|
|||
},
|
||||
format: 0,
|
||||
max_levels,
|
||||
levels: 0,
|
||||
mip_levels: 0,
|
||||
handle: framebuffer,
|
||||
is_raw: false,
|
||||
}
|
||||
|
@ -59,49 +36,38 @@ impl Framebuffer for Gl46Framebuffer {
|
|||
format: GLenum,
|
||||
size: Size<u32>,
|
||||
miplevels: u32,
|
||||
) -> Gl46Framebuffer {
|
||||
Gl46Framebuffer {
|
||||
) -> Framebuffer {
|
||||
Framebuffer {
|
||||
image: texture,
|
||||
size,
|
||||
format,
|
||||
max_levels: miplevels,
|
||||
levels: miplevels,
|
||||
mip_levels: miplevels,
|
||||
handle,
|
||||
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(
|
||||
&mut self,
|
||||
fb: &mut Framebuffer,
|
||||
scaling: Scale2D,
|
||||
format: ImageFormat,
|
||||
viewport: &Viewport<Self>,
|
||||
viewport: &Viewport,
|
||||
_original: &Texture,
|
||||
source: &Texture,
|
||||
) -> Result<Size<u32>> {
|
||||
if self.is_raw {
|
||||
return Ok(self.size);
|
||||
if fb.is_raw {
|
||||
return Ok(fb.size);
|
||||
}
|
||||
|
||||
let size =
|
||||
librashader_runtime::scaling::scale(scaling, source.image.size, viewport.output.size);
|
||||
|
||||
if self.size != size {
|
||||
self.size = size;
|
||||
if fb.size != size {
|
||||
fb.size = size;
|
||||
|
||||
self.init(
|
||||
Self::init(
|
||||
fb,
|
||||
size,
|
||||
if format == ImageFormat::Unknown {
|
||||
ImageFormat::R8G8B8A8Unorm
|
||||
|
@ -112,38 +78,40 @@ impl Framebuffer for Gl46Framebuffer {
|
|||
}
|
||||
Ok(size)
|
||||
}
|
||||
fn clear<const REBIND: bool>(&self) {
|
||||
fn clear<const REBIND: bool>(fb: &Framebuffer) {
|
||||
unsafe {
|
||||
gl::ClearNamedFramebufferfv(
|
||||
self.handle,
|
||||
fb.handle,
|
||||
gl::COLOR,
|
||||
0,
|
||||
[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.
|
||||
if image.size != self.size || image.format != self.format {
|
||||
self.init(image.size, image.format)?;
|
||||
if image.size != fb.size || image.format != fb.format {
|
||||
Self::init(
|
||||
fb,
|
||||
image.size, image.format)?;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// gl::NamedFramebufferDrawBuffer(self.handle, gl::COLOR_ATTACHMENT1);
|
||||
// gl::NamedFramebufferDrawBuffer(fb.handle, gl::COLOR_ATTACHMENT1);
|
||||
gl::NamedFramebufferReadBuffer(image.handle, gl::COLOR_ATTACHMENT0);
|
||||
gl::NamedFramebufferDrawBuffer(self.handle, gl::COLOR_ATTACHMENT1);
|
||||
gl::NamedFramebufferDrawBuffer(fb.handle, gl::COLOR_ATTACHMENT1);
|
||||
|
||||
gl::BlitNamedFramebuffer(
|
||||
image.handle,
|
||||
self.handle,
|
||||
fb.handle,
|
||||
0,
|
||||
0,
|
||||
image.size.width as GLint,
|
||||
image.size.height as GLint,
|
||||
0,
|
||||
0,
|
||||
self.size.width as GLint,
|
||||
self.size.height as GLint,
|
||||
fb.size.width as GLint,
|
||||
fb.size.height as GLint,
|
||||
gl::COLOR_BUFFER_BIT,
|
||||
gl::NEAREST,
|
||||
);
|
||||
|
@ -151,21 +119,21 @@ impl Framebuffer for Gl46Framebuffer {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
fn init(&mut self, mut size: Size<u32>, format: impl Into<GLenum>) -> Result<()> {
|
||||
if self.is_raw {
|
||||
fn init(fb: &mut Framebuffer, mut size: Size<u32>, format: impl Into<GLenum>) -> Result<()> {
|
||||
if fb.is_raw {
|
||||
return Ok(());
|
||||
}
|
||||
self.format = format.into();
|
||||
self.size = size;
|
||||
fb.format = format.into();
|
||||
fb.size = size;
|
||||
|
||||
unsafe {
|
||||
// reset the framebuffer image
|
||||
if self.image != 0 {
|
||||
gl::NamedFramebufferTexture(self.handle, gl::COLOR_ATTACHMENT0, 0, 0);
|
||||
gl::DeleteTextures(1, &self.image);
|
||||
if fb.image != 0 {
|
||||
gl::NamedFramebufferTexture(fb.handle, gl::COLOR_ATTACHMENT0, 0, 0);
|
||||
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 {
|
||||
size.width = 1;
|
||||
|
@ -174,23 +142,23 @@ impl Framebuffer for Gl46Framebuffer {
|
|||
size.height = 1;
|
||||
}
|
||||
|
||||
self.levels = librashader_runtime::scaling::calc_miplevel(size);
|
||||
if self.levels > self.max_levels {
|
||||
self.levels = self.max_levels;
|
||||
fb.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
|
||||
if fb.mip_levels > fb.max_levels {
|
||||
fb.mip_levels = fb.max_levels;
|
||||
}
|
||||
if self.levels == 0 {
|
||||
self.levels = 1;
|
||||
if fb.mip_levels == 0 {
|
||||
fb.mip_levels = 1;
|
||||
}
|
||||
|
||||
gl::TextureStorage2D(
|
||||
self.image,
|
||||
self.levels as GLsizei,
|
||||
self.format,
|
||||
fb.image,
|
||||
fb.mip_levels as GLsizei,
|
||||
fb.format,
|
||||
size.width 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);
|
||||
if status != gl::FRAMEBUFFER_COMPLETE {
|
||||
|
@ -198,32 +166,27 @@ impl Framebuffer for Gl46Framebuffer {
|
|||
gl::FRAMEBUFFER_UNSUPPORTED => {
|
||||
eprintln!("unsupported fbo");
|
||||
|
||||
gl::NamedFramebufferTexture(self.handle, gl::COLOR_ATTACHMENT0, 0, 0);
|
||||
gl::DeleteTextures(1, &self.image);
|
||||
gl::CreateTextures(gl::TEXTURE_2D, 1, &mut self.image);
|
||||
gl::NamedFramebufferTexture(fb.handle, gl::COLOR_ATTACHMENT0, 0, 0);
|
||||
gl::DeleteTextures(1, &fb.image);
|
||||
gl::CreateTextures(gl::TEXTURE_2D, 1, &mut fb.image);
|
||||
|
||||
self.levels = librashader_runtime::scaling::calc_miplevel(size);
|
||||
if self.levels > self.max_levels {
|
||||
self.levels = self.max_levels;
|
||||
fb.mip_levels = librashader_runtime::scaling::calc_miplevel(size);
|
||||
if fb.mip_levels > fb.max_levels {
|
||||
fb.mip_levels = fb.max_levels;
|
||||
}
|
||||
if self.levels == 0 {
|
||||
self.levels = 1;
|
||||
if fb.mip_levels == 0 {
|
||||
fb.mip_levels = 1;
|
||||
}
|
||||
|
||||
gl::TextureStorage2D(
|
||||
self.image,
|
||||
self.levels as GLsizei,
|
||||
fb.image,
|
||||
fb.mip_levels as GLsizei,
|
||||
ImageFormat::R8G8B8A8Unorm.into(),
|
||||
size.width as GLsizei,
|
||||
size.height as GLsizei,
|
||||
);
|
||||
gl::NamedFramebufferTexture(
|
||||
self.handle,
|
||||
gl::COLOR_ATTACHMENT0,
|
||||
self.image,
|
||||
0,
|
||||
);
|
||||
// self.init =
|
||||
gl::NamedFramebufferTexture(fb.handle, gl::COLOR_ATTACHMENT0, fb.image, 0);
|
||||
// fb.init =
|
||||
// gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
_ => return Err(FilterChainError::FramebufferInit(status)),
|
||||
|
@ -233,16 +196,3 @@ impl Framebuffer for Gl46Framebuffer {
|
|||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use librashader_common::Size;
|
|||
use crate::filter_chain::FilterChain;
|
||||
use crate::framebuffer::{GLImage, Viewport};
|
||||
use crate::gl::gl46::DirectStateAccessGL;
|
||||
use crate::gl::{Framebuffer, GLInterface};
|
||||
use crate::gl::{FramebufferInterface, GLInterface};
|
||||
|
||||
const WIDTH: u32 = 900;
|
||||
const HEIGHT: u32 = 700;
|
||||
|
@ -258,7 +258,7 @@ pub fn do_loop(
|
|||
events: Receiver<(f64, WindowEvent)>,
|
||||
triangle_program: GLuint,
|
||||
triangle_vao: GLuint,
|
||||
filter: &mut FilterChain<DirectStateAccessGL>,
|
||||
filter: &mut FilterChain,
|
||||
) {
|
||||
let mut framecount = 0;
|
||||
let mut rendered_framebuffer = 0;
|
||||
|
@ -455,7 +455,7 @@ void main()
|
|||
let (fb_width, fb_height) = window.get_framebuffer_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_framebuffer_handle,
|
||||
gl::RGBA8,
|
||||
|
|
|
@ -16,7 +16,7 @@ use ubo_ring::*;
|
|||
|
||||
pub struct DirectStateAccessGL;
|
||||
impl GLInterface for DirectStateAccessGL {
|
||||
type Framebuffer = Gl46Framebuffer;
|
||||
type FramebufferInterface = Gl46Framebuffer;
|
||||
type UboRing = Gl46UboRing<16>;
|
||||
type DrawQuad = Gl46DrawQuad;
|
||||
type LoadLut = Gl46LutLoad;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
mod framebuffer;
|
||||
pub(crate) mod gl3;
|
||||
pub(crate) mod gl46;
|
||||
|
||||
|
@ -6,6 +7,7 @@ use crate::error::Result;
|
|||
use crate::framebuffer::{GLImage, Viewport};
|
||||
use crate::samplers::SamplerSet;
|
||||
use crate::texture::Texture;
|
||||
pub use framebuffer::Framebuffer;
|
||||
use gl::types::{GLenum, GLuint};
|
||||
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||
use librashader_presets::{Scale2D, TextureConfig};
|
||||
|
@ -33,31 +35,26 @@ pub trait UboRing<const SIZE: usize> {
|
|||
);
|
||||
}
|
||||
|
||||
pub trait Framebuffer {
|
||||
fn new(max_levels: u32) -> Self;
|
||||
pub trait FramebufferInterface {
|
||||
fn new(max_levels: u32) -> Framebuffer;
|
||||
fn new_from_raw(
|
||||
texture: GLuint,
|
||||
handle: GLuint,
|
||||
format: GLenum,
|
||||
size: Size<u32>,
|
||||
miplevels: u32,
|
||||
) -> Self;
|
||||
fn as_texture(&self, filter: FilterMode, wrap_mode: WrapMode) -> Texture;
|
||||
) -> Framebuffer;
|
||||
fn scale(
|
||||
&mut self,
|
||||
fb: &mut Framebuffer,
|
||||
scaling: Scale2D,
|
||||
format: ImageFormat,
|
||||
viewport: &Viewport<Self>,
|
||||
viewport: &Viewport,
|
||||
_original: &Texture,
|
||||
source: &Texture,
|
||||
) -> Result<Size<u32>>;
|
||||
fn clear<const REBIND: bool>(&self);
|
||||
fn copy_from(&mut self, image: &GLImage) -> Result<()>;
|
||||
fn init(&mut self, 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;
|
||||
fn clear<const REBIND: bool>(fb: &Framebuffer);
|
||||
fn copy_from(fb: &mut Framebuffer, image: &GLImage) -> Result<()>;
|
||||
fn init(fb: &mut Framebuffer, size: Size<u32>, format: impl Into<GLenum>) -> Result<()>;
|
||||
}
|
||||
|
||||
pub trait BindTexture {
|
||||
|
@ -65,7 +62,7 @@ pub trait BindTexture {
|
|||
}
|
||||
|
||||
pub trait GLInterface {
|
||||
type Framebuffer: Framebuffer;
|
||||
type FramebufferInterface: FramebufferInterface;
|
||||
type UboRing: UboRing<16>;
|
||||
type DrawQuad: DrawQuad;
|
||||
type LoadLut: LoadLut;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#![feature(strict_provenance)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(let_chains)]
|
||||
|
||||
mod binding;
|
||||
mod filter_chain;
|
||||
|
@ -9,42 +10,29 @@ mod render_target;
|
|||
mod util;
|
||||
|
||||
mod gl;
|
||||
pub mod options;
|
||||
mod samplers;
|
||||
mod texture;
|
||||
|
||||
pub mod options;
|
||||
pub mod error;
|
||||
pub use filter_chain::FilterChain;
|
||||
pub use framebuffer::Viewport;
|
||||
|
||||
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,
|
||||
>;
|
||||
}
|
||||
pub use framebuffer::GLImage;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::filter_chain::FilterChain;
|
||||
use crate::options::FilterChainOptions;
|
||||
|
||||
#[test]
|
||||
fn triangle_gl() {
|
||||
let (glfw, window, events, shader, vao) = gl::gl3::hello_triangle::setup();
|
||||
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)
|
||||
.unwrap();
|
||||
gl::gl3::hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter);
|
||||
|
@ -54,7 +42,10 @@ mod tests {
|
|||
fn triangle_gl46() {
|
||||
let (glfw, window, events, shader, vao) = gl::gl46::hello_triangle::setup();
|
||||
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)
|
||||
.unwrap();
|
||||
gl::gl46::hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter);
|
||||
|
|
|
@ -8,4 +8,5 @@ pub struct FrameOptions {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct FilterChainOptions {
|
||||
pub gl_version: u16,
|
||||
pub use_dsa: bool
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::framebuffer::Viewport;
|
||||
use crate::gl::Framebuffer;
|
||||
use crate::gl::{Framebuffer, FramebufferInterface};
|
||||
|
||||
#[rustfmt::skip]
|
||||
static DEFAULT_MVP: &[f32; 16] = &[
|
||||
|
@ -10,15 +10,15 @@ static DEFAULT_MVP: &[f32; 16] = &[
|
|||
];
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) struct RenderTarget<'a, T: Framebuffer> {
|
||||
pub(crate) struct RenderTarget<'a> {
|
||||
pub mvp: &'a [f32; 16],
|
||||
pub framebuffer: &'a T,
|
||||
pub framebuffer: &'a Framebuffer,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl<'a, T: Framebuffer> RenderTarget<'a, T> {
|
||||
pub fn new(backbuffer: &'a T, mvp: Option<&'a [f32; 16]>, x: i32, y: i32) -> Self {
|
||||
impl<'a> RenderTarget<'a> {
|
||||
pub fn new(backbuffer: &'a Framebuffer, mvp: Option<&'a [f32; 16]>, x: i32, y: i32) -> Self {
|
||||
if let Some(mvp) = mvp {
|
||||
RenderTarget {
|
||||
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> {
|
||||
fn from(value: &Viewport<'a, T>) -> Self {
|
||||
impl<'a> From<&Viewport<'a>> for RenderTarget<'a> {
|
||||
fn from(value: &Viewport<'a>) -> Self {
|
||||
RenderTarget::new(value.output, value.mvp, value.x, value.y)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ pub fn gl_get_version() -> GlVersion {
|
|||
|
||||
pub fn gl_u16_to_version(version: u16) -> GlVersion {
|
||||
match version {
|
||||
0 => gl_get_version(),
|
||||
300 => GlVersion::V1_30,
|
||||
310 => GlVersion::V1_40,
|
||||
320 => GlVersion::V1_50,
|
||||
|
|
|
@ -31,18 +31,7 @@ pub mod targets {
|
|||
|
||||
/// Shader runtime for OpenGL.
|
||||
pub mod runtime {
|
||||
pub use librashader_runtime_gl::error;
|
||||
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::*;
|
||||
}
|
||||
pub use librashader_runtime_gl::*;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue