From 1f068bc0d5e9478d8f2f5df491e43f40d16fff60 Mon Sep 17 00:00:00 2001 From: chyyran Date: Sat, 26 Nov 2022 16:47:48 -0500 Subject: [PATCH] gl: try using samplerset --- librashader-runtime-gl/Cargo.toml | 3 + librashader-runtime-gl/src/filter_chain.rs | 71 ++++++++++---------- librashader-runtime-gl/src/filter_pass.rs | 61 ++++++++--------- librashader-runtime-gl/src/lib.rs | 2 + librashader-runtime-gl/src/samplers.rs | 76 ++++++++++++++++++++++ 5 files changed, 151 insertions(+), 62 deletions(-) create mode 100644 librashader-runtime-gl/src/samplers.rs diff --git a/librashader-runtime-gl/Cargo.toml b/librashader-runtime-gl/Cargo.toml index 060a471..4b35ce1 100644 --- a/librashader-runtime-gl/Cargo.toml +++ b/librashader-runtime-gl/Cargo.toml @@ -18,3 +18,6 @@ thiserror = "1.0.37" [dev-dependencies] glfw = "0.47.0" + +[features] +gl4 = [] \ No newline at end of file diff --git a/librashader-runtime-gl/src/filter_chain.rs b/librashader-runtime-gl/src/filter_chain.rs index b3254d8..2af4474 100644 --- a/librashader-runtime-gl/src/filter_chain.rs +++ b/librashader-runtime-gl/src/filter_chain.rs @@ -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, + 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> { + fn load_luts(samplers: &SamplerSet, textures: &[TextureConfig]) -> Result> { 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); } diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index fca3b12..3859510 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -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 diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs index b9e8837..ecce0e7 100644 --- a/librashader-runtime-gl/src/lib.rs +++ b/librashader-runtime-gl/src/lib.rs @@ -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; diff --git a/librashader-runtime-gl/src/samplers.rs b/librashader-runtime-gl/src/samplers.rs new file mode 100644 index 0000000..0cffb25 --- /dev/null +++ b/librashader-runtime-gl/src/samplers.rs @@ -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 + } + } +} +