reflect: clean up public reflect API a little

This commit is contained in:
chyyran 2022-11-11 01:44:41 -05:00
parent 993359115e
commit 41f721aa6d
13 changed files with 304 additions and 185 deletions

View file

@ -11,6 +11,7 @@
<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" /> <sourceFolder url="file://$MODULE_DIR$/librashader-runtime-gl/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/librashader-compiler/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />

1
Cargo.lock generated
View file

@ -429,7 +429,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"librashader", "librashader",
"librashader-preprocess",
"naga", "naga",
"rspirv", "rspirv",
"rspirv-reflect", "rspirv-reflect",

View file

@ -16,5 +16,5 @@ rustc-hash = "1.1.0"
rspirv = "0.11.0+1.5.4" rspirv = "0.11.0+1.5.4"
rspirv-reflect = { git = "https://github.com/Traverse-Research/rspirv-reflect" } rspirv-reflect = { git = "https://github.com/Traverse-Research/rspirv-reflect" }
[dev-dependencies] [dev-dependencies]
librashader-preprocess = { path = "../librashader-preprocess", default-features = false }

View file

@ -1,4 +1,39 @@
use crate::back::ShaderCompiler; use crate::back::targets::{CompilerBackend, FromCompilation, GLSL, HLSL};
use crate::back::targets::GLSL; use crate::back::CompileShader;
use crate::error::ShaderCompileError; use crate::error::{ShaderCompileError, ShaderReflectError};
use crate::reflect::ShaderReflection; use crate::front::shaderc::GlslangCompilation;
use crate::reflect::cross::{GlslReflect, HlslReflect};
use crate::reflect::{ReflectShader, ShaderReflection};
pub type GlVersion = spirv_cross::glsl::Version;
impl FromCompilation<GlslangCompilation> for GLSL {
type Target = GLSL;
type Options = GlVersion;
fn from_compilation(
compile: GlslangCompilation,
) -> Result<
CompilerBackend<impl CompileShader<Self::Target, Options = Self::Options> + ReflectShader>,
ShaderReflectError,
> {
Ok(CompilerBackend {
backend: GlslReflect::try_from(compile)?,
})
}
}
impl FromCompilation<GlslangCompilation> for HLSL {
type Target = HLSL;
type Options = Option<()>;
fn from_compilation(
compile: GlslangCompilation,
) -> Result<
CompilerBackend<impl CompileShader<Self::Target, Options = Self::Options> + ReflectShader>,
ShaderReflectError,
> {
Ok(CompilerBackend {
backend: HlslReflect::try_from(compile)?,
})
}
}

View file

@ -1,8 +1,11 @@
pub mod cross;
pub mod targets; pub mod targets;
mod cross;
use std::fmt::Debug; use std::fmt::Debug;
pub use targets::ShaderCompiler; use rustc_hash::FxHashMap;
pub use targets::CompileShader;
use crate::reflect::semantics::{SemanticMap, TextureSemantics};
use crate::reflect::UniformSemantic;
#[derive(Debug)] #[derive(Debug)]
pub struct CompiledShader<Source, Context = ()> { pub struct CompiledShader<Source, Context = ()> {
@ -10,4 +13,3 @@ pub struct CompiledShader<Source, Context = ()> {
pub fragment: Source, pub fragment: Source,
pub context: Context, pub context: Context,
} }

View file

@ -1,70 +1,129 @@
use crate::back::CompiledShader; use crate::back::CompiledShader;
use crate::error::{ShaderCompileError, ShaderReflectError}; use crate::error::{ShaderCompileError, ShaderReflectError};
use crate::front::shaderc::GlslangCompilation;
use crate::reflect::{ReflectSemantics, ReflectShader, ShaderReflection}; use crate::reflect::{ReflectSemantics, ReflectShader, ShaderReflection};
use crate::reflect::cross::{GlslReflect, HlslReflect}; use std::marker::PhantomData;
pub trait OutputTarget { } pub trait OutputTarget {
type Output;
type AdditionalContext;
}
pub struct GLSL(GlslReflect); pub struct GLSL;
pub struct HLSL(HlslReflect); pub struct HLSL;
pub struct SpirV; pub struct SpirV;
pub struct MSL; pub struct MSL;
impl OutputTarget for GLSL {} impl OutputTarget for GLSL {
impl OutputTarget for HLSL {}
impl OutputTarget for SpirV {}
impl OutputTarget for MSL {}
pub trait ShaderCompiler<T: OutputTarget>: ReflectShader {
type Output;
type Options = Option<()>;
type Context = ();
fn compile(&mut self, options: Self::Options) -> Result<CompiledShader<Self::Output, Self::Context>, ShaderCompileError>;
}
impl ReflectShader for GLSL {
fn reflect(&mut self, pass_number: u32, semantics: &ReflectSemantics) -> Result<ShaderReflection, ShaderReflectError> {
self.0.reflect(pass_number, semantics)
}
}
impl ShaderCompiler<GLSL> for GLSL {
type Output = String; type Output = String;
type Context = Vec<u32>; type AdditionalContext = Vec<u32>;
fn compile(&mut self, options: Self::Options) -> Result<CompiledShader<Self::Output, Self::Context>, ShaderCompileError> {
self.0.compile(options)
}
} }
impl OutputTarget for HLSL {
impl TryFrom<GlslangCompilation> for GLSL {
type Error = ShaderReflectError;
fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> {
let value = GlslReflect::try_from(value)?;
Ok(Self(value))
}
}
impl ReflectShader for HLSL {
fn reflect(&mut self, pass_number: u32, semantics: &ReflectSemantics) -> Result<ShaderReflection, ShaderReflectError> {
self.0.reflect(pass_number, semantics)
}
}
impl ShaderCompiler<HLSL> for HLSL {
type Output = String; type Output = String;
fn compile(&mut self, options: Self::Options) -> Result<CompiledShader<Self::Output, Self::Context>, ShaderCompileError> { type AdditionalContext = ();
self.0.compile(options) }
impl OutputTarget for SpirV {
type Output = Vec<u32>;
type AdditionalContext = ();
}
pub struct CompilerBackend<T> {
pub(crate) backend: T,
}
pub trait FromCompilation<T> {
type Target: OutputTarget;
type Options;
fn from_compilation(
compile: T,
) -> Result<CompilerBackend<impl CompileShader<Self::Target> + ReflectShader>, ShaderReflectError>;
}
pub trait CompileShader<T: OutputTarget> {
type Options;
fn compile(
&mut self,
options: Self::Options,
) -> Result<CompiledShader<T::Output, T::AdditionalContext>, ShaderCompileError>;
}
impl<T> ReflectShader for CompilerBackend<T>
where
T: ReflectShader,
{
fn reflect(
&mut self,
pass_number: u32,
semantics: &ReflectSemantics,
) -> Result<ShaderReflection, ShaderReflectError> {
self.backend.reflect(pass_number, semantics)
} }
} }
impl TryFrom<GlslangCompilation> for HLSL { impl<T, E> CompileShader<E> for CompilerBackend<T>
type Error = ShaderReflectError; where
T: CompileShader<E>,
E: OutputTarget,
{
type Options = T::Options;
fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> { fn compile(
let value = HlslReflect::try_from(value)?; &mut self,
Ok(Self(value)) options: Self::Options,
) -> Result<CompiledShader<E::Output, E::AdditionalContext>, ShaderCompileError> {
self.backend.compile(options)
} }
} }
mod test {
use crate::back::targets::{CompilerBackend, FromCompilation, GLSL};
use crate::front::shaderc::GlslangCompilation;
pub fn huh(value: GlslangCompilation) {
let x = GLSL::from_compilation(value).unwrap();
}
}
//
// impl ReflectShader for GLSL {
// fn reflect(&mut self, pass_number: u32, semantics: &ReflectSemantics) -> Result<ShaderReflection, ShaderReflectError> {
// self.0.reflect(pass_number, semantics)
// }
// }
//
// impl ShaderCompiler<GLSL> for GLSL {
// type Output = String;
// type Context = Vec<u32>;
// fn compile(&mut self, options: Self::Options) -> Result<CompiledShader<Self::Output, Self::Context>, ShaderCompileError> {
// self.0.compile(options)
// }
// }
//
// impl TryFrom<GlslangCompilation> for GLSL {
// type Error = ShaderReflectError;
//
// fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> {
// let value = GlslReflect::try_from(value)?;
// Ok(Self(value))
// }
// }
//
// impl ReflectShader for HLSL {
// fn reflect(&mut self, pass_number: u32, semantics: &ReflectSemantics) -> Result<ShaderReflection, ShaderReflectError> {
// self.0.reflect(pass_number, semantics)
// }
// }
//
// impl ShaderCompiler<HLSL> for HLSL {
// type Output = String;
// fn compile(&mut self, options: Self::Options) -> Result<CompiledShader<Self::Output, Self::Context>, ShaderCompileError> {
// self.0.compile(options)
// }
// }
//
// impl TryFrom<GlslangCompilation> for HLSL {
// type Error = ShaderReflectError;
//
// fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> {
// let value = HlslReflect::try_from(value)?;
// Ok(Self(value))
// }
// }

View file

@ -1,7 +1,8 @@
#![feature(let_else)] #![feature(let_else)]
#![feature(associated_type_defaults)] #![feature(associated_type_defaults)]
#![feature(return_position_impl_trait_in_trait)]
pub mod back;
pub mod error; pub mod error;
pub mod front; pub mod front;
pub mod reflect; pub mod reflect;
pub mod back;

View file

@ -5,15 +5,18 @@ use crate::reflect::semantics::{
TextureSemantics, TextureSizeMeta, TypeInfo, UboReflection, ValidateTypeSemantics, TextureSemantics, TextureSizeMeta, TypeInfo, UboReflection, ValidateTypeSemantics,
VariableMeta, VariableSemantics, MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE, VariableMeta, VariableSemantics, MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE,
}; };
use crate::reflect::{ReflectMeta, ReflectSemantics, ReflectShader, TextureSemanticMap, UniformSemantic, VariableSemanticMap}; use crate::reflect::{
ReflectMeta, ReflectSemantics, ReflectShader, TextureSemanticMap, UniformSemantic,
VariableSemanticMap,
};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use spirv_cross::hlsl::{ShaderModel}; use spirv_cross::hlsl::ShaderModel;
use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type}; use spirv_cross::spirv::{Ast, Decoration, Module, Resource, ShaderResources, Type};
use spirv_cross::{hlsl, ErrorCode, glsl}; use spirv_cross::{glsl, hlsl, ErrorCode};
use crate::back::targets::{GLSL, HLSL};
use crate::back::{CompileShader, CompiledShader};
use std::str::FromStr; use std::str::FromStr;
use spirv_cross::glsl::{Precision, Version};
use crate::back::{CompiledShader, ShaderCompiler};
pub struct CrossReflect<T> pub struct CrossReflect<T>
where where
@ -23,8 +26,8 @@ where
fragment: Ast<T>, fragment: Ast<T>,
} }
pub type HlslReflect = CrossReflect<hlsl::Target>; pub(crate) type HlslReflect = CrossReflect<hlsl::Target>;
pub type GlslReflect = CrossReflect<glsl::Target>; pub(crate) 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> {
@ -84,7 +87,12 @@ impl ValidateTypeSemantics<Type> for TextureSemantics {
} }
} }
impl TryFrom<GlslangCompilation> for CrossReflect<hlsl::Target> { impl<T> TryFrom<GlslangCompilation> for CrossReflect<T>
where
T: spirv_cross::spirv::Target,
Ast<T>: spirv_cross::spirv::Compile<T>,
Ast<T>: spirv_cross::spirv::Parse<T>,
{
type Error = ShaderReflectError; type Error = ShaderReflectError;
fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> { fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> {
@ -94,30 +102,6 @@ impl TryFrom<GlslangCompilation> for CrossReflect<hlsl::Target> {
let mut vertex = Ast::parse(&vertex_module)?; let mut vertex = Ast::parse(&vertex_module)?;
let mut fragment = Ast::parse(&fragment_module)?; let mut fragment = Ast::parse(&fragment_module)?;
let mut options = hlsl::CompilerOptions::default();
options.shader_model = ShaderModel::V5_0;
fragment.set_compiler_options(&options)?;
vertex.set_compiler_options(&options)?;
Ok(CrossReflect { vertex, fragment })
}
}
impl TryFrom<GlslangCompilation> for CrossReflect<glsl::Target> {
type Error = ShaderReflectError;
fn try_from(value: GlslangCompilation) -> Result<Self, Self::Error> {
let vertex_module = Module::from_words(value.vertex.as_binary());
let fragment_module = Module::from_words(value.fragment.as_binary());
let mut vertex = Ast::parse(&vertex_module)?;
let mut fragment = Ast::parse(&fragment_module)?;
let mut options = glsl::CompilerOptions::default();
options.version = Version::V3_30;
fragment.set_compiler_options(&options)?;
vertex.set_compiler_options(&options)?;
Ok(CrossReflect { vertex, fragment }) Ok(CrossReflect { vertex, fragment })
} }
} }
@ -430,11 +414,13 @@ where
fragment_ubo: Option<&Resource>, fragment_ubo: Option<&Resource>,
) -> Result<Option<UboReflection>, ShaderReflectError> { ) -> Result<Option<UboReflection>, ShaderReflectError> {
if let Some(vertex_ubo) = vertex_ubo { if let Some(vertex_ubo) = vertex_ubo {
self.vertex.set_decoration(vertex_ubo.id, Decoration::Binding, 0)?; self.vertex
.set_decoration(vertex_ubo.id, Decoration::Binding, 0)?;
} }
if let Some(fragment_ubo) = fragment_ubo { if let Some(fragment_ubo) = fragment_ubo {
self.fragment.set_decoration(fragment_ubo.id, Decoration::Binding, 0)?; self.fragment
.set_decoration(fragment_ubo.id, Decoration::Binding, 0)?;
} }
match (vertex_ubo, fragment_ubo) { match (vertex_ubo, fragment_ubo) {
@ -490,9 +476,7 @@ where
return Err(SemanticErrorBlame::Fragment.error(SemanticsErrorKind::UnknownSemantics(texture.name.to_string()))) return Err(SemanticErrorBlame::Fragment.error(SemanticsErrorKind::UnknownSemantics(texture.name.to_string())))
}; };
if semantic.semantics == TextureSemantics::PassOutput if semantic.semantics == TextureSemantics::PassOutput && semantic.index >= pass_number {
&& semantic.index >= pass_number
{
return Err(ShaderReflectError::NonCausalFilterChain { return Err(ShaderReflectError::NonCausalFilterChain {
pass: pass_number, pass: pass_number,
target: semantic.index, target: semantic.index,
@ -542,14 +526,15 @@ where
fragment_pcb: Option<&Resource>, fragment_pcb: Option<&Resource>,
) -> Result<Option<PushReflection>, ShaderReflectError> { ) -> Result<Option<PushReflection>, ShaderReflectError> {
if let Some(vertex_pcb) = vertex_pcb { if let Some(vertex_pcb) = vertex_pcb {
self.vertex.set_decoration(vertex_pcb.id, Decoration::Binding, 1)?; self.vertex
.set_decoration(vertex_pcb.id, Decoration::Binding, 1)?;
} }
if let Some(fragment_pcb) = fragment_pcb { if let Some(fragment_pcb) = fragment_pcb {
self.fragment.set_decoration(fragment_pcb.id, Decoration::Binding, 1)?; self.fragment
.set_decoration(fragment_pcb.id, Decoration::Binding, 1)?;
} }
match (vertex_pcb, fragment_pcb) { match (vertex_pcb, fragment_pcb) {
(None, None) => Ok(None), (None, None) => Ok(None),
(Some(vertex_push), Some(fragment_push)) => { (Some(vertex_push), Some(fragment_push)) => {
@ -597,7 +582,11 @@ where
Ast<T>: spirv_cross::spirv::Compile<T>, Ast<T>: spirv_cross::spirv::Compile<T>,
Ast<T>: spirv_cross::spirv::Parse<T>, Ast<T>: spirv_cross::spirv::Parse<T>,
{ {
fn reflect(&mut self, pass_number: u32, semantics: &ReflectSemantics) -> Result<ShaderReflection, ShaderReflectError> { fn reflect(
&mut self,
pass_number: u32,
semantics: &ReflectSemantics,
) -> Result<ShaderReflection, ShaderReflectError> {
let vertex_res = self.vertex.get_shader_resources()?; let vertex_res = self.vertex.get_shader_resources()?;
let fragment_res = self.fragment.get_shader_resources()?; let fragment_res = self.fragment.get_shader_resources()?;
self.validate(&vertex_res, &fragment_res)?; self.validate(&vertex_res, &fragment_res)?;
@ -685,19 +674,18 @@ where
} }
} }
pub type GlslOptions = glsl::CompilerOptions; impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
type Options = glsl::Version;
impl ShaderCompiler<crate::back::targets::GLSL> for CrossReflect<glsl::Target> {
type Output = String;
type Context = Vec<u32>;
// todo: compile should consume self // todo: compile should consume self
fn compile(&mut self, _options: Self::Options) -> Result<CompiledShader<Self::Output, Self::Context>, ShaderCompileError> { fn compile(
let mut options: GlslOptions = Default::default(); &mut self,
// todo: allow adjust ogl version version: Self::Options,
options.version = Version::V4_60; ) -> Result<CompiledShader<String, Vec<u32>>, ShaderCompileError> {
options.fragment.default_float_precision = Precision::High; let mut options: glsl::CompilerOptions = Default::default();
options.fragment.default_int_precision = Precision::High; options.version = version;
options.fragment.default_float_precision = glsl::Precision::High;
options.fragment.default_int_precision = glsl::Precision::High;
options.enable_420_pack_extension = false; options.enable_420_pack_extension = false;
self.vertex.set_compiler_options(&options)?; self.vertex.set_compiler_options(&options)?;
@ -708,33 +696,46 @@ impl ShaderCompiler<crate::back::targets::GLSL> for CrossReflect<glsl::Target> {
for res in &vertex_resources.stage_inputs { for res in &vertex_resources.stage_inputs {
let location = self.vertex.get_decoration(res.id, Decoration::Location)?; let location = self.vertex.get_decoration(res.id, Decoration::Location)?;
self.vertex.set_name(res.id, &format!("RARCH_ATTRIBUTE_{location}"))?; self.vertex
.set_name(res.id, &format!("RARCH_ATTRIBUTE_{location}"))?;
self.vertex.unset_decoration(res.id, Decoration::Location)?; self.vertex.unset_decoration(res.id, Decoration::Location)?;
} }
for res in &vertex_resources.stage_outputs { for res in &vertex_resources.stage_outputs {
let location = self.vertex.get_decoration(res.id, Decoration::Location)?; let location = self.vertex.get_decoration(res.id, Decoration::Location)?;
self.vertex.set_name(res.id, &format!("RARCH_VARYING_{location}"))?; self.vertex
.set_name(res.id, &format!("RARCH_VARYING_{location}"))?;
self.vertex.unset_decoration(res.id, Decoration::Location)?; self.vertex.unset_decoration(res.id, Decoration::Location)?;
} }
for res in &fragment_resources.stage_inputs { for res in &fragment_resources.stage_inputs {
let location = self.fragment.get_decoration(res.id, Decoration::Location)?; let location = self.fragment.get_decoration(res.id, Decoration::Location)?;
self.fragment.set_name(res.id, &format!("RARCH_VARYING_{location}"))?; self.fragment
self.fragment.unset_decoration(res.id, Decoration::Location)?; .set_name(res.id, &format!("RARCH_VARYING_{location}"))?;
self.fragment
.unset_decoration(res.id, Decoration::Location)?;
} }
if vertex_resources.push_constant_buffers.len() > 1 { if vertex_resources.push_constant_buffers.len() > 1 {
return Err(ShaderCompileError::SpirvCrossCompileError(ErrorCode::CompilationError(String::from("Cannot have more than one push constant buffer")))); return Err(ShaderCompileError::SpirvCrossCompileError(
ErrorCode::CompilationError(String::from(
"Cannot have more than one push constant buffer",
)),
));
} }
for res in &vertex_resources.push_constant_buffers { for res in &vertex_resources.push_constant_buffers {
self.vertex.set_name(res.id, "RARCH_PUSH_VERTEX_INSTANCE")?; self.vertex.set_name(res.id, "RARCH_PUSH_VERTEX_INSTANCE")?;
self.vertex.set_name(res.base_type_id, "RARCH_PUSH_VERTEX")?; self.vertex
.set_name(res.base_type_id, "RARCH_PUSH_VERTEX")?;
} }
// todo: options // todo: options
let flatten = false; let flatten = false;
if vertex_resources.uniform_buffers.len() > 1 { if vertex_resources.uniform_buffers.len() > 1 {
return Err(ShaderCompileError::SpirvCrossCompileError(ErrorCode::CompilationError(String::from("Cannot have more than one uniform buffer")))); return Err(ShaderCompileError::SpirvCrossCompileError(
ErrorCode::CompilationError(String::from(
"Cannot have more than one uniform buffer",
)),
));
} }
for res in &vertex_resources.uniform_buffers { for res in &vertex_resources.uniform_buffers {
if flatten { if flatten {
@ -742,56 +743,74 @@ impl ShaderCompiler<crate::back::targets::GLSL> for CrossReflect<glsl::Target> {
} }
self.vertex.set_name(res.id, "RARCH_UBO_VERTEX_INSTANCE")?; 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.base_type_id, "RARCH_UBO_VERTEX")?;
self.vertex.unset_decoration(res.id, Decoration::DescriptorSet)?; self.vertex
.unset_decoration(res.id, Decoration::DescriptorSet)?;
self.vertex.unset_decoration(res.id, Decoration::Binding)?; self.vertex.unset_decoration(res.id, Decoration::Binding)?;
} }
if fragment_resources.push_constant_buffers.len() > 1 { if fragment_resources.push_constant_buffers.len() > 1 {
return Err(ShaderCompileError::SpirvCrossCompileError(ErrorCode::CompilationError(String::from("Cannot have more than one push constant buffer")))); return Err(ShaderCompileError::SpirvCrossCompileError(
ErrorCode::CompilationError(String::from(
"Cannot have more than one push constant buffer",
)),
));
} }
for res in &fragment_resources.push_constant_buffers { for res in &fragment_resources.push_constant_buffers {
self.fragment.set_name(res.id, "RARCH_PUSH_FRAGMENT_INSTANCE")?; self.fragment
self.fragment.set_name(res.base_type_id, "RARCH_PUSH_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 { if fragment_resources.uniform_buffers.len() > 1 {
return Err(ShaderCompileError::SpirvCrossCompileError(ErrorCode::CompilationError(String::from("Cannot have more than one uniform buffer")))); return Err(ShaderCompileError::SpirvCrossCompileError(
ErrorCode::CompilationError(String::from(
"Cannot have more than one uniform buffer",
)),
));
} }
for res in &fragment_resources.uniform_buffers { for res in &fragment_resources.uniform_buffers {
if flatten { if flatten {
self.fragment.flatten_buffer_block(res.id)?; self.fragment.flatten_buffer_block(res.id)?;
} }
self.fragment.set_name(res.id, "RARCH_UBO_FRAGMENT_INSTANCE")?; self.fragment
self.fragment.set_name(res.base_type_id, "RARCH_UBO_FRAGMENT")?; .set_name(res.id, "RARCH_UBO_FRAGMENT_INSTANCE")?;
self.fragment.unset_decoration(res.id, Decoration::DescriptorSet)?; self.fragment
self.fragment.unset_decoration(res.id, Decoration::Binding)?; .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(); let mut texture_fixups = Vec::new();
for res in &fragment_resources.sampled_images { for res in &fragment_resources.sampled_images {
let binding = self.fragment.get_decoration(res.id, Decoration::Binding)?; let binding = self.fragment.get_decoration(res.id, Decoration::Binding)?;
self.fragment.set_name(res.id, &format!("RARCH_TEXTURE_{binding}"))?; self.fragment
self.fragment.unset_decoration(res.id, Decoration::DescriptorSet)?; .set_name(res.id, &format!("RARCH_TEXTURE_{binding}"))?;
self.fragment.unset_decoration(res.id, Decoration::Binding)?; self.fragment
.unset_decoration(res.id, Decoration::DescriptorSet)?;
self.fragment
.unset_decoration(res.id, Decoration::Binding)?;
texture_fixups.push(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 context: texture_fixups,
}) })
} }
} }
pub type HlslOptions = hlsl::CompilerOptions; impl CompileShader<HLSL> for CrossReflect<hlsl::Target> {
type Options = Option<()>;
impl ShaderCompiler<crate::back::targets::HLSL> for CrossReflect<hlsl::Target> { fn compile(
type Output = String; &mut self,
_options: Self::Options,
fn compile(&mut self, _options: Self::Options) -> Result<CompiledShader<Self::Output>, ShaderCompileError> { ) -> Result<CompiledShader<String>, ShaderCompileError> {
let mut options = hlsl::CompilerOptions::default(); let mut options = hlsl::CompilerOptions::default();
options.shader_model = ShaderModel::V5_0; options.shader_model = ShaderModel::V5_0;
@ -801,22 +820,21 @@ 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: () context: (),
}) })
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use rustc_hash::FxHashMap;
use crate::reflect::cross::CrossReflect; use crate::reflect::cross::CrossReflect;
use crate::reflect::{ReflectSemantics, ReflectShader, UniformSemantic}; use crate::reflect::{ReflectSemantics, ReflectShader, UniformSemantic};
use rustc_hash::FxHashMap;
use spirv_cross::{glsl, hlsl}; use crate::back::CompileShader;
use spirv_cross::glsl::{CompilerOptions, Version};
use crate::back::ShaderCompiler;
use crate::reflect::semantics::{SemanticMap, VariableSemantics}; use crate::reflect::semantics::{SemanticMap, VariableSemantics};
use spirv_cross::glsl::{CompilerOptions, Version};
use spirv_cross::{glsl, hlsl};
#[test] #[test]
pub fn test_into() { pub fn test_into() {
@ -824,24 +842,29 @@ mod test {
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default(); let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
for (index, param) in result.parameters.iter().enumerate() { for (index, param) in result.parameters.iter().enumerate() {
uniform_semantics.insert(param.id.clone(), UniformSemantic::Variable(SemanticMap { uniform_semantics.insert(
semantics: VariableSemantics::FloatParameter, param.id.clone(),
index: index as u32 UniformSemantic::Variable(SemanticMap {
})); semantics: VariableSemantics::FloatParameter,
index: index as u32,
}),
);
} }
let spirv = crate::front::shaderc::compile_spirv(&result).unwrap(); let spirv = crate::front::shaderc::compile_spirv(&result).unwrap();
let mut reflect = CrossReflect::<glsl::Target>::try_from(spirv).unwrap(); let mut reflect = CrossReflect::<glsl::Target>::try_from(spirv).unwrap();
let shader_reflection = reflect let shader_reflection = reflect
.reflect(0, &ReflectSemantics { .reflect(
uniform_semantics, 0,
non_uniform_semantics: Default::default(), &ReflectSemantics {
}) uniform_semantics,
non_uniform_semantics: Default::default(),
},
)
.unwrap(); .unwrap();
let mut opts = CompilerOptions::default(); let mut opts = CompilerOptions::default();
opts.version = Version::V4_60; opts.version = Version::V4_60;
opts.enable_420_pack_extension = false; opts.enable_420_pack_extension = false;
let compiled = reflect.compile(&opts, &shader_reflection) let compiled = reflect.compile(&opts, &shader_reflection).unwrap();
.unwrap();
// eprintln!("{shader_reflection:#?}"); // eprintln!("{shader_reflection:#?}");
eprintln!("{:#}", compiled.fragment) eprintln!("{:#}", compiled.fragment)
// let mut loader = rspirv::dr::Loader::new(); // let mut loader = rspirv::dr::Loader::new();

View file

@ -1,10 +1,9 @@
use std::str::FromStr; use crate::error::ShaderReflectError;
use crate::error::{ShaderReflectError};
use crate::reflect::semantics::{ use crate::reflect::semantics::{
SemanticMap, TextureImage, TextureSemantics, TextureSizeMeta, VariableMeta, SemanticMap, TextureImage, TextureSemantics, TextureSizeMeta, VariableMeta, VariableSemantics,
VariableSemantics,
}; };
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::str::FromStr;
pub mod cross; pub mod cross;
mod naga; mod naga;
@ -12,7 +11,11 @@ mod rspirv;
pub mod semantics; pub mod semantics;
pub trait ReflectShader { pub trait ReflectShader {
fn reflect(&mut self, pass_number: u32, semantics: &ReflectSemantics) -> Result<ShaderReflection, ShaderReflectError>; fn reflect(
&mut self,
pass_number: u32,
semantics: &ReflectSemantics,
) -> Result<ShaderReflection, ShaderReflectError>;
} }
pub trait TextureSemanticMap<T> { pub trait TextureSemanticMap<T> {

View file

@ -39,9 +39,6 @@ impl TryFrom<GlslangCompilation> for NagaReflect {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
#[test] #[test]
pub fn test_into() { pub fn test_into() {
let result = librashader_preprocess::load_shader_source("../test/basic.slang").unwrap(); let result = librashader_preprocess::load_shader_source("../test/basic.slang").unwrap();

View file

@ -1,4 +1,3 @@
use crate::reflect::ReflectMeta; use crate::reflect::ReflectMeta;
use bitflags::bitflags; use bitflags::bitflags;
@ -143,4 +142,3 @@ pub struct ShaderReflection {
pub push_constant: Option<PushReflection>, pub push_constant: Option<PushReflection>,
pub meta: ReflectMeta, pub meta: ReflectMeta,
} }

View file

@ -4,10 +4,10 @@ use std::path::Path;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use librashader::ShaderSource; use librashader::ShaderSource;
use librashader_presets::ShaderPassConfig; use librashader_presets::ShaderPassConfig;
use librashader_reflect::back::ShaderCompiler; use librashader_reflect::back::{CompileShader, ShaderCompiler};
use librashader_reflect::back::targets::HLSL; use librashader_reflect::back::targets::{FromCompilation, HLSL};
use librashader_reflect::front::shaderc::GlslangCompilation; use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::cross::{CrossReflect, HlslOptions, HlslReflect}; use librashader_reflect::reflect::cross::{CrossReflect};
use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, UniformSemantic}; use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, UniformSemantic};
use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, VariableSemantics}; use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, VariableSemantics};
@ -49,13 +49,13 @@ pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap<String, UniformSema
pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{ pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{
let preset = librashader_presets::ShaderPreset::try_parse(path)?; let preset = librashader_presets::ShaderPreset::try_parse(path)?;
let mut passes: Vec<(&ShaderPassConfig, ShaderSource, HLSL)> = preset.shaders.iter() let mut passes: Vec<(&ShaderPassConfig, ShaderSource, _)> = preset.shaders.iter()
.map(|shader| { .map(|shader| {
let source = librashader_preprocess::load_shader_source(&shader.name) let source = librashader_preprocess::load_shader_source(&shader.name)
.unwrap(); .unwrap();
let spirv = librashader_reflect::front::shaderc::compile_spirv(&source) let spirv = librashader_reflect::front::shaderc::compile_spirv(&source)
.unwrap(); .unwrap();
let mut reflect = librashader_reflect::back::targets::HLSL::try_from(spirv).unwrap(); let mut reflect = HLSL::from_compilation(spirv).unwrap();
(shader, source, reflect) (shader, source, reflect)
}).collect(); }).collect();

View file

@ -5,10 +5,11 @@ use rustc_hash::FxHashMap;
use librashader::ShaderSource; use librashader::ShaderSource;
use librashader_presets::ShaderPassConfig; use librashader_presets::ShaderPassConfig;
use librashader_reflect::back::ShaderCompiler; use librashader_reflect::back::CompileShader;
use librashader_reflect::back::targets::GLSL; use librashader_reflect::back::cross::GlVersion;
use librashader_reflect::back::targets::{FromCompilation, GLSL};
use librashader_reflect::front::shaderc::GlslangCompilation; use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::cross::{CrossReflect, GlslOptions, GlslReflect, HlslOptions, HlslReflect}; use librashader_reflect::reflect::cross::CrossReflect;
use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, UniformSemantic}; use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, UniformSemantic};
use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, VariableSemantics}; use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, VariableSemantics};
use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap}; use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap};
@ -50,13 +51,13 @@ pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap<String, UniformSema
pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{ pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{
let preset = librashader_presets::ShaderPreset::try_parse(path)?; let preset = librashader_presets::ShaderPreset::try_parse(path)?;
let mut passes: Vec<(&ShaderPassConfig, ShaderSource, GLSL)> = preset.shaders.iter() let mut passes: Vec<(&ShaderPassConfig, ShaderSource, _)> = preset.shaders.iter()
.map(|shader| { .map(|shader| {
let source = librashader_preprocess::load_shader_source(&shader.name) let source = librashader_preprocess::load_shader_source(&shader.name)
.unwrap(); .unwrap();
let spirv = librashader_reflect::front::shaderc::compile_spirv(&source) let spirv = librashader_reflect::front::shaderc::compile_spirv(&source)
.unwrap(); .unwrap();
let mut reflect = librashader_reflect::back::targets::GLSL::try_from(spirv).unwrap(); let mut reflect = GLSL::from_compilation(spirv).unwrap();
(shader, source, reflect) (shader, source, reflect)
}).collect(); }).collect();
@ -97,17 +98,17 @@ pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{
.unwrap(); .unwrap();
let glsl = reflect.compile(None) let glsl = reflect.compile(GlVersion::V4_60)
.unwrap(); .unwrap();
eprintln!("{:#}", glsl.vertex); eprintln!("{:#}", glsl.vertex);
eprintln!("{:#}", glsl.fragment); eprintln!("{:#}", glsl.fragment);
// shader_gl3: 1375 // shader_gl3: 1375
reflection.meta.texture_meta.get(&SemanticMap { // reflection.meta.texture_meta.get(&SemanticMap {
semantics: TextureSemantics::PassOutput, // semantics: TextureSemantics::PassOutput,
index: 0 // index: 0
}).unwrap().binding; // }).unwrap().binding;
compiled.push(glsl); compiled.push(glsl);
reflections.push(reflection); reflections.push(reflection);