gl: add name mapping to gl compiler

This commit is contained in:
chyyran 2022-11-09 01:11:25 -05:00
parent f1280202e5
commit 301b8bf209
10 changed files with 341 additions and 8 deletions

View file

@ -10,6 +10,7 @@
<sourceFolder url="file://$MODULE_DIR$/naga/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/naga/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/naga/tests" isTestSource="true" /> <sourceFolder url="file://$MODULE_DIR$/naga/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/librashader-runtime-dx11/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/librashader-runtime-dx11/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/librashader-runtime-gl/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />

71
Cargo.lock generated
View file

@ -449,6 +449,20 @@ dependencies = [
"librashader-reflect", "librashader-reflect",
"rustc-hash", "rustc-hash",
"spirv_cross", "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]] [[package]]
@ -1007,6 +1021,63 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 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]] [[package]]
name = "xmlparser" name = "xmlparser"
version = "0.13.5" version = "0.13.5"

View file

@ -5,5 +5,6 @@ members = [
"librashader-preprocess", "librashader-preprocess",
"librashader-reflect", "librashader-reflect",
"librashader-runtime-dx11", "librashader-runtime-dx11",
"librashader-runtime-gl",
"naga" "naga"
] ]

View file

@ -5,7 +5,8 @@ use std::fmt::Debug;
pub use targets::ShaderCompiler; pub use targets::ShaderCompiler;
#[derive(Debug)] #[derive(Debug)]
pub struct CompiledShader<T> { pub struct CompiledShader<Source, Context = ()> {
pub vertex: T, pub vertex: Source,
pub fragment: T, pub fragment: Source,
pub context: Context,
} }

View file

@ -17,6 +17,7 @@ impl OutputTarget for MSL {}
pub trait ShaderCompiler<T: OutputTarget> { pub trait ShaderCompiler<T: OutputTarget> {
type Output; type Output;
type Options; type Options;
type Context = ();
fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result<CompiledShader<Self::Output>, ShaderCompileError>; fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result<CompiledShader<Self::Output, Self::Context>, ShaderCompileError>;
} }

View file

@ -1,4 +1,5 @@
#![feature(let_else)] #![feature(let_else)]
#![feature(associated_type_defaults)]
pub mod error; pub mod error;
pub mod front; pub mod front;

View file

@ -24,6 +24,8 @@ where
} }
pub type HlslReflect = CrossReflect<hlsl::Target>; pub type HlslReflect = CrossReflect<hlsl::Target>;
pub type GlslReflect = CrossReflect<glsl::Target>;
impl ValidateTypeSemantics<Type> for VariableSemantics { impl ValidateTypeSemantics<Type> for VariableSemantics {
fn validate_type(&self, ty: &Type) -> Option<TypeInfo> { fn validate_type(&self, ty: &Type) -> Option<TypeInfo> {
let (Type::Float { ref array, vecsize, columns } | Type::Int { ref array, vecsize, columns } | Type::UInt { ref array, vecsize, columns }) = *ty else { 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<crate::back::targets::GLSL> for CrossReflect<glsl::Target> { impl ShaderCompiler<crate::back::targets::GLSL> for CrossReflect<glsl::Target> {
type Output = String; type Output = String;
type Options = glsl::CompilerOptions; type Options = glsl::CompilerOptions;
type Context = Vec<u32>;
fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result<CompiledShader<Self::Output>, ShaderCompileError> { // todo: compile should consume self
fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result<CompiledShader<Self::Output, Self::Context>, ShaderCompileError> {
self.vertex.set_compiler_options(options)?; self.vertex.set_compiler_options(options)?;
self.fragment.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 { Ok(CompiledShader {
vertex: self.vertex.compile()?, vertex: self.vertex.compile()?,
fragment: self.fragment.compile()? fragment: self.fragment.compile()?,
context: texture_fixups
}) })
} }
} }
@ -812,7 +894,8 @@ impl ShaderCompiler<crate::back::targets::HLSL> for CrossReflect<hlsl::Target> {
Ok(CompiledShader { Ok(CompiledShader {
vertex: self.vertex.compile()?, vertex: self.vertex.compile()?,
fragment: self.fragment.compile()? fragment: self.fragment.compile()?,
context: ()
}) })
} }
} }

View file

@ -12,3 +12,12 @@ edition = "2021"
"librashader-reflect" = { path = "../librashader-reflect" } "librashader-reflect" = { path = "../librashader-reflect" }
spirv_cross = { version = "0.23.1", features = [ "hlsl" ] } spirv_cross = { version = "0.23.1", features = [ "hlsl" ] }
rustc-hash = "1.1.0" rustc-hash = "1.1.0"
[dependencies.windows]
version = "0.43.0"
features = [
"Win32_Foundation",
"Win32_Graphics_Dxgi_Common",
"Win32_Graphics_Direct3D",
"Win32_Graphics_Direct3D11",
]

View file

@ -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",
]

View file

@ -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<String, UniformSemantic>, texture_semantics: &mut FxHashMap<String, SemanticMap<TextureSemantics>>,
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<Path>) -> Result<(), Box<dyn Error>>{
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<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> = 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();
}
}