From d49fa5307a261ed996b44bf52a43e19acea2d9f0 Mon Sep 17 00:00:00 2001 From: chyyran Date: Sat, 19 Nov 2022 18:48:54 -0500 Subject: [PATCH] gl: clean up uniform binding storage --- librashader-reflect/src/back/targets.rs | 2 +- librashader-reflect/src/error.rs | 2 +- librashader-reflect/src/reflect/cross.rs | 30 +-- librashader-reflect/src/reflect/mod.rs | 6 +- librashader-reflect/src/reflect/semantics.rs | 49 +++- librashader-runtime-gl/src/binding.rs | 66 ++++++ librashader-runtime-gl/src/filter_pass.rs | 235 ++++++++++--------- librashader-runtime-gl/src/lib.rs | 63 +++-- librashader-runtime-gl/src/util.rs | 20 -- 9 files changed, 296 insertions(+), 177 deletions(-) create mode 100644 librashader-runtime-gl/src/binding.rs diff --git a/librashader-reflect/src/back/targets.rs b/librashader-reflect/src/back/targets.rs index 3c0c726..a79f321 100644 --- a/librashader-reflect/src/back/targets.rs +++ b/librashader-reflect/src/back/targets.rs @@ -51,7 +51,7 @@ where { fn reflect( &mut self, - pass_number: u32, + pass_number: usize, semantics: &ReflectSemantics, ) -> Result { self.backend.reflect(pass_number, semantics) diff --git a/librashader-reflect/src/error.rs b/librashader-reflect/src/error.rs index 54d8059..4224a26 100644 --- a/librashader-reflect/src/error.rs +++ b/librashader-reflect/src/error.rs @@ -46,7 +46,7 @@ pub enum ShaderReflectError { #[error("vertx and fragment shader must have same binding")] MismatchedUniformBuffer { vertex: u32, fragment: u32 }, #[error("filter chain is non causal")] - NonCausalFilterChain { pass: u32, target: u32 }, + NonCausalFilterChain { pass: usize, target: usize }, #[error("mismatched offset")] MismatchedOffset { semantic: String, diff --git a/librashader-reflect/src/reflect/cross.rs b/librashader-reflect/src/reflect/cross.rs index eb6851a..28f3a49 100644 --- a/librashader-reflect/src/reflect/cross.rs +++ b/librashader-reflect/src/reflect/cross.rs @@ -284,7 +284,7 @@ where fn reflect_buffer_range_metas( ast: &Ast, resource: &Resource, - pass_number: u32, + pass_number: usize, semantics: &ReflectSemantics, meta: &mut ReflectMeta, offset_type: impl Fn(usize) -> MemberOffset, @@ -478,7 +478,7 @@ where fn reflect_texture_metas( &self, texture: TextureData, - pass_number: u32, + pass_number: usize, semantics: &ReflectSemantics, meta: &mut ReflectMeta, ) -> Result<(), ShaderReflectError> { @@ -594,7 +594,7 @@ where { fn reflect( &mut self, - pass_number: u32, + pass_number: usize, semantics: &ReflectSemantics, ) -> Result { let vertex_res = self.vertex.get_shader_resources()?; @@ -707,19 +707,19 @@ impl CompileShader for CrossReflect { for res in &vertex_resources.stage_inputs { let location = self.vertex.get_decoration(res.id, Decoration::Location)?; self.vertex - .set_name(res.id, &format!("RARCH_ATTRIBUTE_{location}"))?; + .set_name(res.id, &format!("LIBRA_ATTRIBUTE_{location}"))?; self.vertex.unset_decoration(res.id, Decoration::Location)?; } for res in &vertex_resources.stage_outputs { let location = self.vertex.get_decoration(res.id, Decoration::Location)?; self.vertex - .set_name(res.id, &format!("RARCH_VARYING_{location}"))?; + .set_name(res.id, &format!("LIBRA_VARYING_{location}"))?; self.vertex.unset_decoration(res.id, Decoration::Location)?; } for res in &fragment_resources.stage_inputs { let location = self.fragment.get_decoration(res.id, Decoration::Location)?; self.fragment - .set_name(res.id, &format!("RARCH_VARYING_{location}"))?; + .set_name(res.id, &format!("LIBRA_VARYING_{location}"))?; self.fragment .unset_decoration(res.id, Decoration::Location)?; } @@ -732,9 +732,9 @@ impl CompileShader for CrossReflect { )); } for res in &vertex_resources.push_constant_buffers { - self.vertex.set_name(res.id, "RARCH_PUSH_VERTEX_INSTANCE")?; + self.vertex.set_name(res.id, "LIBRA_PUSH_VERTEX_INSTANCE")?; self.vertex - .set_name(res.base_type_id, "RARCH_PUSH_VERTEX")?; + .set_name(res.base_type_id, "LIBRA_PUSH_VERTEX")?; } // todo: options @@ -751,8 +751,8 @@ impl CompileShader for CrossReflect { // if flatten { // self.vertex.flatten_buffer_block(res.id)?; // } - self.vertex.set_name(res.id, "RARCH_UBO_VERTEX_INSTANCE")?; - self.vertex.set_name(res.base_type_id, "RARCH_UBO_VERTEX")?; + self.vertex.set_name(res.id, "LIBRA_UBO_VERTEX_INSTANCE")?; + self.vertex.set_name(res.base_type_id, "LIBRA_UBO_VERTEX")?; self.vertex .unset_decoration(res.id, Decoration::DescriptorSet)?; self.vertex.unset_decoration(res.id, Decoration::Binding)?; @@ -767,9 +767,9 @@ impl CompileShader for CrossReflect { } for res in &fragment_resources.push_constant_buffers { self.fragment - .set_name(res.id, "RARCH_PUSH_FRAGMENT_INSTANCE")?; + .set_name(res.id, "LIBRA_PUSH_FRAGMENT_INSTANCE")?; self.fragment - .set_name(res.base_type_id, "RARCH_PUSH_FRAGMENT")?; + .set_name(res.base_type_id, "LIBRA_PUSH_FRAGMENT")?; } if fragment_resources.uniform_buffers.len() > 1 { @@ -785,9 +785,9 @@ impl CompileShader for CrossReflect { // self.fragment.flatten_buffer_block(res.id)?; // } self.fragment - .set_name(res.id, "RARCH_UBO_FRAGMENT_INSTANCE")?; + .set_name(res.id, "LIBRA_UBO_FRAGMENT_INSTANCE")?; self.fragment - .set_name(res.base_type_id, "RARCH_UBO_FRAGMENT")?; + .set_name(res.base_type_id, "LIBRA_UBO_FRAGMENT")?; self.fragment .unset_decoration(res.id, Decoration::DescriptorSet)?; self.fragment @@ -798,7 +798,7 @@ impl CompileShader for CrossReflect { for res in &fragment_resources.sampled_images { let binding = self.fragment.get_decoration(res.id, Decoration::Binding)?; self.fragment - .set_name(res.id, &format!("RARCH_TEXTURE_{binding}"))?; + .set_name(res.id, &format!("LIBRA_TEXTURE_{binding}"))?; self.fragment .unset_decoration(res.id, Decoration::DescriptorSet)?; self.fragment diff --git a/librashader-reflect/src/reflect/mod.rs b/librashader-reflect/src/reflect/mod.rs index e4d35ba..72cd815 100644 --- a/librashader-reflect/src/reflect/mod.rs +++ b/librashader-reflect/src/reflect/mod.rs @@ -13,7 +13,7 @@ pub mod semantics; pub trait ReflectShader { fn reflect( &mut self, - pass_number: u32, + pass_number: usize, semantics: &ReflectSemantics, ) -> Result; } @@ -69,7 +69,7 @@ impl TextureSemanticMap for FxHashMap { if semantics.is_array() { let index = &name[semantics.size_uniform_name().len()..]; - let Ok(index) = u32::from_str(index) else { + let Ok(index) = usize::from_str(index) else { return None; }; return Some(SemanticMap { @@ -101,7 +101,7 @@ impl TextureSemanticMap for FxHashMap UniformType { + match self { + VariableSemantics::MVP => UniformType::MVP, + VariableSemantics::Output => UniformType::Size, + VariableSemantics::FinalViewport => UniformType::Size, + VariableSemantics::FrameCount => UniformType::Unsigned, + VariableSemantics::FrameDirection => UniformType::Signed, + VariableSemantics::FloatParameter => UniformType::Float + } + } } #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)] @@ -78,7 +98,7 @@ impl TextureSemantics { !matches!(self, TextureSemantics::Original | TextureSemantics::Source) } - pub const fn semantics(self, index: u32) -> SemanticMap { + pub const fn semantics(self, index: usize) -> SemanticMap { SemanticMap { semantics: self, index @@ -95,7 +115,7 @@ pub trait ValidateTypeSemantics { } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct SemanticMap { +pub struct SemanticMap { pub semantics: T, pub index: I, } @@ -160,3 +180,28 @@ pub struct ShaderReflection { pub push_constant: Option, pub meta: ReflectMeta, } + +pub trait UniformMeta { + fn offset(&self) -> MemberOffset; + fn id(&self) -> &str; +} + +impl UniformMeta for VariableMeta { + fn offset(&self) -> MemberOffset { + self.offset + } + + fn id(&self) -> &str { + &self.id + } +} + +impl UniformMeta for TextureSizeMeta { + fn offset(&self) -> MemberOffset { + self.offset + } + + fn id(&self) -> &str { + &self.id + } +} \ No newline at end of file diff --git a/librashader-runtime-gl/src/binding.rs b/librashader-runtime-gl/src/binding.rs new file mode 100644 index 0000000..ca5a0f7 --- /dev/null +++ b/librashader-runtime-gl/src/binding.rs @@ -0,0 +1,66 @@ +use std::borrow::Borrow; +use std::hash::{Hash, Hasher}; +use gl::types::GLint; +use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, VariableSemantics}; + +#[derive(Debug)] +pub enum VariableLocation { + Ubo(UniformLocation), + Push(UniformLocation), +} + +impl VariableLocation { + pub fn location(&self) -> UniformLocation { + match self { + VariableLocation::Ubo(l) | VariableLocation::Push(l) => *l + } + } +} + +#[derive(Debug, Copy, Clone)] +pub struct UniformLocation { + pub vertex: T, + pub fragment: T, +} + +impl UniformLocation { + pub fn is_fragment_valid(&self) -> bool { + self.fragment >= 0 + } + + pub fn is_vertex_valid(&self) -> bool { + self.vertex >= 0 + } + + pub fn is_valid(&self) -> bool { + self.is_fragment_valid() || self.is_vertex_valid() + } +} + +#[derive(Debug, Copy, Clone)] +pub enum MemberLocation { + Offset(MemberOffset), + Uniform(UniformLocation) +} + +#[derive(Debug, Copy, Clone)] +pub struct TextureUnit(T); + +#[derive(Debug, Clone, Eq, Hash, PartialEq)] +pub enum UniformBinding { + Parameter(String), + SemanticVariable(VariableSemantics), + TextureSize(SemanticMap), +} + +impl From for UniformBinding { + fn from(value: VariableSemantics) -> Self { + UniformBinding::SemanticVariable(value) + } +} + +impl From> for UniformBinding { + fn from(value: SemanticMap) -> Self { + UniformBinding::TextureSize(value) + } +} diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index 1ce581d..883e3c5 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -1,3 +1,4 @@ +use std::borrow::Borrow; use std::iter::Filter; use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint}; use librashader_reflect::back::cross::GlslangGlslContext; @@ -11,17 +12,18 @@ use librashader_presets::{Scale2D, ScaleType, Scaling, ShaderPassConfig, ShaderP use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureImage, TextureSemantics, VariableMeta, VariableSemantics}; use crate::{FilterChain, FilterCommon}; use crate::framebuffer::Framebuffer; -use crate::util::{Location, VariableLocation, RingBuffer, Size, GlImage, Texture, Viewport}; +use crate::binding::{UniformBinding, UniformLocation, VariableLocation}; +use crate::util::{GlImage, RingBuffer, Size, Texture, Viewport}; pub struct FilterPass { pub reflection: ShaderReflection, pub compiled: ShaderCompilerOutput, pub program: GLuint, - pub ubo_location: Location, + pub ubo_location: UniformLocation, pub ubo_ring: Option>, pub uniform_buffer: Box<[u8]>, pub push_buffer: Box<[u8]>, - pub locations: FxHashMap, + pub variable_bindings: FxHashMap, pub framebuffer: Framebuffer, pub feedback_framebuffer: Framebuffer, pub source: ShaderSource, @@ -34,7 +36,7 @@ impl FilterPass { buffer.copy_from_slice(mvp); } - fn build_vec4(location: Location, buffer: &mut [u8], size: Size) { + fn build_vec4(location: UniformLocation, buffer: &mut [u8], size: Size) { let vec4 = [size.width as f32, size.height as f32, 1.0 / size.width as f32, 1.0/ size.height as f32]; if location.fragment >= 0 || location.vertex >= 0 { unsafe { @@ -52,7 +54,7 @@ impl FilterPass { } #[inline(always)] - fn build_uniform(location: Location, buffer: &mut [u8], value: T, glfn: unsafe fn(GLint, T) -> ()) + fn build_uniform(location: UniformLocation, buffer: &mut [u8], value: T, glfn: unsafe fn(GLint, T) -> ()) where T: Copy, T: bytemuck::Pod { if location.fragment >= 0 || location.vertex >= 0 { @@ -70,19 +72,19 @@ impl FilterPass { } } - fn build_uint(location: Location, buffer: &mut [u8], value: u32) { + fn build_uint(location: UniformLocation, buffer: &mut [u8], value: u32) { Self::build_uniform(location, buffer, value, gl::Uniform1ui) } - fn build_sint(location: Location, buffer: &mut [u8], value: i32) { + fn build_sint(location: UniformLocation, buffer: &mut [u8], value: i32) { Self::build_uniform(location, buffer, value, gl::Uniform1i) } - fn build_float(location: Location, buffer: &mut [u8], value: f32) { + fn build_float(location: UniformLocation, buffer: &mut [u8], value: f32) { Self::build_uniform(location, buffer, value, gl::Uniform1f) } - fn set_texture(binding: &TextureImage, texture: &Texture) { + fn bind_texture(binding: &TextureImage, texture: &Texture) { unsafe { // eprintln!("binding {} = texture {}", binding.binding, texture.image.handle); gl::ActiveTexture((gl::TEXTURE0 + binding.binding) as GLenum); @@ -158,7 +160,8 @@ impl FilterPass { size } - pub fn build_commands(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) { + // todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo) + pub fn build_commands(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: i32, viewport: &Viewport, original: &Texture, source: &Texture) { let mut fb_format = ShaderFormat::R8G8B8A8Unorm; if self.config.srgb_framebuffer { fb_format = ShaderFormat::R8G8B8A8Srgb; @@ -247,134 +250,148 @@ impl FilterPass { } // framecount should be pre-modded - fn build_semantics(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, fb_size: Size, viewport: &Viewport, original: &Texture, source: &Texture) { - - if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::MVP) { - let mvp = mvp.unwrap_or(&[ - 2f32, 0.0, 0.0, 0.0, - 0.0, 2.0, 0.0, 0.0, - 0.0, 0.0, 2.0, 0.0, - -1.0, -1.0, 0.0, 1.0 - ]); - - let mvp_size = mvp.len() * std::mem::size_of::(); - let (buffer, offset) = match variable.offset { - MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), - MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) - }; - FilterPass::build_mvp(&mut buffer[offset..][..mvp_size], mvp) + fn build_semantics(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: i32, fb_size: Size, viewport: &Viewport, original: &Texture, source: &Texture) { + if let Some((_location, offset)) = self.variable_bindings.get(&VariableSemantics::MVP.into()) { + let mvp = mvp.unwrap_or(&[ + 2f32, 0.0, 0.0, 0.0, + 0.0, 2.0, 0.0, 0.0, + 0.0, 0.0, 2.0, 0.0, + -1.0, -1.0, 0.0, 1.0 + ]); + let mvp_size = mvp.len() * std::mem::size_of::(); + let (buffer, offset) = match offset { + MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), + MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset) + }; + FilterPass::build_mvp(&mut buffer[offset..][..mvp_size], mvp) } - if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::Output) { - let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); - 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(location, &mut buffer[offset..][..4], fb_size) - } - - if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::FinalViewport) { - // todo: do all variables have location..? - let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); - 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(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(); - let (buffer, offset) = match variable.offset { - MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), - MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) - }; - FilterPass::build_uint(location, &mut buffer[offset..][..4], frame_count) - } - - if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::FrameDirection) { - // todo: do all variables have location..? - let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); - let (buffer, offset) = match variable.offset { - MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), - MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) + if let Some((location, offset)) = self.variable_bindings.get(&VariableSemantics::Output.into()) { + let (buffer, offset) = match offset { + MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), + MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset) }; - FilterPass::build_uint(location, &mut buffer[offset..][..4], frame_direction) + FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], fb_size) } + if let Some((location, offset)) = self.variable_bindings.get(&VariableSemantics::FinalViewport.into()) { + let (buffer, offset) = match offset { + MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), + MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset) + }; + FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], viewport.size) + } + + if let Some((location, offset)) = self.variable_bindings.get(&VariableSemantics::FrameCount.into()) { + let (buffer, offset) = match offset { + MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), + MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset) + }; + FilterPass::build_uint(location.location(), &mut buffer[offset..][..4], frame_count) + } + + if let Some((location, offset)) = self.variable_bindings.get(&VariableSemantics::FrameDirection.into()) { + let (buffer, offset) = match offset { + MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), + MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset) + }; + FilterPass::build_sint(location.location(), &mut buffer[offset..][..4], frame_direction) + } if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) { eprintln!("setting original binding to {}", binding.binding); - FilterPass::set_texture(binding, original); + FilterPass::bind_texture(binding, original); } - if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::Original.semantics(0)) { - let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); - let (buffer, offset) = match variable.offset { - MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), - MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) + + if let Some((location, offset)) = self.variable_bindings.get(&TextureSemantics::Original.semantics(0).into()) { + let (buffer, offset) = match offset { + 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.image.size); - + FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], original.image.size); } - if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) { // eprintln!("setting source binding to {}", binding.binding); - FilterPass::set_texture(binding, source); + FilterPass::bind_texture(binding, source); } - if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::Source.semantics(0)) { - let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); - let (buffer, offset) = match variable.offset { - MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), - MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) + if let Some((location, offset)) = self.variable_bindings.get(&TextureSemantics::Source.semantics(0).into()) { + let (buffer, offset) = match offset { + MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), + MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset) }; - FilterPass::build_vec4(location, &mut buffer[offset..][..4], source.image.size); + FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], source.image.size); } - - // todo: history - - // if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { - // FilterPass::set_texture(binding, original); - // } - // if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { - // let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); - // 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(location, &mut buffer[offset..][..4], original.image.size); - // } - - for variable in self.reflection.meta.parameter_meta.values() { - let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); - let (buffer, offset) = match variable.offset { - MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset), - MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset) + // // todo: history + // + // // if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { + // // FilterPass::set_texture(binding, original); + // // } + // // if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) { + // // let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location(); + // // 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(location, &mut buffer[offset..][..4], original.image.size); + // // } + // + for (id, (location, offset)) in self.variable_bindings.iter() + .filter_map(|(binding, value)| match binding { + UniformBinding::Parameter(id) => { + Some((id, value)) + } + _ => None + }) + { + let id = id.as_str(); + let (buffer, offset) = match offset { + MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), + MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset) }; // presets override params - let default = self.source.parameters.iter().find(|&p| p.id == variable.id) + let default = self.source.parameters.iter().find(|&p| p.id == id) .map(|f| f.initial) .unwrap_or(0f32); - let value = parent.preset.parameters.iter().find(|&p| p.name == variable.id) + let value = parent.preset.parameters.iter().find(|&p| p.name == id) .map(|p| p.value) .unwrap_or(default); - FilterPass::build_float(location, &mut buffer[offset..][..4], value) + FilterPass::build_float(location.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 + for (id, (location, offset)) in self.variable_bindings.iter() + .filter_map(|(binding, value)| match binding { + UniformBinding::TextureSize(semantics) => { + if semantics.semantics == TextureSemantics::User { + Some((semantics, value)) + } else { + None + } + } + _ => None + }) + { + let (buffer, offset) = match offset { + MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset), + MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset) + }; + + if let Some(lut) = parent.luts.get(&id.index) { + if let Some(binding) = self.reflection.meta.texture_meta.get(&id) { + FilterPass::bind_texture(binding, lut); + } + + FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], + lut.image.size); + } + } + + + // // todo history } } \ No newline at end of file diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs index 62c4930..4b103ff 100644 --- a/librashader-runtime-gl/src/lib.rs +++ b/librashader-runtime-gl/src/lib.rs @@ -5,6 +5,7 @@ mod filter; mod filter_pass; mod util; mod framebuffer; +mod binding; use std::collections::HashMap; use std::error::Error; @@ -26,9 +27,11 @@ use librashader_reflect::back::targets::{FromCompilation, GLSL}; use librashader_reflect::front::shaderc::GlslangCompilation; 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::semantics::{MemberOffset, SemanticMap, TextureSemantics, UniformMeta, VariableMeta, VariableSemantics}; use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap}; -use util::{Location, VariableLocation, RingBuffer, Size, GlImage, Texture, Viewport}; +use binding::{UniformLocation, VariableLocation}; +use util::{GlImage, RingBuffer, Size, Texture, Viewport}; +use crate::binding::UniformBinding; unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint { let shader = gl::CreateShader(stage); @@ -63,7 +66,7 @@ impl FilterChain { return; } - let index = config.id as u32; + let index = config.id as usize; // PassOutput texture_semantics.insert(alias.clone(), SemanticMap { @@ -86,31 +89,31 @@ impl FilterChain { })); } - fn reflect_parameter(pipeline: GLuint, meta: &VariableMeta) -> VariableLocation { + fn reflect_uniform_location(pipeline: GLuint, meta: &impl UniformMeta) -> VariableLocation { // todo: support both ubo and pushco // todo: fix this. - match meta.offset { + match meta.offset() { MemberOffset::Ubo(_) => { - let vert_name = format!("RARCH_UBO_VERTEX_INSTANCE.{}\0", meta.id); - let frag_name = format!("RARCH_UBO_FRAGMENT_INSTANCE.{}\0", meta.id); + let vert_name = format!("LIBRA_UBO_VERTEX_INSTANCE.{}\0", meta.id()); + let frag_name = format!("LIBRA_UBO_FRAGMENT_INSTANCE.{}\0", meta.id()); unsafe { let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast()); let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast()); - VariableLocation::Ubo(Location { + VariableLocation::Ubo(UniformLocation { vertex, fragment }) } } MemberOffset::PushConstant(_) => { - let vert_name = format!("RARCH_PUSH_VERTEX_INSTANCE.{}\0", meta.id); - let frag_name = format!("RARCH_PUSH_FRAGMENT_INSTANCE.{}\0", meta.id); + let vert_name = format!("LIBRA_PUSH_VERTEX_INSTANCE.{}\0", meta.id()); + let frag_name = format!("LIBRA_PUSH_FRAGMENT_INSTANCE.{}\0", meta.id()); unsafe { let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast()); let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast()); - VariableLocation::Push(Location { + VariableLocation::Push(UniformLocation { vertex, fragment }) @@ -133,7 +136,7 @@ pub struct FilterCommon { original_history: Vec, history: Vec, feedback: Vec, - luts: FxHashMap, + luts: FxHashMap, pub quad_vbo: GLuint, pub input_framebuffer: Framebuffer, } @@ -174,12 +177,12 @@ impl FilterChain { for (index, texture) in preset.textures.iter().enumerate() { texture_semantics.insert(texture.name.clone(), SemanticMap { semantics: TextureSemantics::User, - index: index as u32 + index }); uniform_semantics.insert(format!("{}Size", texture.name), UniformSemantic::Texture(SemanticMap { semantics: TextureSemantics::User, - index: index as u32 + index })); } @@ -194,7 +197,7 @@ impl FilterChain { for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() { let mut semantics = semantics.clone(); - let reflection = reflect.reflect(index as u32, &semantics)?; + let reflection = reflect.reflect(index, &semantics)?; let glsl = reflect.compile(GlVersion::V4_60)?; let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?; @@ -210,7 +213,7 @@ impl FilterChain { 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}\0"); + let loc_name = format!("LIBRA_ATTRIBUTE_{loc}\0"); eprintln!("{loc_name}"); gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast()) } @@ -225,7 +228,7 @@ impl FilterChain { } for binding in &glsl.context.texture_fixups { - let loc_name = format!("RARCH_TEXTURE_{}\0", *binding); + let loc_name = format!("LIBRA_TEXTURE_{}\0", *binding); unsafe { let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast()); if location >= 0 { @@ -236,9 +239,9 @@ impl FilterChain { 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()), + (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()), }) } }; @@ -265,13 +268,21 @@ impl FilterChain { // todo: reflect indexed parameters let mut locations = FxHashMap::default(); for param in reflection.meta.parameter_meta.values() { - locations.insert(param.id.clone(), FilterChain::reflect_parameter(program, param)); + locations.insert(UniformBinding::Parameter(param.id.clone()), + (FilterChain::reflect_uniform_location(program, param), param.offset)); } - for param in reflection.meta.variable_meta.values() { - locations.insert(param.id.clone(), FilterChain::reflect_parameter(program, param)); + for (semantics, param) in &reflection.meta.variable_meta { + locations.insert(UniformBinding::SemanticVariable(semantics.clone()), + (FilterChain::reflect_uniform_location(program, param), param.offset)); } + for (semantics, param) in &reflection.meta.texture_size_meta { + locations.insert(UniformBinding::TextureSize(semantics.clone()), + (FilterChain::reflect_uniform_location(program, param), param.offset)); + } + + // eprintln!("{:#?}", semantics); eprintln!("{:#?}", reflection.meta); @@ -290,7 +301,7 @@ impl FilterChain { ubo_ring, uniform_buffer, push_buffer, - locations, + variable_bindings: locations, source, // no idea if this works. // retroarch checks if feedback frames are used but we'll just init it tbh. @@ -323,7 +334,7 @@ impl FilterChain { // load luts let mut luts = FxHashMap::default(); - for texture in &preset.textures { + for (index, texture) in preset.textures.iter().enumerate() { let image = Image::load(&texture.path)?; let levels = if texture.mipmap { util::calc_miplevel(image.width, image.height) @@ -374,7 +385,7 @@ impl FilterChain { gl::BindTexture(gl::TEXTURE_2D, 0); } - luts.insert(texture.name.clone(), Texture { + luts.insert(index, Texture { image: GlImage { handle, format: gl::RGBA8, diff --git a/librashader-runtime-gl/src/util.rs b/librashader-runtime-gl/src/util.rs index 064d236..5f67bcd 100644 --- a/librashader-runtime-gl/src/util.rs +++ b/librashader-runtime-gl/src/util.rs @@ -1,26 +1,6 @@ use gl::types::{GLenum, GLint, GLuint}; use librashader::{FilterMode, WrapMode}; -#[derive(Debug, Copy, Clone)] -pub struct Location { - pub vertex: T, - pub fragment: T, -} - -#[derive(Debug)] -pub enum VariableLocation { - Ubo(Location), - Push(Location), -} - -impl VariableLocation { - pub fn location(&self) -> Location { - match self { - VariableLocation::Ubo(l) | VariableLocation::Push(l) => *l - } - } -} - pub fn calc_miplevel(width: u32, height: u32) -> u32 { let mut size = std::cmp::max(width, height); let mut levels = 0;