gl: correct scaling options

This commit is contained in:
chyyran 2022-11-17 01:21:29 -05:00
parent c06751eca9
commit afc750c37c
4 changed files with 173 additions and 70 deletions

View file

@ -1,9 +1,24 @@
use crate::error::ParsePresetError; use crate::error::ParsePresetError;
use std::convert::Infallible; use std::convert::Infallible;
use std::ops::Mul;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use librashader::{FilterMode, WrapMode}; use librashader::{FilterMode, WrapMode};
#[derive(Debug, Clone)]
pub struct ShaderPassConfig {
pub id: i32,
pub name: PathBuf,
pub alias: Option<String>,
pub filter: FilterMode,
pub wrap_mode: WrapMode,
pub frame_count_mod: u32,
pub srgb_framebuffer: bool,
pub float_framebuffer: bool,
pub mipmap_input: bool,
pub scaling: Scale2D,
}
#[repr(i32)] #[repr(i32)]
#[derive(Default, Copy, Clone, Debug)] #[derive(Default, Copy, Clone, Debug)]
pub enum ScaleType { pub enum ScaleType {
@ -25,6 +40,37 @@ impl Default for ScaleFactor {
} }
} }
impl From<ScaleFactor> for f32 {
fn from(value: ScaleFactor) -> Self {
match value {
ScaleFactor::Float(f) => f,
ScaleFactor::Absolute(f) => f as f32,
}
}
}
impl Mul<ScaleFactor> for f32 {
type Output = f32;
fn mul(self, rhs: ScaleFactor) -> Self::Output {
match rhs {
ScaleFactor::Float(f) => f * self,
ScaleFactor::Absolute(f) => f as f32 * self
}
}
}
impl Mul<ScaleFactor> for u32 {
type Output = f32;
fn mul(self, rhs: ScaleFactor) -> Self::Output {
match rhs {
ScaleFactor::Float(f) => f * self as f32,
ScaleFactor::Absolute(f) => (f as u32 * self) as f32
}
}
}
impl FromStr for ScaleType { impl FromStr for ScaleType {
type Err = ParsePresetError; type Err = ParsePresetError;
@ -51,20 +97,6 @@ pub struct Scale2D {
pub y: Scaling, pub y: Scaling,
} }
#[derive(Debug, Clone)]
pub struct ShaderPassConfig {
pub id: i32,
pub name: PathBuf,
pub alias: Option<String>,
pub filter: FilterMode,
pub wrap_mode: WrapMode,
pub frame_count_mod: u32,
pub srgb_framebuffer: bool,
pub float_framebuffer: bool,
pub mipmap_input: bool,
pub scaling: Scale2D,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct TextureConfig { pub struct TextureConfig {
pub name: String, pub name: String,

View file

@ -7,11 +7,11 @@ use librashader_reflect::reflect::TextureSemanticMap;
use librashader_reflect::reflect::VariableSemanticMap; use librashader_reflect::reflect::VariableSemanticMap;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use librashader::ShaderSource; use librashader::ShaderSource;
use librashader_presets::ShaderPreset; use librashader_presets::{Scale2D, ScaleType, Scaling, ShaderPassConfig, ShaderPreset};
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureImage, TextureSemantics, VariableMeta, VariableSemantics}; use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureImage, TextureSemantics, VariableMeta, VariableSemantics};
use crate::FilterChain; use crate::FilterChain;
use crate::framebuffer::Framebuffer; use crate::framebuffer::Framebuffer;
use crate::util::{Location, VariableLocation, RingBuffer, Size, Texture, TextureMeta}; use crate::util::{Location, VariableLocation, RingBuffer, Size, GlImage, Texture, Viewport};
pub struct FilterPass { pub struct FilterPass {
pub reflection: ShaderReflection, pub reflection: ShaderReflection,
@ -25,6 +25,7 @@ pub struct FilterPass {
pub framebuffer: Framebuffer, pub framebuffer: Framebuffer,
pub feedback_framebuffer: Framebuffer, pub feedback_framebuffer: Framebuffer,
pub source: ShaderSource, pub source: ShaderSource,
pub config: ShaderPassConfig
} }
impl FilterPass { impl FilterPass {
@ -81,10 +82,10 @@ impl FilterPass {
Self::build_uniform(location, buffer, value, gl::Uniform1f) Self::build_uniform(location, buffer, value, gl::Uniform1f)
} }
fn set_texture(binding: &TextureImage, texture: &TextureMeta) { fn set_texture(binding: &TextureImage, texture: &Texture) {
unsafe { unsafe {
gl::ActiveTexture((gl::TEXTURE0 + binding.binding) as GLenum); gl::ActiveTexture((gl::TEXTURE0 + binding.binding) as GLenum);
gl::BindTexture(gl::TEXTURE_2D, texture.texture.handle); 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_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_MIN_FILTER, texture.filter.gl_mip(texture.mip_filter) as GLint);
@ -92,10 +93,73 @@ impl FilterPass {
gl::TexParameteri(gl::TEXTURE_2D, 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);
} }
} }
// todo: build vec4 texture
fn scale_framebuffer(&mut self, viewport: &Viewport, original: &Texture, source: &Texture) -> Size {
let mut width = 0f32;
let mut height = 0f32;
match self.config.scaling.x {
Scaling {
scale_type: ScaleType::Input,
factor
} => {
width = source.image.size.width * factor
},
Scaling {
scale_type: ScaleType::Absolute,
factor
} => {
width = factor.into()
}
Scaling {
scale_type: ScaleType::Viewport,
factor
} => {
width = viewport.size.width * factor
}
};
match self.config.scaling.y {
Scaling {
scale_type: ScaleType::Input,
factor
} => {
height = source.image.size.height * factor
},
Scaling {
scale_type: ScaleType::Absolute,
factor
} => {
height = factor.into()
}
Scaling {
scale_type: ScaleType::Viewport,
factor
} => {
height = viewport.size.height * factor
}
};
let size = Size {
width: width.round() as u32,
height: height.round() as u32
};
self.framebuffer.size = size;
size
}
pub fn build_commands(&mut self, parent: &FilterChain, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) {
unsafe {
gl::UseProgram(self.program);
}
}
// framecount should be pre-modded // framecount should be pre-modded
fn build_semantics(&mut self, parent: &FilterChain, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, fb_size: Size, vp_size: Size, original: &TextureMeta, source: &TextureMeta) { fn build_semantics(&mut self, parent: &FilterChain, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) {
let fb_size = self.scale_framebuffer(viewport, original, source);
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::MVP) { if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::MVP) {
let mvp = mvp.unwrap_or(&[ let mvp = mvp.unwrap_or(&[
2f32, 0.0, 0.0, 0.0, 2f32, 0.0, 0.0, 0.0,
@ -118,17 +182,6 @@ impl FilterPass {
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
}; };
FilterPass::build_vec4(location, &mut buffer[offset..][..4], fb_size) FilterPass::build_vec4(location, &mut buffer[offset..][..4], fb_size)
//
// if location.fragment >= 0 || location.vertex >= 0 {
// FilterPass::build_vec4_uniform(location, fb_size);
// } else {
// let (buffer, offset) = match variable.offset {
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
// };
//
// FilterPass::build_vec4(&mut buffer[offset..][..4], fb_size)
// }
} }
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::FinalViewport) { if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::FinalViewport) {
@ -138,10 +191,9 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
}; };
FilterPass::build_vec4(location, &mut buffer[offset..][..4], vp_size) FilterPass::build_vec4(location, &mut buffer[offset..][..4], viewport.size)
} }
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::FrameCount) { if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::FrameCount) {
// todo: do all variables have location..? // todo: do all variables have location..?
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
@ -169,7 +221,7 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
}; };
FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.texture.size); FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) { if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) {
FilterPass::set_texture(binding, original); FilterPass::set_texture(binding, original);
@ -182,10 +234,10 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
}; };
FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.texture.size); FilterPass::build_vec4(location, &mut buffer[offset..][..4], source.image.size);
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) { if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) {
FilterPass::set_texture(binding, original); FilterPass::set_texture(binding, source);
} }
} }
@ -195,7 +247,7 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
}; };
FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.texture.size); FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
FilterPass::set_texture(binding, original); FilterPass::set_texture(binding, original);
@ -221,8 +273,13 @@ impl FilterPass {
FilterPass::build_float(location, &mut buffer[offset..][..4], value) FilterPass::build_float(location, &mut buffer[offset..][..4], value)
} }
// todo: deal with both lut name and index
// for (index, lut) in parent.luts.values().enumerate() {
// // todo: sort out order
// if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::User.semantics(index as u32)) {
// }
//
// }
// todo history // todo history
} }
} }

View file

@ -26,7 +26,7 @@ use librashader_reflect::reflect::cross::CrossReflect;
use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, ShaderReflection, UniformSemantic}; use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, ShaderReflection, UniformSemantic};
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, VariableMeta, VariableSemantics}; use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, VariableMeta, VariableSemantics};
use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap}; use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap};
use util::{Location, VariableLocation, RingBuffer, Size, Texture, TextureMeta, Viewport}; use util::{Location, VariableLocation, RingBuffer, Size, GlImage, Texture, Viewport};
unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint { unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint {
let shader = gl::CreateShader(stage); let shader = gl::CreateShader(stage);
@ -117,9 +117,9 @@ pub struct FilterChain {
semantics: ReflectSemantics, semantics: ReflectSemantics,
preset: ShaderPreset, preset: ShaderPreset,
original_history: Vec<Framebuffer>, original_history: Vec<Framebuffer>,
history: Vec<TextureMeta>, history: Vec<Texture>,
feedback: Vec<TextureMeta>, feedback: Vec<Texture>,
luts: FxHashMap<String, TextureMeta> luts: FxHashMap<String, Texture>
} }
impl FilterChain { impl FilterChain {
@ -279,6 +279,7 @@ impl FilterChain {
// retroarch checks if feedback frames are used but we'll just init it tbh. // retroarch checks if feedback frames are used but we'll just init it tbh.
framebuffer: Framebuffer::new(1), framebuffer: Framebuffer::new(1),
feedback_framebuffer: Framebuffer::new(1), feedback_framebuffer: Framebuffer::new(1),
config: config.clone()
}); });
} }
@ -356,8 +357,8 @@ impl FilterChain {
gl::BindTexture(gl::TEXTURE_2D, 0); gl::BindTexture(gl::TEXTURE_2D, 0);
} }
luts.insert(texture.name.clone(), TextureMeta { luts.insert(texture.name.clone(), Texture {
texture: Texture { image: GlImage {
handle, handle,
format: gl::RGBA8, format: gl::RGBA8,
size: Size { size: Size {
@ -372,6 +373,7 @@ impl FilterChain {
}); });
} }
// todo: split params
Ok(FilterChain { Ok(FilterChain {
passes: filters, passes: filters,
semantics, semantics,
@ -385,32 +387,44 @@ impl FilterChain {
// how much info do we actually need? // how much info do we actually need?
// fn frame(&mut self, count: u64, vp: &Viewport, input: &Texture, clear: bool) { fn frame(&mut self, count: u32, vp: &Viewport, input: GlImage, clear: bool) {
//
// // todo: make copy
//
// let original = Texture {
// handle: input.handle,
// format: self.preset.shaders.first().,
// size: Size {},
// padded_size: Size {}
// };
// // todo: deal with the mess that is frame history
// }
fn do_final_pass(&mut self, count: u64, vp: &Viewport, input: Texture, clear: bool, mvp: &[f32]) { let filter = self.preset.shaders.first().map(|f| f.filter).unwrap_or_default();
let wrap_mode = self.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default();
let original = Texture {
image: input,
filter,
mip_filter: filter,
wrap_mode
};
let mut source = original.clone();
for passes in &mut self.passes {
// passes.build_semantics(&self, None, count, 1, vp, &original, &source);
}
// todo: deal with the mess that is frame history
}
pub fn do_final_pass(&mut self, count: u64, vp: &Viewport, input: GlImage, clear: bool, mvp: &[f32]) {
// todo: make copy // todo: make copy
// todo: get filter info from pass data. // todo: get filter info from pass data.
let original = TextureMeta { let filter = self.preset.shaders.first().map(|f| f.filter).unwrap_or_default();
texture: input, let wrap_mode = self.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default();
filter: FilterMode::Linear, let original = Texture {
mip_filter: FilterMode::Linear, image: input,
wrap_mode: Default::default() filter,
mip_filter: filter,
wrap_mode
}; };
// todo: deal with the mess that is frame history // todo: deal with the mess that is frame history
} }
} }
@ -423,8 +437,8 @@ mod tests {
#[test] #[test]
fn triangle() { fn triangle() {
let (glfw, window, events, shader, vao) = hello_triangle::setup(); let (glfw, window, events, shader, vao) = hello_triangle::setup();
// FilterChain::load("../test/basic.slangp").unwrap(); FilterChain::load("../test/basic.slangp").unwrap();
FilterChain::load("../test/slang-shaders/crt/crt-royale.slangp").unwrap(); // FilterChain::load("../test/slang-shaders/crt/crt-royale.slangp").unwrap();
hello_triangle::do_loop(glfw, window, events, shader, vao); hello_triangle::do_loop(glfw, window, events, shader, vao);
} }

View file

@ -32,8 +32,9 @@ pub fn calc_miplevel(width: u32, height: u32) -> u32 {
return levels; return levels;
} }
pub struct TextureMeta { #[derive(Debug, Copy, Clone)]
pub texture: Texture, pub struct Texture {
pub image: GlImage,
pub filter: FilterMode, pub filter: FilterMode,
pub mip_filter: FilterMode, pub mip_filter: FilterMode,
pub wrap_mode: WrapMode pub wrap_mode: WrapMode
@ -43,8 +44,7 @@ pub struct TextureMeta {
pub struct Viewport { pub struct Viewport {
pub x: i32, pub x: i32,
pub y: i32, pub y: i32,
pub width: i32, pub size: Size,
pub height: i32
} }
#[derive(Default, Debug, Copy, Clone)] #[derive(Default, Debug, Copy, Clone)]
@ -54,7 +54,7 @@ pub struct Size {
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct Texture { pub struct GlImage {
pub handle: GLuint, pub handle: GLuint,
pub format: GLenum, pub format: GLenum,
pub size: Size, pub size: Size,