From 66d1c872ee4202506f6c189593c52ed88735cf50 Mon Sep 17 00:00:00 2001 From: chyyran Date: Sat, 12 Nov 2022 01:23:49 -0500 Subject: [PATCH] gl: get some more reflection work done --- librashader-reflect/src/back/cross.rs | 4 +- librashader-reflect/src/reflect/cross.rs | 23 +- librashader-reflect/src/reflect/semantics.rs | 2 + librashader-runtime-gl/src/lib.rs | 234 ++++++++++++++++--- 4 files changed, 217 insertions(+), 46 deletions(-) diff --git a/librashader-reflect/src/back/cross.rs b/librashader-reflect/src/back/cross.rs index 5ec61bd..32cad71 100644 --- a/librashader-reflect/src/back/cross.rs +++ b/librashader-reflect/src/back/cross.rs @@ -6,14 +6,14 @@ use crate::reflect::cross::{CompiledAst, CrossReflect, GlslReflect, HlslReflect} use crate::reflect::ReflectShader; pub type GlVersion = spirv_cross::glsl::Version; -pub struct GlslangCompileContext { +pub struct GlslangGlslContext { pub texture_fixups: Vec, pub compiler: CompiledAst } impl FromCompilation for GLSL { type Target = GLSL; type Options = GlVersion; - type Context = GlslangCompileContext; + type Context = GlslangGlslContext; fn from_compilation( compile: GlslangCompilation, diff --git a/librashader-reflect/src/reflect/cross.rs b/librashader-reflect/src/reflect/cross.rs index 83c72e0..1c692db 100644 --- a/librashader-reflect/src/reflect/cross.rs +++ b/librashader-reflect/src/reflect/cross.rs @@ -15,7 +15,7 @@ use spirv_cross::{glsl, hlsl, ErrorCode}; use crate::back::targets::{GLSL, HLSL}; use crate::back::{CompileShader, ShaderCompilerOutput}; -use crate::back::cross::GlslangCompileContext; +use crate::back::cross::GlslangGlslContext; pub struct CrossReflect where @@ -291,7 +291,6 @@ where blame: SemanticErrorBlame, ) -> Result<(), ShaderReflectError> { let ranges = ast.get_active_buffer_ranges(resource.id)?; - eprintln!("{ranges:?}"); for range in ranges { let name = ast.get_member_name(resource.base_type_id, range.index)?; let ubo_type = ast.get_type(resource.base_type_id)?; @@ -333,6 +332,7 @@ where meta.parameter_meta.insert( parameter.index, VariableMeta { + id: name, offset, components: typeinfo.size, }, @@ -360,6 +360,7 @@ where meta.variable_meta.insert( *semantics, VariableMeta { + id: name, offset, components: typeinfo.size * typeinfo.columns, }, @@ -381,6 +382,7 @@ where } } + // this will break if range is both ubo and push buf whatever let offset = offset_type(range.offset); if let Some(meta) = meta.texture_size_meta.get_mut(&texture) { if offset != meta.offset { @@ -405,6 +407,7 @@ where SemanticErrorBlame::Vertex => BindingStage::VERTEX, SemanticErrorBlame::Fragment => BindingStage::FRAGMENT, }, + id: name }, ); } @@ -683,7 +686,7 @@ where impl CompileShader for CrossReflect { type Options = glsl::Version; - type Context = GlslangCompileContext; + type Context = GlslangGlslContext; fn compile( mut self, @@ -745,9 +748,9 @@ impl CompileShader for CrossReflect { )); } for res in &vertex_resources.uniform_buffers { - if flatten { - self.vertex.flatten_buffer_block(res.id)?; - } + // 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 @@ -778,9 +781,9 @@ impl CompileShader for CrossReflect { } for res in &fragment_resources.uniform_buffers { - if flatten { - self.fragment.flatten_buffer_block(res.id)?; - } + // if flatten { + // self.fragment.flatten_buffer_block(res.id)?; + // } self.fragment .set_name(res.id, "RARCH_UBO_FRAGMENT_INSTANCE")?; self.fragment @@ -806,7 +809,7 @@ impl CompileShader for CrossReflect { Ok(ShaderCompilerOutput { vertex: self.vertex.compile()?, fragment: self.fragment.compile()?, - context: GlslangCompileContext { + context: GlslangGlslContext { texture_fixups, compiler: CompiledAst { vertex: self.vertex, diff --git a/librashader-reflect/src/reflect/semantics.rs b/librashader-reflect/src/reflect/semantics.rs index 5ea6345..2f3403c 100644 --- a/librashader-reflect/src/reflect/semantics.rs +++ b/librashader-reflect/src/reflect/semantics.rs @@ -122,6 +122,7 @@ pub struct VariableMeta { // this might bite us in the back because retroarch keeps separate UBO/push offsets.. eh pub offset: MemberOffset, pub components: u32, + pub id: String, } #[derive(Debug)] @@ -129,6 +130,7 @@ pub struct TextureSizeMeta { // this might bite us in the back because retroarch keeps separate UBO/push offsets.. pub offset: MemberOffset, pub stage_mask: BindingStage, + pub id: String, } #[derive(Debug)] diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs index 4619797..5faeca4 100644 --- a/librashader-runtime-gl/src/lib.rs +++ b/librashader-runtime-gl/src/lib.rs @@ -3,18 +3,19 @@ mod hello_triangle; use std::collections::HashMap; use std::error::Error; use std::path::Path; -use gl::types::{GLenum, GLuint}; +use gl::types::{GLenum, GLint, GLsizeiptr, GLuint}; use rustc_hash::FxHashMap; +use spirv_cross::spirv::Decoration; use librashader::ShaderSource; use librashader_presets::ShaderPassConfig; -use librashader_reflect::back::CompileShader; -use librashader_reflect::back::cross::GlVersion; +use librashader_reflect::back::{CompileShader, ShaderCompilerOutput}; +use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion}; 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, UniformSemantic}; -use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, VariableSemantics}; +use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, ShaderReflection, UniformSemantic}; +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>, @@ -52,7 +53,97 @@ pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap { + items: [T; SIZE], + index: usize +} +impl RingBuffer +where T: Copy, T: Default +{ + pub fn new() -> Self { + Self { + items: [T::default(); SIZE], + index: 0 + } + } +} + +impl RingBuffer { + pub fn current(&self) -> &T { + &self.items[self.index] + } + + pub fn next(&mut self) { + self.index += 1; + if self.index >= SIZE { + self.index = 0 + } + } +} + + +#[derive(Debug)] +pub struct Location { + vertex: T, + fragment: T, +} + +#[derive(Debug)] +pub enum ParameterLocation { + Ubo(Location), + Push(Location), +} +pub struct FilterPass { + reflection: ShaderReflection, + compiled: ShaderCompilerOutput, + program: GLuint, + ubo_location: Location, + ubo_ring: Option>, + uniform_buffer: Vec, + push_buffer: Vec, + locations: FxHashMap +} + +pub struct FilterChain { + reflections: Vec, + compiled: Vec>, + programs: Vec, + ubo_location: Location, +} + +pub fn reflect_parameter(pipeline: GLuint, meta: &VariableMeta) -> ParameterLocation { + // todo: support both ubo and pushco + // todo: fix this. + 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); + unsafe { + let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast()); + let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast()); + + ParameterLocation::Ubo(Location { + 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); + unsafe { + let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast()); + let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast()); + + ParameterLocation::Push(Location { + vertex, + fragment + }) + } + } + } +} // todo: init gl pub fn load(path: impl AsRef) -> Result<(), Box>{ @@ -96,41 +187,114 @@ pub fn load(path: impl AsRef) -> Result<(), Box>{ non_uniform_semantics: texture_semantics }; - let mut reflections = Vec::new(); - let mut compiled = Vec::new(); + let mut filters = Vec::new(); for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() { let reflection = reflect.reflect(index as u32, &semantics)?; let glsl = reflect.compile(GlVersion::V4_60)?; + let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?; - // shader_gl3: 1375 - reflection.meta.texture_meta.get(&SemanticMap { - semantics: TextureSemantics::Source, - index: 0 - }).unwrap().binding; + // 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()); - // 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 program = gl::CreateProgram(); - // gl::AttachShader(program, vertex); - // gl::AttachShader(program, fragment); - // - // } + 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!("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); + } + } + } + + 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); + } + 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)); + } + + for param in reflection.meta.variable_meta.values() { + locations.insert(param.id.clone(), reflect_parameter(program, param)); + } - compiled.push(glsl); - reflections.push(reflection); + 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 - } + // let mut glprogram: Vec = Vec::new(); + // for compilation in &compiled { + // // compilation.context.compiler.vertex + // } - eprintln!("{:#?}", reflections); +// eprintln!("{:#?}", reflections); // eprintln!("{:#?}", compiled./); // eprintln!("{:?}", preset); @@ -164,13 +328,15 @@ mod tests { #[test] fn triangle() { let (glfw, window, events, shader, vao) = hello_triangle::setup(); + load("../test/basic.slangp") + .unwrap(); hello_triangle::do_loop(glfw, window, events, shader, vao); } - #[test] - fn load_preset() { - - load("../test/basic.slangp") - .unwrap(); - } + // #[test] + // fn load_preset() { + // + // load("../test/basic.slangp") + // .unwrap(); + // } }