diff --git a/librashader-presets/src/parse/token.rs b/librashader-presets/src/parse/token.rs index a4854ac..1f88cfc 100644 --- a/librashader-presets/src/parse/token.rs +++ b/librashader-presets/src/parse/token.rs @@ -4,15 +4,14 @@ use nom::branch::alt; use nom::bytes::complete::{is_not, take_until}; use nom::character::complete::{char, line_ending, multispace1, not_line_ending}; -use nom::combinator::{eof, map_res, opt, value}; +use nom::combinator::{eof, map_res, value}; use nom::error::{ErrorKind, ParseError}; -use nom::sequence::{delimited, preceded}; +use nom::sequence::delimited; use nom::{ bytes::complete::tag, character::complete::multispace0, IResult, InputIter, InputLength, InputTake, }; -use nom::multi::many0; #[derive(Debug)] pub struct Token<'a> { diff --git a/librashader-presets/src/preset.rs b/librashader-presets/src/preset.rs index 9566588..40afe71 100644 --- a/librashader-presets/src/preset.rs +++ b/librashader-presets/src/preset.rs @@ -1,5 +1,4 @@ use crate::error::ParsePresetError; -use std::convert::Infallible; use std::ops::Mul; use std::path::PathBuf; use std::str::FromStr; diff --git a/librashader-runtime-gl/src/filter_chain.rs b/librashader-runtime-gl/src/filter_chain.rs index 27ed5b8..95c7952 100644 --- a/librashader-runtime-gl/src/filter_chain.rs +++ b/librashader-runtime-gl/src/filter_chain.rs @@ -7,9 +7,9 @@ use crate::util::{GlImage, RingBuffer, Size, Texture, Viewport}; use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint}; use librashader::image::Image; use librashader::{FilterMode, ShaderSource}; -use librashader_presets::{ShaderPassConfig, ShaderPreset}; -use librashader_reflect::back::cross::GlVersion; -use librashader_reflect::back::targets::{FromCompilation, GLSL}; +use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; +use librashader_reflect::back::cross::{GlVersion, GlslangGlslContext}; +use librashader_reflect::back::targets::{CompilerBackend, FromCompilation, GLSL}; use librashader_reflect::back::CompileShader; use librashader_reflect::reflect::semantics::{ MemberOffset, SemanticMap, TextureSemantics, UniformMeta, VariableSemantics, @@ -120,9 +120,23 @@ pub struct FilterCommon { pub(crate) quad_vbo: GLuint, } +type ShaderPassMeta<'a> = ( + &'a ShaderPassConfig, + ShaderSource, + CompilerBackend< + impl CompileShader + + ReflectShader + + Sized, + >, +); + impl FilterChain { - pub fn load(path: impl AsRef) -> Result> { - let preset = ShaderPreset::try_parse(path)?; + fn load_preset( + preset: &ShaderPreset, + ) -> ( + Vec, + ReflectSemantics, + ) { let mut uniform_semantics: FxHashMap = Default::default(); let mut texture_semantics: FxHashMap> = Default::default(); @@ -186,177 +200,13 @@ impl FilterChain { non_uniform_semantics: texture_semantics, }; - let mut filters = Vec::new(); - let mut output_framebuffers = Vec::new(); + (passes, semantics) + } - // initialize passes - for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() { - let semantics = semantics.clone(); - - let reflection = reflect.reflect(index, &semantics)?; - let glsl = reflect.compile(GlVersion::V4_60)?; - - let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?; - - // todo: split this out. - let (program, ubo_location) = unsafe { - let vertex = util::gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str()); - let fragment = util::gl_compile_shader(gl::FRAGMENT_SHADER, glsl.fragment.as_str()); - - let program = gl::CreateProgram(); - gl::AttachShader(program, vertex); - gl::AttachShader(program, fragment); - - for res in &vertex_resources.stage_inputs { - let loc = glsl - .context - .compiler - .vertex - .get_decoration(res.id, Decoration::Location)?; - let loc_name = format!("LIBRA_ATTRIBUTE_{loc}\0"); - eprintln!("{loc_name}"); - 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") - } - - gl::UseProgram(program); - - for binding in &glsl.context.sampler_bindings { - let loc_name = format!("LIBRA_TEXTURE_{}\0", *binding); - let location = - gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast()); - if location >= 0 { - // eprintln!("setting sampler {location} to sample from {binding}"); - gl::Uniform1i(location, *binding as GLint); - } - } - - gl::UseProgram(0); - ( - program, - UniformLocation { - vertex: gl::GetUniformBlockIndex( - program, - b"LIBRA_UBO_VERTEX\0".as_ptr().cast(), - ), - fragment: gl::GetUniformBlockIndex( - program, - b"LIBRA_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_mut().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) - ] - .into_boxed_slice(); - let push_buffer = vec![ - 0; - reflection - .push_constant - .as_ref() - .map(|push| push.size as usize) - .unwrap_or(0) - ] - .into_boxed_slice(); - - // todo: reflect indexed parameters - let mut locations = FxHashMap::default(); - for param in reflection.meta.parameter_meta.values() { - locations.insert( - UniformBinding::Parameter(param.id.clone()), - ( - FilterChain::reflect_uniform_location(program, param), - param.offset, - ), - ); - } - - for (semantics, param) in &reflection.meta.variable_meta { - locations.insert( - UniformBinding::SemanticVariable(*semantics), - ( - FilterChain::reflect_uniform_location(program, param), - param.offset, - ), - ); - } - - for (semantics, param) in &reflection.meta.texture_size_meta { - locations.insert( - UniformBinding::TextureSize(*semantics), - ( - FilterChain::reflect_uniform_location(program, param), - param.offset, - ), - ); - } - - // need output framebuffers. - output_framebuffers.push(Framebuffer::new(1)); - - // 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, - variable_bindings: locations, - source, - config: config.clone(), - }); - } - - // load luts + fn load_luts(textures: &[TextureConfig]) -> Result, Box> { let mut luts = FxHashMap::default(); - for (index, texture) in preset.textures.iter().enumerate() { + for (index, texture) in textures.iter().enumerate() { let image = Image::load(&texture.path)?; let levels = if texture.mipmap { util::calc_miplevel(image.width, image.height) @@ -452,7 +302,191 @@ impl FilterChain { }, ); } + Ok(luts) + } + pub fn init_passes(passes: Vec, semantics: &ReflectSemantics) -> Result, Box> { + let mut filters = Vec::new(); + + // initialize passes + for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() { + let reflection = reflect.reflect(index, semantics)?; + let glsl = reflect.compile(GlVersion::V4_60)?; + + let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?; + + // todo: split this out. + let (program, ubo_location) = unsafe { + let vertex = util::gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str()); + let fragment = util::gl_compile_shader(gl::FRAGMENT_SHADER, glsl.fragment.as_str()); + + let program = gl::CreateProgram(); + gl::AttachShader(program, vertex); + gl::AttachShader(program, fragment); + + for res in &vertex_resources.stage_inputs { + let loc = glsl + .context + .compiler + .vertex + .get_decoration(res.id, Decoration::Location)?; + let loc_name = format!("LIBRA_ATTRIBUTE_{loc}\0"); + eprintln!("{loc_name}"); + 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") + } + + gl::UseProgram(program); + + for binding in &glsl.context.sampler_bindings { + let loc_name = format!("LIBRA_TEXTURE_{}\0", *binding); + let location = + gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast()); + if location >= 0 { + // eprintln!("setting sampler {location} to sample from {binding}"); + gl::Uniform1i(location, *binding as GLint); + } + } + + gl::UseProgram(0); + ( + program, + UniformLocation { + vertex: gl::GetUniformBlockIndex( + program, + b"LIBRA_UBO_VERTEX\0".as_ptr().cast(), + ), + fragment: gl::GetUniformBlockIndex( + program, + b"LIBRA_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_mut().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) + ] + .into_boxed_slice(); + let push_buffer = vec![ + 0; + reflection + .push_constant + .as_ref() + .map(|push| push.size as usize) + .unwrap_or(0) + ] + .into_boxed_slice(); + + // todo: reflect indexed parameters + let mut locations = FxHashMap::default(); + for param in reflection.meta.parameter_meta.values() { + locations.insert( + UniformBinding::Parameter(param.id.clone()), + ( + FilterChain::reflect_uniform_location(program, param), + param.offset, + ), + ); + } + + for (semantics, param) in &reflection.meta.variable_meta { + locations.insert( + UniformBinding::SemanticVariable(*semantics), + ( + FilterChain::reflect_uniform_location(program, param), + param.offset, + ), + ); + } + + for (semantics, param) in &reflection.meta.texture_size_meta { + locations.insert( + UniformBinding::TextureSize(*semantics), + ( + FilterChain::reflect_uniform_location(program, param), + param.offset, + ), + ); + } + + // 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, + variable_bindings: locations, + source, + config: config.clone(), + }); + } + + Ok(filters) + } + + + pub fn load(path: impl AsRef) -> Result> { + // load passes from preset + let preset = ShaderPreset::try_parse(path)?; + let (passes, semantics) = FilterChain::load_preset(&preset); + + // initialize passes + let filters = FilterChain::init_passes(passes, &semantics)?; + + // initialize output framebuffers + let mut output_framebuffers = Vec::new(); + output_framebuffers.resize_with(filters.len(), || Framebuffer::new(1)); + + // load luts + let luts = FilterChain::load_luts(&preset.textures)?; + + // create VBO objects let mut quad_vbo = 0; unsafe { gl::GenBuffers(1, &mut quad_vbo); diff --git a/librashader-runtime-gl/src/hello_triangle.rs b/librashader-runtime-gl/src/hello_triangle.rs index 89731d5..ff4b3ac 100644 --- a/librashader-runtime-gl/src/hello_triangle.rs +++ b/librashader-runtime-gl/src/hello_triangle.rs @@ -535,7 +535,6 @@ void main() gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4); } - framecount += 1; window.swap_buffers(); } diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs index 8d8cc4f..f5be735 100644 --- a/librashader-runtime-gl/src/lib.rs +++ b/librashader-runtime-gl/src/lib.rs @@ -1,4 +1,5 @@ #![feature(strict_provenance)] +#![feature(type_alias_impl_trait)] mod binding; mod filter_chain; diff --git a/librashader-runtime-gl/src/render_target.rs b/librashader-runtime-gl/src/render_target.rs index 0131046..6176650 100644 --- a/librashader-runtime-gl/src/render_target.rs +++ b/librashader-runtime-gl/src/render_target.rs @@ -1,6 +1,7 @@ use crate::framebuffer::Framebuffer; use crate::util::Viewport; +#[rustfmt::skip] static DEFAULT_MVP: &[f32] = &[ 2f32, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, diff --git a/librashader/src/gl.rs b/librashader/src/gl.rs index 8ab6a8f..a7e2da6 100644 --- a/librashader/src/gl.rs +++ b/librashader/src/gl.rs @@ -1,4 +1,3 @@ -use gl::types::GLenum; use crate::{FilterMode, ShaderFormat, WrapMode}; impl From for gl::types::GLenum { diff --git a/librashader/src/image.rs b/librashader/src/image.rs index 2b3dbfe..1c4b3c9 100644 --- a/librashader/src/image.rs +++ b/librashader/src/image.rs @@ -1,5 +1,3 @@ -use std::ffi::OsStr; -use std::io::ErrorKind; use std::path::Path; pub struct Image {