From 301b8bf209dffd123b443c0a77df1c88a8e6451d Mon Sep 17 00:00:00 2001 From: chyyran Date: Wed, 9 Nov 2022 01:11:25 -0500 Subject: [PATCH] gl: add name mapping to gl compiler --- .idea/src.iml | 1 + Cargo.lock | 71 ++++++++++++ Cargo.toml | 1 + librashader-reflect/src/back/mod.rs | 7 +- librashader-reflect/src/back/targets.rs | 3 +- librashader-reflect/src/lib.rs | 1 + librashader-reflect/src/reflect/cross.rs | 89 +++++++++++++- librashader-runtime-dx11/Cargo.toml | 11 +- librashader-runtime-gl/Cargo.toml | 23 ++++ librashader-runtime-gl/src/lib.rs | 142 +++++++++++++++++++++++ 10 files changed, 341 insertions(+), 8 deletions(-) create mode 100644 librashader-runtime-gl/Cargo.toml create mode 100644 librashader-runtime-gl/src/lib.rs diff --git a/.idea/src.iml b/.idea/src.iml index a3a4323..1f841a2 100644 --- a/.idea/src.iml +++ b/.idea/src.iml @@ -10,6 +10,7 @@ + diff --git a/Cargo.lock b/Cargo.lock index 5280748..88da746 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -449,6 +449,20 @@ dependencies = [ "librashader-reflect", "rustc-hash", "spirv_cross", + "windows", +] + +[[package]] +name = "librashader-runtime-gl" +version = "0.1.0" +dependencies = [ + "librashader", + "librashader-preprocess", + "librashader-presets", + "librashader-reflect", + "rustc-hash", + "spirv_cross", + "windows", ] [[package]] @@ -1007,6 +1021,63 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + [[package]] name = "xmlparser" version = "0.13.5" diff --git a/Cargo.toml b/Cargo.toml index eb130fc..0eec267 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,5 +5,6 @@ members = [ "librashader-preprocess", "librashader-reflect", "librashader-runtime-dx11", + "librashader-runtime-gl", "naga" ] \ No newline at end of file diff --git a/librashader-reflect/src/back/mod.rs b/librashader-reflect/src/back/mod.rs index bdfc268..7bb1f81 100644 --- a/librashader-reflect/src/back/mod.rs +++ b/librashader-reflect/src/back/mod.rs @@ -5,7 +5,8 @@ use std::fmt::Debug; pub use targets::ShaderCompiler; #[derive(Debug)] -pub struct CompiledShader { - pub vertex: T, - pub fragment: T, +pub struct CompiledShader { + pub vertex: Source, + pub fragment: Source, + pub context: Context, } diff --git a/librashader-reflect/src/back/targets.rs b/librashader-reflect/src/back/targets.rs index 841b7a3..4d9625b 100644 --- a/librashader-reflect/src/back/targets.rs +++ b/librashader-reflect/src/back/targets.rs @@ -17,6 +17,7 @@ impl OutputTarget for MSL {} pub trait ShaderCompiler { type Output; type Options; + type Context = (); - fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result, ShaderCompileError>; + fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result, ShaderCompileError>; } diff --git a/librashader-reflect/src/lib.rs b/librashader-reflect/src/lib.rs index cf915a0..f605bf4 100644 --- a/librashader-reflect/src/lib.rs +++ b/librashader-reflect/src/lib.rs @@ -1,4 +1,5 @@ #![feature(let_else)] +#![feature(associated_type_defaults)] pub mod error; pub mod front; diff --git a/librashader-reflect/src/reflect/cross.rs b/librashader-reflect/src/reflect/cross.rs index ce29476..8417e56 100644 --- a/librashader-reflect/src/reflect/cross.rs +++ b/librashader-reflect/src/reflect/cross.rs @@ -24,6 +24,8 @@ where } pub type HlslReflect = CrossReflect; +pub type GlslReflect = CrossReflect; + impl ValidateTypeSemantics for VariableSemantics { fn validate_type(&self, ty: &Type) -> Option { let (Type::Float { ref array, vecsize, columns } | Type::Int { ref array, vecsize, columns } | Type::UInt { ref array, vecsize, columns }) = *ty else { @@ -785,17 +787,97 @@ where } } +pub type GlslOptions = glsl::CompilerOptions; + impl ShaderCompiler for CrossReflect { type Output = String; type Options = glsl::CompilerOptions; + type Context = Vec; - fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result, ShaderCompileError> { + // todo: compile should consume self + fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result, ShaderCompileError> { self.vertex.set_compiler_options(options)?; self.fragment.set_compiler_options(options)?; + let vertex_resources = self.vertex.get_shader_resources()?; + let fragment_resources = self.fragment.get_shader_resources()?; + + 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}"))?; + 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}"))?; + 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}"))?; + self.fragment.unset_decoration(res.id, Decoration::Location)?; + } + + if vertex_resources.push_constant_buffers.len() > 1 { + return Err(ShaderCompileError::SpirvCrossCompileError(ErrorCode::CompilationError(String::from("Cannot have more than one push constant buffer")))); + } + for res in &vertex_resources.push_constant_buffers { + self.vertex.set_name(res.id, "RARCH_PUSH_VERTEX_INSTANCE")?; + self.vertex.set_name(res.base_type_id, "RARCH_PUSH_VERTEX")?; + } + + // todo: options + let flatten = false; + + if vertex_resources.uniform_buffers.len() > 1 { + return Err(ShaderCompileError::SpirvCrossCompileError(ErrorCode::CompilationError(String::from("Cannot have more than one uniform buffer")))); + } + for res in &vertex_resources.uniform_buffers { + 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.unset_decoration(res.id, Decoration::DescriptorSet)?; + self.vertex.unset_decoration(res.id, Decoration::Binding)?; + + } + + if fragment_resources.push_constant_buffers.len() > 1 { + return Err(ShaderCompileError::SpirvCrossCompileError(ErrorCode::CompilationError(String::from("Cannot have more than one push constant buffer")))); + } + for res in &fragment_resources.push_constant_buffers { + self.fragment.set_name(res.id, "RARCH_PUSH_FRAGMENT_INSTANCE")?; + self.fragment.set_name(res.base_type_id, "RARCH_PUSH_FRAGMENT")?; + } + + if fragment_resources.uniform_buffers.len() > 1 { + return Err(ShaderCompileError::SpirvCrossCompileError(ErrorCode::CompilationError(String::from("Cannot have more than one uniform buffer")))); + } + + for res in &fragment_resources.uniform_buffers { + if flatten { + self.fragment.flatten_buffer_block(res.id)?; + } + self.fragment.set_name(res.id, "RARCH_UBO_FRAGMENT_INSTANCE")?; + self.fragment.set_name(res.base_type_id, "RARCH_UBO_FRAGMENT")?; + self.fragment.unset_decoration(res.id, Decoration::DescriptorSet)?; + self.fragment.unset_decoration(res.id, Decoration::Binding)?; + } + + let mut texture_fixups = Vec::new(); + 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}"))?; + self.fragment.unset_decoration(res.id, Decoration::DescriptorSet)?; + self.fragment.unset_decoration(res.id, Decoration::Binding)?; + texture_fixups.push(binding); + } + Ok(CompiledShader { vertex: self.vertex.compile()?, - fragment: self.fragment.compile()? + fragment: self.fragment.compile()?, + context: texture_fixups }) } } @@ -812,7 +894,8 @@ impl ShaderCompiler for CrossReflect { Ok(CompiledShader { vertex: self.vertex.compile()?, - fragment: self.fragment.compile()? + fragment: self.fragment.compile()?, + context: () }) } } diff --git a/librashader-runtime-dx11/Cargo.toml b/librashader-runtime-dx11/Cargo.toml index 4adc399..b6f3083 100644 --- a/librashader-runtime-dx11/Cargo.toml +++ b/librashader-runtime-dx11/Cargo.toml @@ -11,4 +11,13 @@ edition = "2021" "librashader-preprocess" = { path = "../librashader-preprocess" } "librashader-reflect" = { path = "../librashader-reflect" } spirv_cross = { version = "0.23.1", features = [ "hlsl" ] } -rustc-hash = "1.1.0" \ No newline at end of file +rustc-hash = "1.1.0" + +[dependencies.windows] +version = "0.43.0" +features = [ + "Win32_Foundation", + "Win32_Graphics_Dxgi_Common", + "Win32_Graphics_Direct3D", + "Win32_Graphics_Direct3D11", +] \ No newline at end of file diff --git a/librashader-runtime-gl/Cargo.toml b/librashader-runtime-gl/Cargo.toml new file mode 100644 index 0000000..276bed2 --- /dev/null +++ b/librashader-runtime-gl/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "librashader-runtime-gl" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +"librashader" = { path = "../librashader" } +"librashader-presets" = { path = "../librashader-presets" } +"librashader-preprocess" = { path = "../librashader-preprocess" } +"librashader-reflect" = { path = "../librashader-reflect" } +spirv_cross = { version = "0.23.1", features = [ "hlsl" ] } +rustc-hash = "1.1.0" + +[dependencies.windows] +version = "0.43.0" +features = [ + "Win32_Foundation", + "Win32_Graphics_Dxgi_Common", + "Win32_Graphics_Direct3D", + "Win32_Graphics_Direct3D11", +] \ No newline at end of file diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs new file mode 100644 index 0000000..95fc93c --- /dev/null +++ b/librashader-runtime-gl/src/lib.rs @@ -0,0 +1,142 @@ +use std::collections::HashMap; +use std::error::Error; +use std::path::Path; +use rustc_hash::FxHashMap; +use spirv_cross::glsl::{Precision, Version}; +use spirv_cross::hlsl::ShaderModel; +use librashader::ShaderSource; +use librashader_presets::ShaderPassConfig; +use librashader_reflect::back::ShaderCompiler; +use librashader_reflect::front::shaderc::GlslangCompilation; +use librashader_reflect::reflect::cross::{CrossReflect, GlslOptions, GlslReflect, HlslOptions, HlslReflect}; +use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, UniformSemantic}; +use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, VariableSemantics}; + + +pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap, texture_semantics: &mut FxHashMap>, + config: &ShaderPassConfig) { + let Some(alias) = &config.alias else { + return; + }; + + // Ignore empty aliases + if alias.trim().is_empty() { + return; + } + + let index = config.id as u32; + + // PassOutput + texture_semantics.insert(alias.clone(), SemanticMap { + semantics: TextureSemantics::PassOutput, + index + }); + uniform_semantics.insert(format!("{alias}Size"), UniformSemantic::Texture(SemanticMap { + semantics: TextureSemantics::PassOutput, + index + })); + + // PassFeedback + texture_semantics.insert(format!("{alias}Feedback"), SemanticMap { + semantics: TextureSemantics::PassFeedback, + index + }); + uniform_semantics.insert(format!("{alias}FeedbackSize"), UniformSemantic::Texture(SemanticMap { + semantics: TextureSemantics::PassFeedback, + index + })); + +} + +pub fn load(path: impl AsRef) -> Result<(), Box>{ + let preset = librashader_presets::ShaderPreset::try_parse(path)?; + let mut passes: Vec<(&ShaderPassConfig, ShaderSource, GlslReflect)> = preset.shaders.iter() + .map(|shader| { + let source = librashader_preprocess::load_shader_source(&shader.name) + .unwrap(); + let spirv = librashader_reflect::front::shaderc::compile_spirv(&source) + .unwrap(); + let mut reflect = librashader_reflect::reflect::cross::GlslReflect::try_from(spirv).unwrap(); + (shader, source, reflect) + }).collect(); + + // todo: this can probably be extracted out. + let mut uniform_semantics: FxHashMap = Default::default(); + let mut texture_semantics: FxHashMap> = Default::default(); + + for details in &passes { + load_pass_semantics(&mut uniform_semantics, &mut texture_semantics, details.0) + } + + // add float params + for (index, parameter) in preset.parameters.iter().enumerate() { + uniform_semantics.insert(parameter.name.clone(), UniformSemantic::Variable(SemanticMap { + semantics: VariableSemantics::FloatParameter, + 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 + }); + } + + let semantics = ReflectSemantics { + uniform_semantics, + non_uniform_semantics: texture_semantics + }; + + let mut reflections = Vec::new(); + let mut compiled = Vec::new(); + + for (index, (_, _, reflect)) in passes.iter_mut().enumerate() { + let reflection = reflect.reflect(index as u32, &semantics) + .unwrap(); + let mut options: GlslOptions = Default::default(); + // todo: adjust ogl version + options.version = Version::V4_60; + options.fragment.default_float_precision = Precision::High; + options.fragment.default_int_precision = Precision::High; + options.enable_420_pack_extension = false; + + + let glsl = reflect.compile(&options, &reflection) + .unwrap(); + + eprintln!("{:#}", glsl.vertex); + eprintln!("{:#}", glsl.fragment); + + compiled.push(glsl); + reflections.push(reflection); + + } + + + eprintln!("{:#?}", reflections); + + eprintln!("{:#?}", compiled); + // //todo: add the semantics for other shit (slang_process:68) + // eprintln!("{:?}", preset); + // eprintln!("{:?}", reflect.reflect(&ReflectOptions { + // pass_number: i as u32, + // uniform_semantics, + // non_uniform_semantics: Default::default(), + // })); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn load_preset() { + + load("../test/basic.slangp") + .unwrap(); + } +}