gl: correct scaling options
This commit is contained in:
parent
c06751eca9
commit
afc750c37c
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue