gl: try using samplerset

This commit is contained in:
chyyran 2022-11-26 16:47:48 -05:00
parent bfed01435b
commit 1f068bc0d5
5 changed files with 151 additions and 62 deletions

View file

@ -18,3 +18,6 @@ thiserror = "1.0.37"
[dev-dependencies]
glfw = "0.47.0"
[features]
gl4 = []

View file

@ -22,6 +22,7 @@ use std::collections::VecDeque;
use std::path::Path;
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
use librashader_reflect::front::shaderc::GlslangCompilation;
use crate::samplers::SamplerSet;
pub struct FilterChain {
passes: Box<[FilterPass]>,
@ -36,6 +37,7 @@ pub struct FilterCommon {
// semantics: ReflectSemantics,
pub(crate) preset: ShaderPreset,
pub(crate) luts: FxHashMap<usize, Texture>,
pub(crate) samplers: SamplerSet,
pub output_textures: Box<[Texture]>,
pub feedback_textures: Box<[Texture]>,
pub history_textures: Box<[Texture]>,
@ -142,6 +144,8 @@ impl FilterChain {
.map(|f| f.config.wrap_mode)
.unwrap_or_default();
let samplers = SamplerSet::new();
// initialize output framebuffers
let mut output_framebuffers = Vec::new();
output_framebuffers.resize_with(filters.len(), || Framebuffer::new(1));
@ -155,7 +159,7 @@ impl FilterChain {
feedback_textures.resize_with(filters.len(), Texture::default);
// load luts
let luts = FilterChain::load_luts(&preset.textures)?;
let luts = FilterChain::load_luts(&samplers, &preset.textures)?;
let (history_framebuffers, history_textures) =
FilterChain::init_history(&filters, default_filter, default_wrap);
@ -179,6 +183,7 @@ impl FilterChain {
// semantics,
preset,
luts,
samplers,
output_textures: output_textures.into_boxed_slice(),
feedback_textures: feedback_textures.into_boxed_slice(),
history_textures,
@ -260,7 +265,7 @@ impl FilterChain {
Ok((passes, semantics))
}
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>> {
fn load_luts(samplers: &SamplerSet, textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>> {
let mut luts = FxHashMap::default();
for (index, texture) in textures.iter().enumerate() {
@ -299,7 +304,7 @@ impl FilterChain {
);
let mipmap = levels > 1;
let linear = texture.filter_mode == FilterMode::Linear;
// let linear = texture.filter_mode == FilterMode::Linear;
// set mipmaps and wrapping
@ -307,36 +312,36 @@ impl FilterChain {
gl::GenerateMipmap(gl::TEXTURE_2D);
}
gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_WRAP_S,
GLenum::from(texture.wrap_mode) as GLint,
);
gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_WRAP_T,
GLenum::from(texture.wrap_mode) as GLint,
);
if !linear {
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
} else {
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
if mipmap {
gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MIN_FILTER,
gl::LINEAR_MIPMAP_LINEAR as GLint,
);
} else {
gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MIN_FILTER,
gl::LINEAR as GLint,
);
}
}
// gl::TexParameteri(
// gl::TEXTURE_2D,
// gl::TEXTURE_WRAP_S,
// GLenum::from(texture.wrap_mode) as GLint,
// );
// gl::TexParameteri(
// gl::TEXTURE_2D,
// gl::TEXTURE_WRAP_T,
// GLenum::from(texture.wrap_mode) as GLint,
// );
//
// if !linear {
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
// } else {
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
// if mipmap {
// gl::TexParameteri(
// gl::TEXTURE_2D,
// gl::TEXTURE_MIN_FILTER,
// gl::LINEAR_MIPMAP_LINEAR as GLint,
// );
// } else {
// gl::TexParameteri(
// gl::TEXTURE_2D,
// gl::TEXTURE_MIN_FILTER,
// gl::LINEAR as GLint,
// );
// }
// }
gl::BindTexture(gl::TEXTURE_2D, 0);
}

View file

@ -13,6 +13,7 @@ use crate::binding::{UniformLocation, VariableLocation};
use crate::filter_chain::FilterCommon;
use crate::framebuffer::Viewport;
use crate::render_target::RenderTarget;
use crate::samplers::SamplerSet;
use crate::util::{InlineRingBuffer, RingBuffer, Texture};
pub struct FilterPass {
@ -88,32 +89,34 @@ impl FilterPass {
Self::build_uniform(location, buffer, value, gl::Uniform1f)
}
fn bind_texture(binding: &TextureBinding, texture: &Texture) {
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
unsafe {
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MAG_FILTER,
GLenum::from(texture.filter) as GLint,
);
gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MIN_FILTER,
texture.filter.gl_mip(texture.mip_filter) as GLint,
);
gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_WRAP_S,
GLenum::from(texture.wrap_mode) as GLint,
);
gl::TexParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_WRAP_T,
GLenum::from(texture.wrap_mode) as GLint,
);
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
gl::BindSampler(gl::TEXTURE0 + binding.binding,
samplers.get(texture.wrap_mode, texture.filter, texture.mip_filter));
// gl::TexParameteri(
// gl::TEXTURE_2D,
// gl::TEXTURE_MAG_FILTER,
// GLenum::from(texture.filter) as GLint,
// );
// gl::TexParameteri(
// gl::TEXTURE_2D,
// gl::TEXTURE_MIN_FILTER,
// texture.filter.gl_mip(texture.mip_filter) as GLint,
// );
// gl::TexParameteri(
// gl::TEXTURE_2D,
// gl::TEXTURE_WRAP_S,
// GLenum::from(texture.wrap_mode) as GLint,
// );
// gl::TexParameteri(
// gl::TEXTURE_2D,
// gl::TEXTURE_WRAP_T,
// GLenum::from(texture.wrap_mode) as GLint,
// );
}
}
@ -335,7 +338,7 @@ impl FilterPass {
.texture_meta
.get(&TextureSemantics::Original.semantics(0))
{
FilterPass::bind_texture(binding, original);
FilterPass::bind_texture(&parent.samplers, binding, original);
}
// bind OriginalSize
@ -362,7 +365,7 @@ impl FilterPass {
.get(&TextureSemantics::Source.semantics(0))
{
// eprintln!("setting source binding to {}", binding.binding);
FilterPass::bind_texture(binding, source);
FilterPass::bind_texture(&parent.samplers, binding, source);
}
// bind SourceSize
@ -387,7 +390,7 @@ impl FilterPass {
.texture_meta
.get(&TextureSemantics::OriginalHistory.semantics(0))
{
FilterPass::bind_texture(binding, original);
FilterPass::bind_texture(&parent.samplers, binding, original);
}
if let Some((location, offset)) = self
.uniform_bindings
@ -411,7 +414,7 @@ impl FilterPass {
.texture_meta
.get(&TextureSemantics::OriginalHistory.semantics(index + 1))
{
FilterPass::bind_texture(binding, output);
FilterPass::bind_texture(&parent.samplers, binding, output);
}
if let Some((location, offset)) = self.uniform_bindings.get(
@ -439,7 +442,7 @@ impl FilterPass {
.texture_meta
.get(&TextureSemantics::PassOutput.semantics(index))
{
FilterPass::bind_texture(binding, output);
FilterPass::bind_texture(&parent.samplers, binding, output);
}
if let Some((location, offset)) = self
@ -469,7 +472,7 @@ impl FilterPass {
if feedback.image.handle == 0 {
eprintln!("[WARNING] trying to bind PassFeedback: {index} which has texture 0 to slot {} in pass {pass_index}", binding.binding)
}
FilterPass::bind_texture(binding, feedback);
FilterPass::bind_texture(&parent.samplers, binding, feedback);
}
if let Some((location, offset)) = self
@ -532,7 +535,7 @@ impl FilterPass {
.texture_meta
.get(&TextureSemantics::User.semantics(*index))
{
FilterPass::bind_texture(binding, lut);
FilterPass::bind_texture(&parent.samplers, binding, lut);
}
if let Some((location, offset)) = self

View file

@ -10,6 +10,8 @@ mod render_target;
mod util;
pub mod error;
mod samplers;
pub use filter_chain::FilterChain;
pub use framebuffer::Framebuffer;
pub use framebuffer::GlImage;

View file

@ -0,0 +1,76 @@
use gl::types::{GLenum, GLint, GLuint};
use rustc_hash::FxHashMap;
use librashader_common::{FilterMode, WrapMode};
use crate::error::Result;
pub struct SamplerSet {
// todo: may need to deal with differences in mip filter.
samplers: FxHashMap<(WrapMode, FilterMode, FilterMode), GLuint>
}
impl SamplerSet {
pub fn get(&self, wrap: WrapMode, filter: FilterMode, mip: FilterMode) -> GLuint {
// eprintln!("{wrap}, {filter}, {mip}");
*self.samplers.get(&(wrap, filter, mip))
.unwrap()
}
fn make_sampler(sampler: GLuint, wrap: WrapMode, filter: FilterMode, mip: FilterMode) {
unsafe {
gl::SamplerParameteri(
sampler,
gl::TEXTURE_WRAP_S,
GLenum::from(wrap) as GLint,
);
gl::SamplerParameteri(
sampler,
gl::TEXTURE_WRAP_T,
GLenum::from(wrap) as GLint,
);
gl::SamplerParameteri(
sampler,
gl::TEXTURE_MAG_FILTER,
GLenum::from(filter) as GLint,
);
gl::SamplerParameteri(
sampler,
gl::TEXTURE_MIN_FILTER,
GLenum::from(filter.gl_mip(mip)) as GLint,
);
}
}
pub fn new() -> SamplerSet {
let mut samplers = FxHashMap::default();
let wrap_modes =
&[WrapMode::ClampToBorder, WrapMode::ClampToEdge, WrapMode::Repeat, WrapMode::MirroredRepeat];
for wrap_mode in wrap_modes {
unsafe {
let mut linear_linear = 0;
let mut nearest_nearest = 0;
let mut linear_nearest = 0;
let mut nearest_linear = 0;
gl::GenSamplers(1, &mut linear_linear);
gl::GenSamplers(1, &mut linear_nearest);
gl::GenSamplers(1, &mut nearest_linear);
gl::GenSamplers(1, &mut nearest_nearest);
SamplerSet::make_sampler(linear_linear, *wrap_mode, FilterMode::Linear, FilterMode::Linear);
SamplerSet::make_sampler(linear_nearest, *wrap_mode, FilterMode::Linear, FilterMode::Linear);
SamplerSet::make_sampler(nearest_linear, *wrap_mode, FilterMode::Nearest, FilterMode::Linear);
SamplerSet::make_sampler(nearest_linear, *wrap_mode, FilterMode::Nearest, FilterMode::Nearest);
samplers.insert((*wrap_mode, FilterMode::Linear, FilterMode::Linear), linear_linear);
samplers.insert((*wrap_mode, FilterMode::Linear, FilterMode::Nearest), linear_nearest);
samplers.insert((*wrap_mode, FilterMode::Nearest, FilterMode::Nearest), nearest_nearest);
samplers.insert((*wrap_mode, FilterMode::Nearest, FilterMode::Linear), nearest_linear);
}
}
SamplerSet {
samplers
}
}
}