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 std::convert::Infallible;
use std::ops::Mul;
use std::path::PathBuf;
use std::str::FromStr;
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)]
#[derive(Default, Copy, Clone, Debug)]
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 {
type Err = ParsePresetError;
@ -51,20 +97,6 @@ pub struct Scale2D {
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)]
pub struct TextureConfig {
pub name: String,

View file

@ -7,11 +7,11 @@ use librashader_reflect::reflect::TextureSemanticMap;
use librashader_reflect::reflect::VariableSemanticMap;
use rustc_hash::FxHashMap;
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 crate::FilterChain;
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 reflection: ShaderReflection,
@ -25,6 +25,7 @@ pub struct FilterPass {
pub framebuffer: Framebuffer,
pub feedback_framebuffer: Framebuffer,
pub source: ShaderSource,
pub config: ShaderPassConfig
}
impl FilterPass {
@ -81,10 +82,10 @@ impl FilterPass {
Self::build_uniform(location, buffer, value, gl::Uniform1f)
}
fn set_texture(binding: &TextureImage, texture: &TextureMeta) {
fn set_texture(binding: &TextureImage, texture: &Texture) {
unsafe {
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_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);
}
}
// 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
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) {
let mvp = mvp.unwrap_or(&[
2f32, 0.0, 0.0, 0.0,
@ -118,17 +182,6 @@ impl FilterPass {
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
};
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) {
@ -138,10 +191,9 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_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) {
// todo: do all variables have 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::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)) {
FilterPass::set_texture(binding, original);
@ -182,10 +234,10 @@ impl FilterPass {
MemberOffset::Ubo(offset) => (&mut self.uniform_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)) {
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::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)) {
FilterPass::set_texture(binding, original);
@ -221,8 +273,13 @@ impl FilterPass {
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
}
}

View file

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