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 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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
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::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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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::*;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue