gl: try using samplerset
This commit is contained in:
parent
bfed01435b
commit
1f068bc0d5
|
@ -18,3 +18,6 @@ thiserror = "1.0.37"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
glfw = "0.47.0"
|
glfw = "0.47.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
gl4 = []
|
|
@ -22,6 +22,7 @@ use std::collections::VecDeque;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
|
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
|
||||||
use librashader_reflect::front::shaderc::GlslangCompilation;
|
use librashader_reflect::front::shaderc::GlslangCompilation;
|
||||||
|
use crate::samplers::SamplerSet;
|
||||||
|
|
||||||
pub struct FilterChain {
|
pub struct FilterChain {
|
||||||
passes: Box<[FilterPass]>,
|
passes: Box<[FilterPass]>,
|
||||||
|
@ -36,6 +37,7 @@ pub struct FilterCommon {
|
||||||
// semantics: ReflectSemantics,
|
// semantics: ReflectSemantics,
|
||||||
pub(crate) preset: ShaderPreset,
|
pub(crate) preset: ShaderPreset,
|
||||||
pub(crate) luts: FxHashMap<usize, Texture>,
|
pub(crate) luts: FxHashMap<usize, Texture>,
|
||||||
|
pub(crate) 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]>,
|
||||||
|
@ -142,6 +144,8 @@ impl FilterChain {
|
||||||
.map(|f| f.config.wrap_mode)
|
.map(|f| f.config.wrap_mode)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let samplers = SamplerSet::new();
|
||||||
|
|
||||||
// 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(), || Framebuffer::new(1));
|
||||||
|
@ -155,7 +159,7 @@ impl FilterChain {
|
||||||
feedback_textures.resize_with(filters.len(), Texture::default);
|
feedback_textures.resize_with(filters.len(), Texture::default);
|
||||||
|
|
||||||
// load luts
|
// load luts
|
||||||
let luts = FilterChain::load_luts(&preset.textures)?;
|
let luts = FilterChain::load_luts(&samplers, &preset.textures)?;
|
||||||
|
|
||||||
let (history_framebuffers, history_textures) =
|
let (history_framebuffers, history_textures) =
|
||||||
FilterChain::init_history(&filters, default_filter, default_wrap);
|
FilterChain::init_history(&filters, default_filter, default_wrap);
|
||||||
|
@ -179,6 +183,7 @@ impl FilterChain {
|
||||||
// semantics,
|
// semantics,
|
||||||
preset,
|
preset,
|
||||||
luts,
|
luts,
|
||||||
|
samplers,
|
||||||
output_textures: output_textures.into_boxed_slice(),
|
output_textures: output_textures.into_boxed_slice(),
|
||||||
feedback_textures: feedback_textures.into_boxed_slice(),
|
feedback_textures: feedback_textures.into_boxed_slice(),
|
||||||
history_textures,
|
history_textures,
|
||||||
|
@ -260,7 +265,7 @@ impl FilterChain {
|
||||||
Ok((passes, semantics))
|
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();
|
let mut luts = FxHashMap::default();
|
||||||
|
|
||||||
for (index, texture) in textures.iter().enumerate() {
|
for (index, texture) in textures.iter().enumerate() {
|
||||||
|
@ -299,7 +304,7 @@ impl FilterChain {
|
||||||
);
|
);
|
||||||
|
|
||||||
let mipmap = levels > 1;
|
let mipmap = levels > 1;
|
||||||
let linear = texture.filter_mode == FilterMode::Linear;
|
// let linear = texture.filter_mode == FilterMode::Linear;
|
||||||
|
|
||||||
// set mipmaps and wrapping
|
// set mipmaps and wrapping
|
||||||
|
|
||||||
|
@ -307,36 +312,36 @@ impl FilterChain {
|
||||||
gl::GenerateMipmap(gl::TEXTURE_2D);
|
gl::GenerateMipmap(gl::TEXTURE_2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::TexParameteri(
|
// gl::TexParameteri(
|
||||||
gl::TEXTURE_2D,
|
// gl::TEXTURE_2D,
|
||||||
gl::TEXTURE_WRAP_S,
|
// gl::TEXTURE_WRAP_S,
|
||||||
GLenum::from(texture.wrap_mode) as GLint,
|
// GLenum::from(texture.wrap_mode) as GLint,
|
||||||
);
|
// );
|
||||||
gl::TexParameteri(
|
// gl::TexParameteri(
|
||||||
gl::TEXTURE_2D,
|
// gl::TEXTURE_2D,
|
||||||
gl::TEXTURE_WRAP_T,
|
// gl::TEXTURE_WRAP_T,
|
||||||
GLenum::from(texture.wrap_mode) as GLint,
|
// GLenum::from(texture.wrap_mode) as GLint,
|
||||||
);
|
// );
|
||||||
|
//
|
||||||
if !linear {
|
// if !linear {
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
|
// 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);
|
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
|
||||||
} else {
|
// } else {
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
|
// gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
|
||||||
if mipmap {
|
// if mipmap {
|
||||||
gl::TexParameteri(
|
// gl::TexParameteri(
|
||||||
gl::TEXTURE_2D,
|
// gl::TEXTURE_2D,
|
||||||
gl::TEXTURE_MIN_FILTER,
|
// gl::TEXTURE_MIN_FILTER,
|
||||||
gl::LINEAR_MIPMAP_LINEAR as GLint,
|
// gl::LINEAR_MIPMAP_LINEAR as GLint,
|
||||||
);
|
// );
|
||||||
} else {
|
// } else {
|
||||||
gl::TexParameteri(
|
// gl::TexParameteri(
|
||||||
gl::TEXTURE_2D,
|
// gl::TEXTURE_2D,
|
||||||
gl::TEXTURE_MIN_FILTER,
|
// gl::TEXTURE_MIN_FILTER,
|
||||||
gl::LINEAR as GLint,
|
// gl::LINEAR as GLint,
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
gl::BindTexture(gl::TEXTURE_2D, 0);
|
gl::BindTexture(gl::TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use crate::binding::{UniformLocation, VariableLocation};
|
||||||
use crate::filter_chain::FilterCommon;
|
use crate::filter_chain::FilterCommon;
|
||||||
use crate::framebuffer::Viewport;
|
use crate::framebuffer::Viewport;
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
|
use crate::samplers::SamplerSet;
|
||||||
use crate::util::{InlineRingBuffer, RingBuffer, Texture};
|
use crate::util::{InlineRingBuffer, RingBuffer, Texture};
|
||||||
|
|
||||||
pub struct FilterPass {
|
pub struct FilterPass {
|
||||||
|
@ -88,32 +89,34 @@ impl FilterPass {
|
||||||
Self::build_uniform(location, buffer, value, gl::Uniform1f)
|
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 {
|
unsafe {
|
||||||
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
|
||||||
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
||||||
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
|
||||||
|
|
||||||
gl::TexParameteri(
|
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
||||||
gl::TEXTURE_2D,
|
gl::BindSampler(gl::TEXTURE0 + binding.binding,
|
||||||
gl::TEXTURE_MAG_FILTER,
|
samplers.get(texture.wrap_mode, texture.filter, texture.mip_filter));
|
||||||
GLenum::from(texture.filter) as GLint,
|
// gl::TexParameteri(
|
||||||
);
|
// gl::TEXTURE_2D,
|
||||||
gl::TexParameteri(
|
// gl::TEXTURE_MAG_FILTER,
|
||||||
gl::TEXTURE_2D,
|
// GLenum::from(texture.filter) as GLint,
|
||||||
gl::TEXTURE_MIN_FILTER,
|
// );
|
||||||
texture.filter.gl_mip(texture.mip_filter) as GLint,
|
// gl::TexParameteri(
|
||||||
);
|
// gl::TEXTURE_2D,
|
||||||
gl::TexParameteri(
|
// gl::TEXTURE_MIN_FILTER,
|
||||||
gl::TEXTURE_2D,
|
// texture.filter.gl_mip(texture.mip_filter) as GLint,
|
||||||
gl::TEXTURE_WRAP_S,
|
// );
|
||||||
GLenum::from(texture.wrap_mode) as GLint,
|
// gl::TexParameteri(
|
||||||
);
|
// gl::TEXTURE_2D,
|
||||||
gl::TexParameteri(
|
// gl::TEXTURE_WRAP_S,
|
||||||
gl::TEXTURE_2D,
|
// GLenum::from(texture.wrap_mode) as GLint,
|
||||||
gl::TEXTURE_WRAP_T,
|
// );
|
||||||
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
|
.texture_meta
|
||||||
.get(&TextureSemantics::Original.semantics(0))
|
.get(&TextureSemantics::Original.semantics(0))
|
||||||
{
|
{
|
||||||
FilterPass::bind_texture(binding, original);
|
FilterPass::bind_texture(&parent.samplers, binding, original);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind OriginalSize
|
// bind OriginalSize
|
||||||
|
@ -362,7 +365,7 @@ impl FilterPass {
|
||||||
.get(&TextureSemantics::Source.semantics(0))
|
.get(&TextureSemantics::Source.semantics(0))
|
||||||
{
|
{
|
||||||
// eprintln!("setting source binding to {}", binding.binding);
|
// eprintln!("setting source binding to {}", binding.binding);
|
||||||
FilterPass::bind_texture(binding, source);
|
FilterPass::bind_texture(&parent.samplers, binding, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind SourceSize
|
// bind SourceSize
|
||||||
|
@ -387,7 +390,7 @@ impl FilterPass {
|
||||||
.texture_meta
|
.texture_meta
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(0))
|
.get(&TextureSemantics::OriginalHistory.semantics(0))
|
||||||
{
|
{
|
||||||
FilterPass::bind_texture(binding, original);
|
FilterPass::bind_texture(&parent.samplers, binding, original);
|
||||||
}
|
}
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
.uniform_bindings
|
.uniform_bindings
|
||||||
|
@ -411,7 +414,7 @@ impl FilterPass {
|
||||||
.texture_meta
|
.texture_meta
|
||||||
.get(&TextureSemantics::OriginalHistory.semantics(index + 1))
|
.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(
|
if let Some((location, offset)) = self.uniform_bindings.get(
|
||||||
|
@ -439,7 +442,7 @@ impl FilterPass {
|
||||||
.texture_meta
|
.texture_meta
|
||||||
.get(&TextureSemantics::PassOutput.semantics(index))
|
.get(&TextureSemantics::PassOutput.semantics(index))
|
||||||
{
|
{
|
||||||
FilterPass::bind_texture(binding, output);
|
FilterPass::bind_texture(&parent.samplers, binding, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
|
@ -469,7 +472,7 @@ impl FilterPass {
|
||||||
if feedback.image.handle == 0 {
|
if feedback.image.handle == 0 {
|
||||||
eprintln!("[WARNING] trying to bind PassFeedback: {index} which has texture 0 to slot {} in pass {pass_index}", binding.binding)
|
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
|
if let Some((location, offset)) = self
|
||||||
|
@ -532,7 +535,7 @@ impl FilterPass {
|
||||||
.texture_meta
|
.texture_meta
|
||||||
.get(&TextureSemantics::User.semantics(*index))
|
.get(&TextureSemantics::User.semantics(*index))
|
||||||
{
|
{
|
||||||
FilterPass::bind_texture(binding, lut);
|
FilterPass::bind_texture(&parent.samplers, binding, lut);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self
|
if let Some((location, offset)) = self
|
||||||
|
|
|
@ -10,6 +10,8 @@ mod render_target;
|
||||||
mod util;
|
mod util;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
|
mod samplers;
|
||||||
|
|
||||||
pub use filter_chain::FilterChain;
|
pub use filter_chain::FilterChain;
|
||||||
pub use framebuffer::Framebuffer;
|
pub use framebuffer::Framebuffer;
|
||||||
pub use framebuffer::GlImage;
|
pub use framebuffer::GlImage;
|
||||||
|
|
76
librashader-runtime-gl/src/samplers.rs
Normal file
76
librashader-runtime-gl/src/samplers.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue