From 993359115ebd3bb5d04b23d1ac5c52ff045b5f31 Mon Sep 17 00:00:00 2001 From: chyyran Date: Wed, 9 Nov 2022 01:51:10 -0500 Subject: [PATCH] reflect: hide spirv details from consumer --- Cargo.lock | 2 - librashader-reflect/src/back/cross.rs | 1 - librashader-reflect/src/back/mod.rs | 1 + librashader-reflect/src/back/targets.rs | 61 +++++++++-- librashader-reflect/src/reflect/cross.rs | 130 ++++------------------- librashader-reflect/src/reflect/mod.rs | 103 ++++++++++++++++++ librashader-runtime-dx11/Cargo.toml | 1 - librashader-runtime-dx11/src/lib.rs | 10 +- librashader-runtime-gl/Cargo.toml | 1 - librashader-runtime-gl/src/lib.rs | 30 +++--- 10 files changed, 196 insertions(+), 144 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88da746..51f00ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -448,7 +448,6 @@ dependencies = [ "librashader-presets", "librashader-reflect", "rustc-hash", - "spirv_cross", "windows", ] @@ -461,7 +460,6 @@ dependencies = [ "librashader-presets", "librashader-reflect", "rustc-hash", - "spirv_cross", "windows", ] diff --git a/librashader-reflect/src/back/cross.rs b/librashader-reflect/src/back/cross.rs index ef87031..cd0932c 100644 --- a/librashader-reflect/src/back/cross.rs +++ b/librashader-reflect/src/back/cross.rs @@ -2,4 +2,3 @@ use crate::back::ShaderCompiler; use crate::back::targets::GLSL; use crate::error::ShaderCompileError; use crate::reflect::ShaderReflection; - diff --git a/librashader-reflect/src/back/mod.rs b/librashader-reflect/src/back/mod.rs index 7bb1f81..c1e3190 100644 --- a/librashader-reflect/src/back/mod.rs +++ b/librashader-reflect/src/back/mod.rs @@ -10,3 +10,4 @@ pub struct CompiledShader { pub fragment: Source, pub context: Context, } + diff --git a/librashader-reflect/src/back/targets.rs b/librashader-reflect/src/back/targets.rs index 4d9625b..560c440 100644 --- a/librashader-reflect/src/back/targets.rs +++ b/librashader-reflect/src/back/targets.rs @@ -1,11 +1,13 @@ use crate::back::CompiledShader; -use crate::error::ShaderCompileError; -use crate::reflect::ShaderReflection; +use crate::error::{ShaderCompileError, ShaderReflectError}; +use crate::front::shaderc::GlslangCompilation; +use crate::reflect::{ReflectSemantics, ReflectShader, ShaderReflection}; +use crate::reflect::cross::{GlslReflect, HlslReflect}; pub trait OutputTarget { } -pub struct GLSL; -pub struct HLSL; +pub struct GLSL(GlslReflect); +pub struct HLSL(HlslReflect); pub struct SpirV; pub struct MSL; @@ -14,10 +16,55 @@ impl OutputTarget for HLSL {} impl OutputTarget for SpirV {} impl OutputTarget for MSL {} -pub trait ShaderCompiler { +pub trait ShaderCompiler: ReflectShader { type Output; - type Options; + type Options = Option<()>; type Context = (); - fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result, ShaderCompileError>; + fn compile(&mut self, options: Self::Options) -> Result, ShaderCompileError>; +} + +impl ReflectShader for GLSL { + fn reflect(&mut self, pass_number: u32, semantics: &ReflectSemantics) -> Result { + self.0.reflect(pass_number, semantics) + } +} + +impl ShaderCompiler for GLSL { + type Output = String; + type Context = Vec; + fn compile(&mut self, options: Self::Options) -> Result, ShaderCompileError> { + self.0.compile(options) + } +} + +impl TryFrom for GLSL { + type Error = ShaderReflectError; + + fn try_from(value: GlslangCompilation) -> Result { + let value = GlslReflect::try_from(value)?; + Ok(Self(value)) + } +} + +impl ReflectShader for HLSL { + fn reflect(&mut self, pass_number: u32, semantics: &ReflectSemantics) -> Result { + self.0.reflect(pass_number, semantics) + } +} + +impl ShaderCompiler for HLSL { + type Output = String; + fn compile(&mut self, options: Self::Options) -> Result, ShaderCompileError> { + self.0.compile(options) + } +} + +impl TryFrom for HLSL { + type Error = ShaderReflectError; + + fn try_from(value: GlslangCompilation) -> Result { + let value = HlslReflect::try_from(value)?; + Ok(Self(value)) + } } diff --git a/librashader-reflect/src/reflect/cross.rs b/librashader-reflect/src/reflect/cross.rs index 8417e56..6e8418f 100644 --- a/librashader-reflect/src/reflect/cross.rs +++ b/librashader-reflect/src/reflect/cross.rs @@ -5,14 +5,14 @@ use crate::reflect::semantics::{ TextureSemantics, TextureSizeMeta, TypeInfo, UboReflection, ValidateTypeSemantics, VariableMeta, VariableSemantics, MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE, }; -use crate::reflect::{ReflectMeta, ReflectSemantics, ReflectShader, UniformSemantic}; +use crate::reflect::{ReflectMeta, ReflectSemantics, ReflectShader, TextureSemanticMap, UniformSemantic, VariableSemanticMap}; use rustc_hash::FxHashMap; use spirv_cross::hlsl::{ShaderModel}; use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type}; use spirv_cross::{hlsl, ErrorCode, glsl}; use std::str::FromStr; -use spirv_cross::glsl::Version; +use spirv_cross::glsl::{Precision, Version}; use crate::back::{CompiledShader, ShaderCompiler}; pub struct CrossReflect @@ -250,108 +250,6 @@ impl SemanticErrorBlame { } } -trait TextureSemanticMap { - fn get_texture_semantic(&self, name: &str) -> Option>; -} - -trait VariableSemanticMap { - fn get_variable_semantic(&self, name: &str) -> Option>; -} - -impl VariableSemanticMap for FxHashMap { - fn get_variable_semantic(&self, name: &str) -> Option> { - match self.get(name) { - // existing uniforms in the semantic map have priority - None => match name { - "MVP" => Some(SemanticMap { - semantics: VariableSemantics::MVP, - index: 0, - }), - "OutputSize" => Some(SemanticMap { - semantics: VariableSemantics::Output, - index: 0, - }), - "FinalViewportSize" => Some(SemanticMap { - semantics: VariableSemantics::FinalViewport, - index: 0, - }), - "FrameCount" => Some(SemanticMap { - semantics: VariableSemantics::FrameCount, - index: 0, - }), - "FrameDirection" => Some(SemanticMap { - semantics: VariableSemantics::FrameDirection, - index: 0, - }), - _ => None, - }, - Some(UniformSemantic::Variable(variable)) => Some(*variable), - Some(UniformSemantic::Texture(_)) => None, - } - } -} - -impl TextureSemanticMap for FxHashMap { - fn get_texture_semantic(&self, name: &str) -> Option> { - match self.get(name) { - None => { - if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS - .iter() - .find(|f| name.starts_with(f.size_uniform_name())) - { - if semantics.is_array() { - let index = &name[semantics.size_uniform_name().len()..]; - let Ok(index) = u32::from_str(index) else { - return None; - }; - return Some(SemanticMap { - semantics: *semantics, - index, - }); - } else if name == semantics.size_uniform_name() { - return Some(SemanticMap { - semantics: *semantics, - index: 0, - }); - } - } - None - } - Some(UniformSemantic::Variable(_)) => None, - Some(UniformSemantic::Texture(texture)) => Some(*texture), - } - } -} - -impl TextureSemanticMap for FxHashMap> { - fn get_texture_semantic(&self, name: &str) -> Option> { - match self.get(name) { - None => { - if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS - .iter() - .find(|f| name.starts_with(f.texture_name())) - { - if semantics.is_array() { - let index = &name[semantics.texture_name().len()..]; - let Ok(index) = u32::from_str(index) else {return None}; - return Some(SemanticMap { - semantics: *semantics, - index, - }); - } else if name == semantics.texture_name() { - return Some(SemanticMap { - semantics: *semantics, - index: 0, - }); - } - } - None - } - Some(texture) => Some(*texture), - } - } -} - impl CrossReflect where T: spirv_cross::spirv::Target, @@ -791,13 +689,19 @@ pub type GlslOptions = glsl::CompilerOptions; impl ShaderCompiler for CrossReflect { type Output = String; - type Options = glsl::CompilerOptions; type Context = Vec; // 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)?; + fn compile(&mut self, _options: Self::Options) -> Result, ShaderCompileError> { + let mut options: GlslOptions = Default::default(); + // todo: allow 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; + + 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()?; @@ -886,11 +790,13 @@ pub type HlslOptions = hlsl::CompilerOptions; impl ShaderCompiler for CrossReflect { type Output = String; - type Options = hlsl::CompilerOptions; - fn compile(&mut self, options: &Self::Options, reflection: &ShaderReflection) -> Result, ShaderCompileError> { - self.vertex.set_compiler_options(options)?; - self.fragment.set_compiler_options(options)?; + fn compile(&mut self, _options: Self::Options) -> Result, ShaderCompileError> { + let mut options = hlsl::CompilerOptions::default(); + options.shader_model = ShaderModel::V5_0; + + self.vertex.set_compiler_options(&options)?; + self.fragment.set_compiler_options(&options)?; Ok(CompiledShader { vertex: self.vertex.compile()?, diff --git a/librashader-reflect/src/reflect/mod.rs b/librashader-reflect/src/reflect/mod.rs index 607dfa4..e380c50 100644 --- a/librashader-reflect/src/reflect/mod.rs +++ b/librashader-reflect/src/reflect/mod.rs @@ -1,3 +1,4 @@ +use std::str::FromStr; use crate::error::{ShaderReflectError}; use crate::reflect::semantics::{ SemanticMap, TextureImage, TextureSemantics, TextureSizeMeta, VariableMeta, @@ -14,6 +15,108 @@ pub trait ReflectShader { fn reflect(&mut self, pass_number: u32, semantics: &ReflectSemantics) -> Result; } +pub trait TextureSemanticMap { + fn get_texture_semantic(&self, name: &str) -> Option>; +} + +pub trait VariableSemanticMap { + fn get_variable_semantic(&self, name: &str) -> Option>; +} + +impl VariableSemanticMap for FxHashMap { + fn get_variable_semantic(&self, name: &str) -> Option> { + match self.get(name) { + // existing uniforms in the semantic map have priority + None => match name { + "MVP" => Some(SemanticMap { + semantics: VariableSemantics::MVP, + index: 0, + }), + "OutputSize" => Some(SemanticMap { + semantics: VariableSemantics::Output, + index: 0, + }), + "FinalViewportSize" => Some(SemanticMap { + semantics: VariableSemantics::FinalViewport, + index: 0, + }), + "FrameCount" => Some(SemanticMap { + semantics: VariableSemantics::FrameCount, + index: 0, + }), + "FrameDirection" => Some(SemanticMap { + semantics: VariableSemantics::FrameDirection, + index: 0, + }), + _ => None, + }, + Some(UniformSemantic::Variable(variable)) => Some(*variable), + Some(UniformSemantic::Texture(_)) => None, + } + } +} + +impl TextureSemanticMap for FxHashMap { + fn get_texture_semantic(&self, name: &str) -> Option> { + match self.get(name) { + None => { + if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS + .iter() + .find(|f| name.starts_with(f.size_uniform_name())) + { + if semantics.is_array() { + let index = &name[semantics.size_uniform_name().len()..]; + let Ok(index) = u32::from_str(index) else { + return None; + }; + return Some(SemanticMap { + semantics: *semantics, + index, + }); + } else if name == semantics.size_uniform_name() { + return Some(SemanticMap { + semantics: *semantics, + index: 0, + }); + } + } + None + } + Some(UniformSemantic::Variable(_)) => None, + Some(UniformSemantic::Texture(texture)) => Some(*texture), + } + } +} + +impl TextureSemanticMap for FxHashMap> { + fn get_texture_semantic(&self, name: &str) -> Option> { + match self.get(name) { + None => { + if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS + .iter() + .find(|f| name.starts_with(f.texture_name())) + { + if semantics.is_array() { + let index = &name[semantics.texture_name().len()..]; + let Ok(index) = u32::from_str(index) else {return None}; + return Some(SemanticMap { + semantics: *semantics, + index, + }); + } else if name == semantics.texture_name() { + return Some(SemanticMap { + semantics: *semantics, + index: 0, + }); + } + } + None + } + Some(texture) => Some(*texture), + } + } +} + #[derive(Debug)] pub enum UniformSemantic { Variable(SemanticMap), diff --git a/librashader-runtime-dx11/Cargo.toml b/librashader-runtime-dx11/Cargo.toml index b6f3083..f142a3d 100644 --- a/librashader-runtime-dx11/Cargo.toml +++ b/librashader-runtime-dx11/Cargo.toml @@ -10,7 +10,6 @@ edition = "2021" "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] diff --git a/librashader-runtime-dx11/src/lib.rs b/librashader-runtime-dx11/src/lib.rs index f8900df..d0d8524 100644 --- a/librashader-runtime-dx11/src/lib.rs +++ b/librashader-runtime-dx11/src/lib.rs @@ -2,10 +2,10 @@ use std::collections::HashMap; use std::error::Error; use std::path::Path; use rustc_hash::FxHashMap; -use spirv_cross::hlsl::ShaderModel; use librashader::ShaderSource; use librashader_presets::ShaderPassConfig; use librashader_reflect::back::ShaderCompiler; +use librashader_reflect::back::targets::HLSL; use librashader_reflect::front::shaderc::GlslangCompilation; use librashader_reflect::reflect::cross::{CrossReflect, HlslOptions, HlslReflect}; use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, UniformSemantic}; @@ -49,13 +49,13 @@ pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap) -> Result<(), Box>{ let preset = librashader_presets::ShaderPreset::try_parse(path)?; - let mut passes: Vec<(&ShaderPassConfig, ShaderSource, HlslReflect)> = preset.shaders.iter() + let mut passes: Vec<(&ShaderPassConfig, ShaderSource, HLSL)> = 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::HlslReflect::try_from(spirv).unwrap(); + let mut reflect = librashader_reflect::back::targets::HLSL::try_from(spirv).unwrap(); (shader, source, reflect) }).collect(); @@ -94,10 +94,8 @@ pub fn load(path: impl AsRef) -> Result<(), Box>{ for (index, (_, _, reflect)) in passes.iter_mut().enumerate() { let reflection = reflect.reflect(index as u32, &semantics) .unwrap(); - let mut options: HlslOptions = Default::default(); - options.shader_model = ShaderModel::V5_0; - let hlsl = reflect.compile(&options, &reflection) + let hlsl = reflect.compile(None) .unwrap(); eprintln!("{:#}", hlsl.vertex); diff --git a/librashader-runtime-gl/Cargo.toml b/librashader-runtime-gl/Cargo.toml index 276bed2..b1dd4ec 100644 --- a/librashader-runtime-gl/Cargo.toml +++ b/librashader-runtime-gl/Cargo.toml @@ -10,7 +10,6 @@ edition = "2021" "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] diff --git a/librashader-runtime-gl/src/lib.rs b/librashader-runtime-gl/src/lib.rs index 95fc93c..60fca0d 100644 --- a/librashader-runtime-gl/src/lib.rs +++ b/librashader-runtime-gl/src/lib.rs @@ -2,16 +2,16 @@ 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::back::targets::GLSL; 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}; - +use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap}; pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap, texture_semantics: &mut FxHashMap>, config: &ShaderPassConfig) { @@ -50,13 +50,13 @@ pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap) -> Result<(), Box>{ let preset = librashader_presets::ShaderPreset::try_parse(path)?; - let mut passes: Vec<(&ShaderPassConfig, ShaderSource, GlslReflect)> = preset.shaders.iter() + let mut passes: Vec<(&ShaderPassConfig, ShaderSource, GLSL)> = 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(); + let mut reflect = librashader_reflect::back::targets::GLSL::try_from(spirv).unwrap(); (shader, source, reflect) }).collect(); @@ -92,33 +92,35 @@ pub fn load(path: impl AsRef) -> Result<(), Box>{ let mut reflections = Vec::new(); let mut compiled = Vec::new(); - for (index, (_, _, reflect)) in passes.iter_mut().enumerate() { + for (index, (config, source, 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) + let glsl = reflect.compile(None) .unwrap(); eprintln!("{:#}", glsl.vertex); eprintln!("{:#}", glsl.fragment); + // shader_gl3: 1375 + reflection.meta.texture_meta.get(&SemanticMap { + semantics: TextureSemantics::PassOutput, + index: 0 + }).unwrap().binding; + compiled.push(glsl); reflections.push(reflection); } + // todo: build gl semantics + + // shader_gl3:188 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,