diff --git a/Cargo.lock b/Cargo.lock index 0b45967..ac728aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,6 +458,9 @@ checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" [[package]] name = "librashader" version = "0.1.0" +dependencies = [ + "gl", +] [[package]] name = "librashader-preprocess" @@ -472,6 +475,7 @@ dependencies = [ name = "librashader-presets" version = "0.1.0" dependencies = [ + "librashader", "nom", "nom_locate", "thiserror", diff --git a/librashader-presets/Cargo.toml b/librashader-presets/Cargo.toml index 9103155..e09de6b 100644 --- a/librashader-presets/Cargo.toml +++ b/librashader-presets/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" thiserror = "1.0.37" nom = "7.1.1" nom_locate = "4.0.0" +librashader = { path = "../librashader" } diff --git a/librashader-presets/src/parse/value.rs b/librashader-presets/src/parse/value.rs index 08d2095..cede313 100644 --- a/librashader-presets/src/parse/value.rs +++ b/librashader-presets/src/parse/value.rs @@ -1,6 +1,6 @@ use crate::error::{ParseErrorKind, ParsePresetError}; use crate::parse::{remove_if, Span, Token}; -use crate::{FilterMode, ScaleFactor, ScaleType, WrapMode}; +use crate::{ScaleFactor, ScaleType}; use nom::bytes::complete::tag; use nom::character::complete::digit1; use nom::combinator::{eof, map_res}; @@ -12,6 +12,7 @@ use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; use std::str::FromStr; +use librashader::{FilterMode, WrapMode}; #[derive(Debug)] pub enum Value { diff --git a/librashader-presets/src/preset.rs b/librashader-presets/src/preset.rs index ecdfeb6..b3cb1df 100644 --- a/librashader-presets/src/preset.rs +++ b/librashader-presets/src/preset.rs @@ -2,25 +2,7 @@ use crate::error::ParsePresetError; use std::convert::Infallible; use std::path::PathBuf; use std::str::FromStr; - -#[repr(i32)] -#[derive(Copy, Clone, Default, Debug)] -pub enum FilterMode { - #[default] - Linear = 0, - Nearest, - Unspecified, -} - -#[repr(i32)] -#[derive(Copy, Clone, Default, Debug)] -pub enum WrapMode { - #[default] - ClampToBorder = 0, - ClampToEdge, - Repeat, - MirroredRepeat, -} +use librashader::{FilterMode, WrapMode}; #[repr(i32)] #[derive(Default, Copy, Clone, Debug)] @@ -43,20 +25,6 @@ impl Default for ScaleFactor { } } -impl FromStr for WrapMode { - type Err = Infallible; - - fn from_str(s: &str) -> Result { - Ok(match s { - "clamp_to_border" => WrapMode::ClampToBorder, - "clamp_to_edge" => WrapMode::ClampToEdge, - "repeat" => WrapMode::Repeat, - "mirrored_repeat" => WrapMode::MirroredRepeat, - _ => WrapMode::ClampToBorder, - }) - } -} - impl FromStr for ScaleType { type Err = ParsePresetError; diff --git a/librashader-runtime-dx11/src/lib.rs b/librashader-runtime-dx11/src/lib.rs index 44c4260..af28c38 100644 --- a/librashader-runtime-dx11/src/lib.rs +++ b/librashader-runtime-dx11/src/lib.rs @@ -71,7 +71,7 @@ pub fn load(path: impl AsRef) -> Result<(), Box>{ for (index, parameter) in preset.parameters.iter().enumerate() { uniform_semantics.insert(parameter.name.clone(), UniformSemantic::Variable(SemanticMap { semantics: VariableSemantics::FloatParameter, - index: index as u32 + index: () })); } diff --git a/librashader-runtime-gl/Cargo.toml b/librashader-runtime-gl/Cargo.toml index 67a70ef..617f572 100644 --- a/librashader-runtime-gl/Cargo.toml +++ b/librashader-runtime-gl/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -"librashader" = { path = "../librashader" } +"librashader" = { path = "../librashader", features = ["opengl"] } "librashader-presets" = { path = "../librashader-presets" } "librashader-preprocess" = { path = "../librashader-preprocess" } "librashader-reflect" = { path = "../librashader-reflect" } diff --git a/librashader-runtime-gl/src/filter.rs b/librashader-runtime-gl/src/filter.rs new file mode 100644 index 0000000..e69de29 diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs index 5999015..87e8507 100644 --- a/librashader-runtime-gl/src/lib.rs +++ b/librashader-runtime-gl/src/lib.rs @@ -1,14 +1,17 @@ mod hello_triangle; +mod filter; use std::collections::HashMap; use std::error::Error; +use std::iter::Filter; use std::path::Path; -use gl::types::{GLenum, GLint, GLsizeiptr, GLuint}; +use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint}; +use glfw::Key::P; use rustc_hash::FxHashMap; use spirv_cross::spirv::Decoration; -use librashader::ShaderSource; -use librashader_presets::ShaderPassConfig; +use librashader::{ShaderFormat, ShaderSource}; +use librashader_presets::{ShaderPassConfig, ShaderPreset}; use librashader_reflect::back::{CompileShader, ShaderCompilerOutput}; use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion}; use librashader_reflect::back::targets::{FromCompilation, GLSL}; @@ -18,7 +21,21 @@ use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, ShaderReflec use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, VariableMeta, VariableSemantics}; use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap}; -pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap, texture_semantics: &mut FxHashMap>, +unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint { + let shader = gl::CreateShader(stage); + gl::ShaderSource(shader, 1, &source.as_bytes().as_ptr().cast(), std::ptr::null()); + gl::CompileShader(shader); + + let mut compile_status = 0; + gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut compile_status); + + if compile_status == 0 { + panic!("failed to compile") + } + shader +} + +fn load_pass_semantics(uniform_semantics: &mut FxHashMap, texture_semantics: &mut FxHashMap>, config: &ShaderPassConfig) { let Some(alias) = &config.alias else { return; @@ -102,14 +119,149 @@ pub struct FilterPass { ubo_ring: Option>, uniform_buffer: Vec, push_buffer: Vec, - locations: FxHashMap + locations: FxHashMap, + framebuffer: Framebuffer, + feedback_framebuffer: Framebuffer, } +pub struct Framebuffer { + image: GLuint, + size: Size, + format: GLenum, + max_levels: u32, + levels: u32, + framebuffer: GLuint, + init: bool +} + +impl Drop for Framebuffer { + fn drop(&mut self) { + if self.framebuffer != 0 { + unsafe { + gl::DeleteFramebuffers(1, &self.framebuffer); + } + } + + if self.image != 0 { + unsafe { + gl::DeleteTextures(1, &self.image); + } + } + } +} +impl Framebuffer { + pub fn new(max_levels: u32) -> Framebuffer { + let mut framebuffer = 0; + unsafe { + gl::GenFramebuffers(1, &mut framebuffer); + gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer); + gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer); + } + + Framebuffer { + image: 0, + size: Size { width: 1, height: 1 }, + format: 0, + max_levels, + levels: 0, + framebuffer, + init: false + } + } + + fn init(&mut self, mut size: Size, mut format: ShaderFormat) { + if format == ShaderFormat::Unknown { + format = ShaderFormat::R8G8B8A8Unorm; + } + + self.format = GLenum::from(format); + self.size = size; + + unsafe { + gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer); + + // reset the framebuffer image + if self.image != 0 { + gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, 0, 0); + gl::DeleteTextures(1, &self.image); + } + + gl::GenTextures(1, &mut self.image); + gl::BindTexture(1, self.image); + + if size.width == 0 { + size.width = 1; + } + if size.height == 0 { + size.height = 1; + } + + self.levels = calc_miplevel(size.width, size.height); + if self.levels > self.max_levels { + self.levels = self.max_levels; + } + if self.levels == 0 { + self.levels = 1; + } + + gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, self.format, size.width as GLsizei, size.height as GLsizei); + gl::FramebufferTexture2D(gl::FRAMEBUFFER, + gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, self.image, 0); + + let status = gl::CheckFramebufferStatus(gl::FRAMEBUFFER); + if status != gl::FRAMEBUFFER_COMPLETE { + match status { + gl::FRAMEBUFFER_UNSUPPORTED => { + eprintln!("unsupported fbo"); + + gl::FramebufferTexture2D(gl::FRAMEBUFFER, + gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, 0, 0); + gl::DeleteTextures(1, &self.image); + gl::GenTextures(1, &mut self.image); + gl::BindTexture(1, self.image); + + self.levels = calc_miplevel(size.width, size.height); + if self.levels > self.max_levels { + self.levels = self.max_levels; + } + if self.levels == 0 { + self.levels = 1; + } + + gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, gl::RGBA8, size.width as GLsizei, size.height as GLsizei); + gl::FramebufferTexture2D(gl::FRAMEBUFFER, + gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, self.image, 0); + self.init = gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE; + } + _ => panic!("failed to complete: {status}") + } + } else { + self.init = true; + } + + gl::BindFramebuffer(gl::FRAMEBUFFER, 0); + gl::BindTexture(gl::TEXTURE_2D, 0); + } + } +} + +pub fn calc_miplevel(width: u32, height: u32) -> u32 { + let mut size = std::cmp::max(width, height); + let mut levels = 0; + while size != 0 { + levels += 1; + size >>= 1; + } + + return levels; +} pub struct FilterChain { - reflections: Vec, - compiled: Vec>, - programs: Vec, - ubo_location: Location, + passes: Vec, + semantics: ReflectSemantics, + preset: ShaderPreset, + original_history: Vec, + history: Vec, + feedback: Vec } pub fn reflect_parameter(pipeline: GLuint, meta: &VariableMeta) -> ParameterLocation { @@ -144,201 +296,228 @@ pub fn reflect_parameter(pipeline: GLuint, meta: &VariableMeta) -> ParameterLoca } } } -// todo: init gl -pub fn load(path: impl AsRef) -> Result<(), Box>{ - let preset = librashader_presets::ShaderPreset::try_parse(path)?; - let mut uniform_semantics: FxHashMap = Default::default(); - let mut texture_semantics: FxHashMap> = Default::default(); +impl FilterChain { + pub fn load(path: impl AsRef) -> Result> { + let preset = librashader_presets::ShaderPreset::try_parse(path)?; + let mut uniform_semantics: FxHashMap = Default::default(); + let mut texture_semantics: FxHashMap> = Default::default(); - let mut passes: Vec<(&ShaderPassConfig, ShaderSource, _)> = preset.shaders.iter() - .map(|shader| { - eprintln!("[gl] loading {}", &shader.name.display()); - let source: ShaderSource = librashader_preprocess::load_shader_source(&shader.name) - .unwrap(); + let mut passes: Vec<(&ShaderPassConfig, ShaderSource, _)> = preset.shaders.iter() + .map(|shader| { + eprintln!("[gl] loading {}", &shader.name.display()); + let source: ShaderSource = librashader_preprocess::load_shader_source(&shader.name) + .unwrap(); - let spirv = librashader_reflect::front::shaderc::compile_spirv(&source) - .unwrap(); - let mut reflect = GLSL::from_compilation(spirv).unwrap(); + let spirv = librashader_reflect::front::shaderc::compile_spirv(&source) + .unwrap(); + let mut reflect = GLSL::from_compilation(spirv).unwrap(); - for parameter in source.parameters.iter() { - uniform_semantics.insert(parameter.id.clone(), UniformSemantic::Variable(SemanticMap { - semantics: VariableSemantics::FloatParameter, - index: () - })); - } + for parameter in source.parameters.iter() { + uniform_semantics.insert(parameter.id.clone(), UniformSemantic::Variable(SemanticMap { + semantics: VariableSemantics::FloatParameter, + index: () + })); + } - (shader, source, reflect) - }).collect(); + (shader, source, reflect) + }).collect(); - // todo: this can probably be extracted out. + // todo: this can probably be extracted out. - for details in &passes { - load_pass_semantics(&mut uniform_semantics, &mut texture_semantics, details.0) - } + for details in &passes { + load_pass_semantics(&mut uniform_semantics, &mut texture_semantics, details.0) + } - // add lut params - for (index, texture) in preset.textures.iter().enumerate() { - texture_semantics.insert(texture.name.clone(), SemanticMap { - semantics: TextureSemantics::User, - index: index as u32 - }); + // add lut params + for (index, texture) in preset.textures.iter().enumerate() { + texture_semantics.insert(texture.name.clone(), SemanticMap { + semantics: TextureSemantics::User, + index: index as u32 + }); - uniform_semantics.insert(format!("{}Size", texture.name), UniformSemantic::Texture(SemanticMap { - semantics: TextureSemantics::User, - index: index as u32 - })); - } + uniform_semantics.insert(format!("{}Size", texture.name), UniformSemantic::Texture(SemanticMap { + semantics: TextureSemantics::User, + index: index as u32 + })); + } - let semantics = ReflectSemantics { - uniform_semantics, - non_uniform_semantics: texture_semantics - }; + let semantics = ReflectSemantics { + uniform_semantics, + non_uniform_semantics: texture_semantics + }; - let mut filters = Vec::new(); + let mut filters = Vec::new(); - for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() { - let mut semantics = semantics.clone(); + // initialize passes + for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() { + let mut semantics = semantics.clone(); - // insert parameters parsed from source - // for (index, parameter) in source.parameters.iter().enumerate() { - // semantics.uniform_semantics.insert(parameter.id.clone(), UniformSemantic::Variable(SemanticMap { - // semantics: VariableSemantics::FloatParameter, - // index: 0 - // })); - // } + let reflection = reflect.reflect(index as u32, &semantics)?; + let glsl = reflect.compile(GlVersion::V4_60)?; - let reflection = reflect.reflect(index as u32, &semantics)?; + let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?; - let glsl = reflect.compile(GlVersion::V4_60)?; + // todo: split this out. + let (program, ubo_location) = unsafe { + let vertex = gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str()); + let fragment = gl_compile_shader(gl::FRAGMENT_SHADER, glsl.fragment.as_str()); - let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?; + let program = gl::CreateProgram(); + gl::AttachShader(program, vertex); + gl::AttachShader(program, fragment); - // todo: split this out. - let (program, ubo_location) = unsafe { - let vertex = gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str()); - let fragment = gl_compile_shader(gl::FRAGMENT_SHADER, glsl.fragment.as_str()); + for res in &vertex_resources.stage_inputs { + let loc = glsl.context.compiler.vertex.get_decoration(res.id, Decoration::Location)?; + let loc_name = format!("RARCH_ATTRIBUTE_{loc}"); + gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast()) + } + gl::LinkProgram(program); + gl::DeleteShader(vertex); + gl::DeleteShader(fragment); - let program = gl::CreateProgram(); - gl::AttachShader(program, vertex); - gl::AttachShader(program, fragment); + let mut status = 0; + gl::GetProgramiv(program, gl::LINK_STATUS, &mut status); + if status != 1 { + panic!("failed to link program") + } - for res in &vertex_resources.stage_inputs { - let loc = glsl.context.compiler.vertex.get_decoration(res.id, Decoration::Location)?; - let loc_name = format!("RARCH_ATTRIBUTE_{loc}"); - gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast()) - } - gl::LinkProgram(program); - gl::DeleteShader(vertex); - gl::DeleteShader(fragment); - - let mut status = 0; - gl::GetProgramiv(program, gl::LINK_STATUS, &mut status); - if status != 1 { - panic!("failed to link program") - } - - for binding in &glsl.context.texture_fixups { - let loc_name = format!("RARCH_TEXTURE_{}", *binding); - unsafe { - let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast()); - if location >= 0 { - gl::Uniform1i(location, *binding as GLint); + for binding in &glsl.context.texture_fixups { + let loc_name = format!("RARCH_TEXTURE_{}", *binding); + unsafe { + let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast()); + if location >= 0 { + gl::Uniform1i(location, *binding as GLint); + } } } - } - unsafe { - gl::UseProgram(0); - (program, Location { - vertex: gl::GetUniformBlockIndex(program, b"RARCH_UBO_VERTEX\0".as_ptr().cast()), - fragment: gl::GetUniformBlockIndex(program, b"RARCH_UBO_FRAGMENT\0".as_ptr().cast()), - }) - } - }; - - let ubo_ring = if let Some(ubo) = &reflection.ubo { - let size = ubo.size; - let mut ring: RingBuffer = RingBuffer::new(); - unsafe { - gl::GenBuffers(16, ring.items.as_mut_ptr()); - for buffer in &ring.items { - gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer); - gl::BufferData(gl::UNIFORM_BUFFER, size as GLsizeiptr, std::ptr::null(), gl::STREAM_DRAW); + unsafe { + gl::UseProgram(0); + (program, Location { + vertex: gl::GetUniformBlockIndex(program, b"RARCH_UBO_VERTEX\0".as_ptr().cast()), + fragment: gl::GetUniformBlockIndex(program, b"RARCH_UBO_FRAGMENT\0".as_ptr().cast()), + }) } - gl::BindBuffer(gl::UNIFORM_BUFFER, 0); + }; + + let ubo_ring = if let Some(ubo) = &reflection.ubo { + let size = ubo.size; + let mut ring: RingBuffer = RingBuffer::new(); + unsafe { + gl::GenBuffers(16, ring.items.as_mut_ptr()); + for buffer in &ring.items { + gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer); + gl::BufferData(gl::UNIFORM_BUFFER, size as GLsizeiptr, std::ptr::null(), gl::STREAM_DRAW); + } + gl::BindBuffer(gl::UNIFORM_BUFFER, 0); + } + Some(ring) + } else { + None + }; + + let uniform_buffer = vec![0; reflection.ubo.as_ref().map(|ubo| ubo.size as usize).unwrap_or(0)]; + let push_buffer = vec![0; reflection.push_constant.as_ref().map(|push| push.size as usize).unwrap_or(0)]; + + // todo: reflect indexed parameters + let mut locations = FxHashMap::default(); + for param in reflection.meta.parameter_meta.values() { + locations.insert(param.id.clone(), reflect_parameter(program, param)); } - Some(ring) - } else { - None - }; - let uniform_buffer = vec![0; reflection.ubo.as_ref().map(|ubo| ubo.size as usize).unwrap_or(0)]; - let push_buffer = vec![0; reflection.push_constant.as_ref().map(|push| push.size as usize).unwrap_or(0)]; + for param in reflection.meta.variable_meta.values() { + locations.insert(param.id.clone(), reflect_parameter(program, param)); + } - // todo: reflect indexed parameters - let mut locations = FxHashMap::default(); - for param in reflection.meta.parameter_meta.values() { - locations.insert(param.id.clone(), reflect_parameter(program, param)); + + // eprintln!("{:#?}", semantics); + eprintln!("{:#?}", reflection.meta); + eprintln!("{:#?}", locations); + eprintln!("{:#?}", reflection.push_constant); + // eprintln!("====fragment===="); + // eprintln!("{:#}", glsl.fragment); + // eprintln!("====vertex===="); + // eprintln!("{:#}", glsl.vertex); + + filters.push(FilterPass { + reflection, + compiled: glsl, + program, + ubo_location, + ubo_ring, + uniform_buffer, + push_buffer, + locations, + + // no idea if this works. + // retroarch checks if feedback frames are used but we'll just init it tbh. + framebuffer: Framebuffer::new(1), + feedback_framebuffer: Framebuffer::new(1) + }); } - for param in reflection.meta.variable_meta.values() { - locations.insert(param.id.clone(), reflect_parameter(program, param)); - } - - // eprintln!("{:#?}", semantics); - eprintln!("{:#?}", reflection.meta); - eprintln!("{:#?}", locations); - eprintln!("{:#?}", reflection.push_constant); - // eprintln!("====fragment===="); - // eprintln!("{:#}", glsl.fragment); - // eprintln!("====vertex===="); - // eprintln!("{:#}", glsl.vertex); - - filters.push(FilterPass { - reflection, - compiled: glsl, - program, - ubo_location, - ubo_ring, - uniform_buffer, - push_buffer, - locations - }); - } - - // let mut glprogram: Vec = Vec::new(); - // for compilation in &compiled { - // // compilation.context.compiler.vertex - // } + eprintln!("{:?}", filters.iter().map(|f| f.program).collect::>()); + // let mut glprogram: Vec = Vec::new(); + // for compilation in &compiled { + // // compilation.context.compiler.vertex + // } // eprintln!("{:#?}", reflections); - // eprintln!("{:#?}", compiled./); - // eprintln!("{:?}", preset); - // eprintln!("{:?}", reflect.reflect(&ReflectOptions { - // pass_number: i as u32, - // uniform_semantics, - // non_uniform_semantics: Default::default(), - // })); + // eprintln!("{:#?}", compiled./); + // eprintln!("{:?}", preset); + // eprintln!("{:?}", reflect.reflect(&ReflectOptions { + // pass_number: i as u32, + // uniform_semantics, + // non_uniform_semantics: Default::default(), + // })); - Ok(()) -} + // todo: apply shader pass + // gl3.cpp: 1942 -unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint { - let shader = gl::CreateShader(stage); - gl::ShaderSource(shader, 1, &source.as_bytes().as_ptr().cast(), std::ptr::null()); - gl::CompileShader(shader); - let mut compile_status = 0; - gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut compile_status); - - if compile_status == 0 { - panic!("failed to compile") + Ok(FilterChain { + passes: filters, + semantics, + preset, + original_history: vec![], + history: vec![], + feedback: vec![] + }) + } + + + // how much info do we actually need? + fn frame(&mut self, count: u64, vp: &Viewport, input: &Texture, clear: bool) { + + // todo: deal with the mess that is frame history } - shader } +#[derive(Debug, Copy, Clone)] +struct Viewport { + x: i32, + y: i32, + width: i32, + height: i32 +} + +#[derive(Debug, Copy, Clone)] +struct Size { + width: u32, + height: u32, +} + +#[derive(Debug, Copy, Clone)] +struct Texture { + handle: GLuint, + format: GLenum, + size: Size, + padded_size: Size +} + + #[cfg(test)] mod tests { use super::*; @@ -346,9 +525,9 @@ mod tests { #[test] fn triangle() { let (glfw, window, events, shader, vao) = hello_triangle::setup(); - // load("../test/basic.slangp") - 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); } diff --git a/librashader/Cargo.toml b/librashader/Cargo.toml index 7997b35..04d679f 100644 --- a/librashader/Cargo.toml +++ b/librashader/Cargo.toml @@ -5,4 +5,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = [ "opengl" ] +opengl = ["gl"] + [dependencies] +gl = { version = "0.14.0", optional = true } \ No newline at end of file diff --git a/librashader/src/gl.rs b/librashader/src/gl.rs new file mode 100644 index 0000000..236ef02 --- /dev/null +++ b/librashader/src/gl.rs @@ -0,0 +1,50 @@ +use crate::{FilterMode, ShaderFormat, WrapMode}; + +impl From for gl::types::GLenum { + fn from(format: ShaderFormat) -> Self { + match format { + ShaderFormat::Unknown => 0 as gl::types::GLenum, + ShaderFormat::R8Unorm => gl::R8, + ShaderFormat::R8Uint => gl::R8UI, + ShaderFormat::R8Sint => gl::R8I, + ShaderFormat::R8G8Unorm => gl::RG8, + ShaderFormat::R8G8Uint => gl::RG8UI, + ShaderFormat::R8G8Sint => gl::RG8I, + ShaderFormat::R8G8B8A8Unorm => gl::RGBA8, + ShaderFormat::R8G8B8A8Uint => gl::RGBA8UI, + ShaderFormat::R8G8B8A8Sint => gl::RGBA8I, + ShaderFormat::R8G8B8A8Srgb => gl::SRGB8_ALPHA8, + ShaderFormat::A2B10G10R10UnormPack32 => gl::RGB10_A2, + ShaderFormat::A2B10G10R10UintPack32 => gl::RGB10_A2UI, + ShaderFormat::R16Uint => gl::R16UI, + ShaderFormat::R16Sint => gl::R16I, + ShaderFormat::R16Sfloat => gl::R16F, + ShaderFormat::R16G16Uint => gl::RG16UI, + ShaderFormat::R16G16Sint => gl::RG16I, + ShaderFormat::R16G16Sfloat => gl::RG16F, + ShaderFormat::R16G16B16A16Uint => gl::RGBA16UI, + ShaderFormat::R16G16B16A16Sint => gl::RGBA16I, + ShaderFormat::R16G16B16A16Sfloat => gl::RGBA16F, + ShaderFormat::R32Uint => gl::R32UI, + ShaderFormat::R32Sint => gl::R32I, + ShaderFormat::R32Sfloat => gl::R32F, + ShaderFormat::R32G32Uint => gl::RG32UI, + ShaderFormat::R32G32Sint => gl::RG32I, + ShaderFormat::R32G32Sfloat => gl::RG32F, + ShaderFormat::R32G32B32A32Uint => gl::RGBA32UI, + ShaderFormat::R32G32B32A32Sint => gl::RGBA32I, + ShaderFormat::R32G32B32A32Sfloat => gl::RGBA32F + } + } +} + +impl From for gl::types::GLenum { + fn from(value: WrapMode) -> Self { + match value { + WrapMode::ClampToBorder => gl::CLAMP_TO_BORDER, + WrapMode::ClampToEdge => gl::CLAMP_TO_EDGE, + WrapMode::Repeat => gl::REPEAT, + WrapMode::MirroredRepeat => gl::MIRRORED_REPEAT + } + } +} diff --git a/librashader/src/lib.rs b/librashader/src/lib.rs index 8126d0b..42d8358 100644 --- a/librashader/src/lib.rs +++ b/librashader/src/lib.rs @@ -1,3 +1,6 @@ +#[cfg(feature = "opengl")] +pub mod gl; + use std::convert::Infallible; use std::str::FromStr; @@ -65,6 +68,40 @@ pub enum ShaderFormat { R32G32B32A32Sfloat, } +#[repr(i32)] +#[derive(Copy, Clone, Default, Debug)] +pub enum FilterMode { + #[default] + Linear = 0, + Nearest, + Unspecified, +} + +impl FromStr for WrapMode { + type Err = Infallible; + + fn from_str(s: &str) -> Result { + Ok(match s { + "clamp_to_border" => WrapMode::ClampToBorder, + "clamp_to_edge" => WrapMode::ClampToEdge, + "repeat" => WrapMode::Repeat, + "mirrored_repeat" => WrapMode::MirroredRepeat, + _ => WrapMode::ClampToBorder, + }) + } +} + + +#[repr(i32)] +#[derive(Copy, Clone, Default, Debug)] +pub enum WrapMode { + #[default] + ClampToBorder = 0, + ClampToEdge, + Repeat, + MirroredRepeat, +} + impl FromStr for ShaderFormat { type Err = Infallible;