reflect: document and rename some structs

This commit is contained in:
chyyran 2022-12-01 01:50:16 -05:00
parent 5d668a2233
commit e804ffd310
17 changed files with 356 additions and 219 deletions

1
.gitignore vendored
View file

@ -5,3 +5,4 @@
*.rdc *.rdc
*.cap *.cap
/.vs/ /.vs/
librashader_runtime_*.exe

View file

@ -5,17 +5,22 @@ use crate::front::shaderc::GlslangCompilation;
use crate::reflect::cross::{CompiledProgram, GlslReflect, HlslReflect}; use crate::reflect::cross::{CompiledProgram, GlslReflect, HlslReflect};
use crate::reflect::ReflectShader; use crate::reflect::ReflectShader;
pub type GlVersion = spirv_cross::glsl::Version; /// The GLSL version to use.
pub struct GlslangGlslContext { pub type GlslVersion = spirv_cross::glsl::Version;
/// The context for a GLSL compilation via spirv-cross.
pub struct CrossGlslContext {
/// A map of bindings of sampler names to binding locations.
pub sampler_bindings: Vec<(String, u32)>, pub sampler_bindings: Vec<(String, u32)>,
pub compiler: CompiledProgram<spirv_cross::glsl::Target>, /// The compiled program artifact after compilation.
pub artifact: CompiledProgram<spirv_cross::glsl::Target>,
} }
impl FromCompilation<GlslangCompilation> for GLSL { impl FromCompilation<GlslangCompilation> for GLSL {
type Target = GLSL; type Target = GLSL;
type Options = GlVersion; type Options = GlslVersion;
type Context = GlslangGlslContext; type Context = CrossGlslContext;
type Output = impl CompileShader<Self::Target, Options = GlVersion, Context = GlslangGlslContext> type Output = impl CompileShader<Self::Target, Options = GlslVersion, Context = CrossGlslContext>
+ ReflectShader; + ReflectShader;
fn from_compilation( fn from_compilation(
@ -27,14 +32,15 @@ impl FromCompilation<GlslangCompilation> for GLSL {
} }
} }
pub struct GlslangHlslContext { /// The context for a HLSL compilation via spirv-cross.
pub struct CrossHlslContext {
pub compiler: CompiledProgram<spirv_cross::hlsl::Target>, pub compiler: CompiledProgram<spirv_cross::hlsl::Target>,
} }
impl FromCompilation<GlslangCompilation> for HLSL { impl FromCompilation<GlslangCompilation> for HLSL {
type Target = HLSL; type Target = HLSL;
type Options = Option<()>; type Options = Option<()>;
type Context = GlslangHlslContext; type Context = CrossHlslContext;
type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context> type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context>
+ ReflectShader; + ReflectShader;

View file

@ -3,21 +3,29 @@ pub mod targets;
use crate::back::targets::OutputTarget; use crate::back::targets::OutputTarget;
use crate::error::{ShaderCompileError, ShaderReflectError}; use crate::error::{ShaderCompileError, ShaderReflectError};
use crate::reflect::semantics::ReflectSemantics; use crate::reflect::semantics::ShaderSemantics;
use crate::reflect::{ReflectShader, ShaderReflection}; use crate::reflect::{ReflectShader, ShaderReflection};
use std::fmt::Debug; use std::fmt::Debug;
/// The output of the shader compiler.
#[derive(Debug)] #[derive(Debug)]
pub struct ShaderCompilerOutput<T, Context = ()> { pub struct ShaderCompilerOutput<T, Context = ()> {
/// The output for the vertex shader.
pub vertex: T, pub vertex: T,
/// The output for the fragment shader.
pub fragment: T, pub fragment: T,
/// Additional context provided by the shader compiler.
pub context: Context, pub context: Context,
} }
/// A trait for objects that can be compiled into a shader.
pub trait CompileShader<T: OutputTarget> { pub trait CompileShader<T: OutputTarget> {
/// Options provided to the compiler.
type Options; type Options;
/// Additional context returned by the compiler after compilation.
type Context; type Context;
/// Consume the object and return the compiled output of the shader.
fn compile( fn compile(
self, self,
options: Self::Options, options: Self::Options,
@ -40,17 +48,24 @@ where
} }
} }
/// A trait for reflectable compilations that can be transformed into an object ready for reflection or compilation.
pub trait FromCompilation<T> { pub trait FromCompilation<T> {
/// The target that the transformed object is expected to compile for.
type Target: OutputTarget; type Target: OutputTarget;
/// Options provided to the compiler.
type Options; type Options;
/// Additional context returned by the compiler after compilation.
type Context; type Context;
/// The output type after conversion.
type Output: CompileShader<Self::Target, Context = Self::Context, Options = Self::Options> type Output: CompileShader<Self::Target, Context = Self::Context, Options = Self::Options>
+ ReflectShader; + ReflectShader;
/// Tries to convert the input object into an object ready for compilation.
fn from_compilation(compile: T) -> Result<CompilerBackend<Self::Output>, ShaderReflectError>; fn from_compilation(compile: T) -> Result<CompilerBackend<Self::Output>, ShaderReflectError>;
} }
/// A wrapper for a compiler backend.
pub struct CompilerBackend<T> { pub struct CompilerBackend<T> {
pub(crate) backend: T, pub(crate) backend: T,
} }
@ -62,7 +77,7 @@ where
fn reflect( fn reflect(
&mut self, &mut self,
pass_number: usize, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ShaderSemantics,
) -> Result<ShaderReflection, ShaderReflectError> { ) -> Result<ShaderReflection, ShaderReflectError> {
self.backend.reflect(pass_number, semantics) self.backend.reflect(pass_number, semantics)
} }

View file

@ -1,10 +1,16 @@
/// Marker trait for shader compiler targets.
pub trait OutputTarget { pub trait OutputTarget {
/// The output format for the target.
type Output; type Output;
} }
/// Shader compiler target for GLSL.
pub struct GLSL; pub struct GLSL;
/// Shader compiler target for HLSL.
pub struct HLSL; pub struct HLSL;
/// Shader compiler target for SPIR-V.
pub struct SPIRV; pub struct SPIRV;
/// Shader compiler target for MSL
pub struct MSL; pub struct MSL;
impl OutputTarget for GLSL { impl OutputTarget for GLSL {

View file

@ -1,69 +1,100 @@
use crate::reflect::semantics::MemberOffset; use crate::reflect::semantics::MemberOffset;
use thiserror::Error; use thiserror::Error;
/// Error type for shader compilation.
#[non_exhaustive] #[non_exhaustive]
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum ShaderCompileError { pub enum ShaderCompileError {
/// Compile error from naga.
#[cfg(feature = "unstable-rust-pipeline")] #[cfg(feature = "unstable-rust-pipeline")]
#[error("shader")] #[error("shader")]
NagaCompileError(Vec<naga::front::glsl::Error>), NagaCompileError(Vec<naga::front::glsl::Error>),
/// Compilation error from shaderc (glslang).
#[error("shaderc")] #[error("shaderc")]
ShaderCCompileError(#[from] shaderc::Error), ShaderCCompileError(#[from] shaderc::Error),
/// Error when initializing the shaderc compiler.
#[error("shaderc init")] #[error("shaderc init")]
ShaderCInitError, ShaderCInitError,
/// Error when transpiling from spirv-cross.
#[error("cross")] #[error("cross")]
SpirvCrossCompileError(#[from] spirv_cross::ErrorCode), SpirvCrossCompileError(#[from] spirv_cross::ErrorCode),
} }
/// The error kind encountered when reflecting shader semantics.
#[derive(Debug)] #[derive(Debug)]
pub enum SemanticsErrorKind { pub enum SemanticsErrorKind {
/// The number of uniform buffers was invalid. Only one UBO is permitted.
InvalidUniformBufferCount(usize), InvalidUniformBufferCount(usize),
/// The number of push constant blocks was invalid. Only one push constant block is permitted.
InvalidPushBufferSize(u32), InvalidPushBufferSize(u32),
/// The location of a varying was invalid.
InvalidLocation(u32), InvalidLocation(u32),
/// The requested descriptor set was invalid. Only descriptor set 0 is available.
InvalidDescriptorSet(u32), InvalidDescriptorSet(u32),
/// The number of inputs to the shader was invalid.
InvalidInputCount(usize), InvalidInputCount(usize),
/// The number of outputs declared was invalid.
InvalidOutputCount(usize), InvalidOutputCount(usize),
/// The declared binding point was invalid.
InvalidBinding(u32), InvalidBinding(u32),
/// The declared resource type was invalid.
InvalidResourceType, InvalidResourceType,
/// The range of a struct member was invalid.
InvalidRange(u32), InvalidRange(u32),
/// The requested uniform or texture name was not provided semantics.
UnknownSemantics(String), UnknownSemantics(String),
/// The type of the requested uniform was not compatible with the provided semantics.
InvalidTypeForSemantic(String), InvalidTypeForSemantic(String),
} }
/// Error type for shader reflection.
#[non_exhaustive] #[non_exhaustive]
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum ShaderReflectError { pub enum ShaderReflectError {
/// Compile error from naga.
#[cfg(feature = "unstable-rust-pipeline")] #[cfg(feature = "unstable-rust-pipeline")]
#[error("shader")] #[error("shader")]
NagaCompileError(#[from] naga::front::spv::Error), NagaCompileError(#[from] naga::front::spv::Error),
/// Parse error from rspirv.
#[cfg(feature = "unstable-rust-pipeline")] #[cfg(feature = "unstable-rust-pipeline")]
#[error("rspirv")] #[error("rspirv")]
RspirvParseError(#[from] rspirv::binary::ParseState), RspirvParseError(#[from] rspirv::binary::ParseState),
/// Reflection error from spirv-cross.
#[error("spirv")] #[error("spirv")]
SpirvCrossError(#[from] spirv_cross::ErrorCode), SpirvCrossError(#[from] spirv_cross::ErrorCode),
/// Error when validating vertex shader semantics.
#[error("error when verifying vertex semantics")] #[error("error when verifying vertex semantics")]
VertexSemanticError(SemanticsErrorKind), VertexSemanticError(SemanticsErrorKind),
/// Error when validating fragment shader semantics.
#[error("error when verifying texture semantics")] #[error("error when verifying texture semantics")]
FragmentSemanticError(SemanticsErrorKind), FragmentSemanticError(SemanticsErrorKind),
#[error("vertx and fragment shader must have same binding")] /// The vertex and fragment shader must have the same UBO binding location.
#[error("vertex and fragment shader must have same binding")]
MismatchedUniformBuffer { vertex: u32, fragment: u32 }, MismatchedUniformBuffer { vertex: u32, fragment: u32 },
/// The filter chain was found to be non causal. A pass tried to access the target output
/// in the future.
#[error("filter chain is non causal")] #[error("filter chain is non causal")]
NonCausalFilterChain { pass: usize, target: usize }, NonCausalFilterChain { pass: usize, target: usize },
/// The offset of the given uniform did not match up in both the vertex and fragment shader.
#[error("mismatched offset")] #[error("mismatched offset")]
MismatchedOffset { MismatchedOffset {
semantic: String, semantic: String,
vertex: MemberOffset, vertex: MemberOffset,
fragment: MemberOffset, fragment: MemberOffset,
}, },
/// The size of the given uniform did not match up in both the vertex and fragment shader.
#[error("mismatched component")] #[error("mismatched component")]
MismatchedComponent { MismatchedSize {
semantic: String, semantic: String,
vertex: u32, vertex: u32,
fragment: u32, fragment: u32,
}, },
/// The binding number is already in use.
#[error("the binding is already in use")] #[error("the binding is already in use")]
BindingInUse(u32), BindingInUse(u32),
} }

View file

@ -3,6 +3,7 @@ use librashader_preprocess::ShaderSource;
use naga::front::glsl::{Options, Parser}; use naga::front::glsl::{Options, Parser};
use naga::{Module, ShaderStage}; use naga::{Module, ShaderStage};
/// A reflectable shader compilation via naga.
#[derive(Debug)] #[derive(Debug)]
pub struct NagaCompilation { pub struct NagaCompilation {
pub(crate) vertex: Module, pub(crate) vertex: Module,

View file

@ -2,6 +2,7 @@ use crate::error::ShaderCompileError;
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use shaderc::{CompilationArtifact, CompileOptions, Limit, ShaderKind}; use shaderc::{CompilationArtifact, CompileOptions, Limit, ShaderKind};
/// A reflectable shader compilation via glslang (shaderc).
pub struct GlslangCompilation { pub struct GlslangCompilation {
pub(crate) vertex: CompilationArtifact, pub(crate) vertex: CompilationArtifact,
pub(crate) fragment: CompilationArtifact, pub(crate) fragment: CompilationArtifact,

View file

@ -1,19 +1,14 @@
use crate::error::{SemanticsErrorKind, ShaderCompileError, ShaderReflectError}; use crate::error::{SemanticsErrorKind, ShaderCompileError, ShaderReflectError};
use crate::front::shaderc::GlslangCompilation; use crate::front::shaderc::GlslangCompilation;
use crate::reflect::semantics::{ use crate::reflect::semantics::{BindingStage, MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE, MemberOffset, PushReflection, BindingMeta, ShaderSemantics, ShaderReflection, TextureBinding, TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo, UboReflection, UniqueSemantics, ValidateTypeSemantics, VariableMeta, UniqueSemanticMap};
BindingStage, MemberOffset, PushReflection, ReflectSemantics, ShaderReflection, TextureBinding, use crate::reflect::{align_uniform_size, ReflectShader};
TextureSemanticMap, TextureSemantics, TextureSizeMeta, TypeInfo, UboReflection,
ValidateTypeSemantics, VariableMeta, VariableSemanticMap, VariableSemantics,
MAX_BINDINGS_COUNT, MAX_PUSH_BUFFER_SIZE,
};
use crate::reflect::{align_uniform_size, ReflectMeta, ReflectShader};
use std::ops::Deref; use std::ops::Deref;
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::{glsl, hlsl, ErrorCode}; use spirv_cross::{ErrorCode, glsl, hlsl};
use crate::back::cross::{GlslangGlslContext, GlslangHlslContext}; use crate::back::cross::{CrossGlslContext, CrossHlslContext};
use crate::back::targets::{GLSL, HLSL}; use crate::back::targets::{GLSL, HLSL};
use crate::back::{CompileShader, ShaderCompilerOutput}; use crate::back::{CompileShader, ShaderCompilerOutput};
@ -49,7 +44,7 @@ where
pub(crate) type HlslReflect = CrossReflect<hlsl::Target>; pub(crate) type HlslReflect = CrossReflect<hlsl::Target>;
pub(crate) type GlslReflect = CrossReflect<glsl::Target>; pub(crate) type GlslReflect = CrossReflect<glsl::Target>;
impl ValidateTypeSemantics<Type> for VariableSemantics { impl ValidateTypeSemantics<Type> for UniqueSemantics {
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 {
return None return None
@ -60,16 +55,16 @@ impl ValidateTypeSemantics<Type> for VariableSemantics {
} }
let valid = match self { let valid = match self {
VariableSemantics::MVP => { UniqueSemantics::MVP => {
matches!(ty, Type::Float { .. }) && vecsize == 4 && columns == 4 matches!(ty, Type::Float { .. }) && vecsize == 4 && columns == 4
} }
VariableSemantics::FrameCount => { UniqueSemantics::FrameCount => {
matches!(ty, Type::UInt { .. }) && vecsize == 1 && columns == 1 matches!(ty, Type::UInt { .. }) && vecsize == 1 && columns == 1
} }
VariableSemantics::FrameDirection => { UniqueSemantics::FrameDirection => {
matches!(ty, Type::Int { .. }) && vecsize == 1 && columns == 1 matches!(ty, Type::Int { .. }) && vecsize == 1 && columns == 1
} }
VariableSemantics::FloatParameter => { UniqueSemantics::FloatParameter => {
matches!(ty, Type::Float { .. }) && vecsize == 1 && columns == 1 matches!(ty, Type::Float { .. }) && vecsize == 1 && columns == 1
} }
_ => matches!(ty, Type::Float { .. }) && vecsize == 4 && columns == 1, _ => matches!(ty, Type::Float { .. }) && vecsize == 4 && columns == 1,
@ -299,8 +294,8 @@ where
ast: &Ast<T>, ast: &Ast<T>,
resource: &Resource, resource: &Resource,
pass_number: usize, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ShaderSemantics,
meta: &mut ReflectMeta, meta: &mut BindingMeta,
offset_type: impl Fn(usize) -> MemberOffset, offset_type: impl Fn(usize) -> MemberOffset,
blame: SemanticErrorBlame, blame: SemanticErrorBlame,
) -> Result<(), ShaderReflectError> { ) -> Result<(), ShaderReflectError> {
@ -319,13 +314,13 @@ where
_ => return Err(blame.error(SemanticsErrorKind::InvalidResourceType)), _ => return Err(blame.error(SemanticsErrorKind::InvalidResourceType)),
}; };
if let Some(parameter) = semantics.uniform_semantics.get_variable_semantic(&name) { if let Some(parameter) = semantics.uniform_semantics.get_unique_semantic(&name) {
let Some(typeinfo) = parameter.semantics.validate_type(&range_type) else { let Some(typeinfo) = parameter.semantics.validate_type(&range_type) else {
return Err(blame.error(SemanticsErrorKind::InvalidTypeForSemantic(name))) return Err(blame.error(SemanticsErrorKind::InvalidTypeForSemantic(name)))
}; };
match &parameter.semantics { match &parameter.semantics {
VariableSemantics::FloatParameter => { UniqueSemantics::FloatParameter => {
let offset = offset_type(range.offset); let offset = offset_type(range.offset);
if let Some(meta) = meta.parameter_meta.get(&name) { if let Some(meta) = meta.parameter_meta.get(&name) {
if offset != meta.offset { if offset != meta.offset {
@ -335,10 +330,10 @@ where
fragment: offset, fragment: offset,
}); });
} }
if meta.components != typeinfo.size { if meta.size != typeinfo.size {
return Err(ShaderReflectError::MismatchedComponent { return Err(ShaderReflectError::MismatchedSize {
semantic: name, semantic: name,
vertex: meta.components, vertex: meta.size,
fragment: typeinfo.size, fragment: typeinfo.size,
}); });
} }
@ -348,14 +343,14 @@ where
VariableMeta { VariableMeta {
id: name, id: name,
offset, offset,
components: typeinfo.size, size: typeinfo.size,
}, },
); );
} }
} }
semantics => { semantics => {
let offset = offset_type(range.offset); let offset = offset_type(range.offset);
if let Some(meta) = meta.variable_meta.get(semantics) { if let Some(meta) = meta.unique_meta.get(semantics) {
if offset != meta.offset { if offset != meta.offset {
return Err(ShaderReflectError::MismatchedOffset { return Err(ShaderReflectError::MismatchedOffset {
semantic: name, semantic: name,
@ -363,20 +358,20 @@ where
fragment: offset, fragment: offset,
}); });
} }
if meta.components != typeinfo.size * typeinfo.columns { if meta.size != typeinfo.size * typeinfo.columns {
return Err(ShaderReflectError::MismatchedComponent { return Err(ShaderReflectError::MismatchedSize {
semantic: name, semantic: name,
vertex: meta.components, vertex: meta.size,
fragment: typeinfo.size, fragment: typeinfo.size,
}); });
} }
} else { } else {
meta.variable_meta.insert( meta.unique_meta.insert(
*semantics, *semantics,
VariableMeta { VariableMeta {
id: name, id: name,
offset, offset,
components: typeinfo.size * typeinfo.columns, size: typeinfo.size * typeinfo.columns,
}, },
); );
} }
@ -493,8 +488,8 @@ where
&self, &self,
texture: TextureData, texture: TextureData,
pass_number: usize, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ShaderSemantics,
meta: &mut ReflectMeta, meta: &mut BindingMeta,
) -> Result<(), ShaderReflectError> { ) -> Result<(), ShaderReflectError> {
let Some(semantic) = semantics.texture_semantics.get_texture_semantic(texture.name) else { let Some(semantic) = semantics.texture_semantics.get_texture_semantic(texture.name) else {
return Err(SemanticErrorBlame::Fragment.error(SemanticsErrorKind::UnknownSemantics(texture.name.to_string()))) return Err(SemanticErrorBlame::Fragment.error(SemanticsErrorKind::UnknownSemantics(texture.name.to_string())))
@ -609,7 +604,7 @@ where
fn reflect( fn reflect(
&mut self, &mut self,
pass_number: usize, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ShaderSemantics,
) -> Result<ShaderReflection, ShaderReflectError> { ) -> 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()?;
@ -625,7 +620,7 @@ where
let push_constant = self.reflect_push_constant_buffer(vertex_push, fragment_push)?; let push_constant = self.reflect_push_constant_buffer(vertex_push, fragment_push)?;
let mut meta = ReflectMeta::default(); let mut meta = BindingMeta::default();
if let Some(ubo) = vertex_ubo { if let Some(ubo) = vertex_ubo {
Self::reflect_buffer_range_metas( Self::reflect_buffer_range_metas(
@ -700,7 +695,7 @@ where
impl CompileShader<GLSL> for CrossReflect<glsl::Target> { impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
type Options = glsl::Version; type Options = glsl::Version;
type Context = GlslangGlslContext; type Context = CrossGlslContext;
fn compile( fn compile(
mut self, mut self,
@ -820,9 +815,9 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
Ok(ShaderCompilerOutput { Ok(ShaderCompilerOutput {
vertex: self.vertex.compile()?, vertex: self.vertex.compile()?,
fragment: self.fragment.compile()?, fragment: self.fragment.compile()?,
context: GlslangGlslContext { context: CrossGlslContext {
sampler_bindings: texture_fixups, sampler_bindings: texture_fixups,
compiler: CompiledProgram { artifact: CompiledProgram {
vertex: CompiledAst(self.vertex), vertex: CompiledAst(self.vertex),
fragment: CompiledAst(self.fragment), fragment: CompiledAst(self.fragment),
}, },
@ -833,12 +828,12 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
impl CompileShader<HLSL> for CrossReflect<hlsl::Target> { impl CompileShader<HLSL> for CrossReflect<hlsl::Target> {
type Options = Option<()>; type Options = Option<()>;
type Context = GlslangHlslContext; type Context = CrossHlslContext;
fn compile( fn compile(
mut self, mut self,
_options: Self::Options, _options: Self::Options,
) -> Result<ShaderCompilerOutput<String, GlslangHlslContext>, ShaderCompileError> { ) -> Result<ShaderCompilerOutput<String, CrossHlslContext>, 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;
@ -848,7 +843,7 @@ impl CompileShader<HLSL> for CrossReflect<hlsl::Target> {
Ok(ShaderCompilerOutput { Ok(ShaderCompilerOutput {
vertex: self.vertex.compile()?, vertex: self.vertex.compile()?,
fragment: self.fragment.compile()?, fragment: self.fragment.compile()?,
context: GlslangHlslContext { context: CrossHlslContext {
compiler: CompiledProgram { compiler: CompiledProgram {
vertex: CompiledAst(self.vertex), vertex: CompiledAst(self.vertex),
fragment: CompiledAst(self.fragment), fragment: CompiledAst(self.fragment),
@ -867,7 +862,7 @@ mod test {
use crate::back::CompileShader; use crate::back::CompileShader;
use crate::front::shaderc::GlslangCompilation; use crate::front::shaderc::GlslangCompilation;
use crate::reflect::semantics::{ use crate::reflect::semantics::{
ReflectSemantics, SemanticMap, UniformSemantic, VariableSemantics, ShaderSemantics, Semantic, UniformSemantic, UniqueSemantics,
}; };
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use spirv_cross::glsl; use spirv_cross::glsl;
@ -881,8 +876,8 @@ mod test {
for (_index, param) in result.parameters.iter().enumerate() { for (_index, param) in result.parameters.iter().enumerate() {
uniform_semantics.insert( uniform_semantics.insert(
param.id.clone(), param.id.clone(),
UniformSemantic::Variable(SemanticMap { UniformSemantic::Unique(Semantic {
semantics: VariableSemantics::FloatParameter, semantics: UniqueSemantics::FloatParameter,
index: (), index: (),
}), }),
); );
@ -892,7 +887,7 @@ mod test {
let _shader_reflection = reflect let _shader_reflection = reflect
.reflect( .reflect(
0, 0,
&ReflectSemantics { &ShaderSemantics {
uniform_semantics, uniform_semantics,
texture_semantics: Default::default(), texture_semantics: Default::default(),
}, },

View file

@ -1,12 +1,14 @@
use crate::error::ShaderReflectError; use crate::error::ShaderReflectError;
use crate::reflect::semantics::{ use crate::reflect::semantics::{
SemanticMap, TextureBinding, TextureSemantics, TextureSizeMeta, VariableMeta, VariableSemantics, Semantic, TextureBinding, TextureSemantics, TextureSizeMeta, UniqueSemantics, VariableMeta,
}; };
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use semantics::ReflectSemantics; use semantics::ShaderSemantics;
/// Reflection via spirv-cross.
pub mod cross; pub mod cross;
/// Shader semantics and reflection information.
pub mod semantics; pub mod semantics;
#[cfg(feature = "unstable-rust-pipeline")] #[cfg(feature = "unstable-rust-pipeline")]
@ -14,22 +16,17 @@ mod naga;
#[cfg(feature = "unstable-rust-pipeline")] #[cfg(feature = "unstable-rust-pipeline")]
mod rspirv; mod rspirv;
/// A trait for compilation outputs that can provide reflection information.
pub trait ReflectShader { pub trait ReflectShader {
/// Reflect the shader as the given pass within the shader preset, against the provided
/// semantic map.
fn reflect( fn reflect(
&mut self, &mut self,
pass_number: usize, pass_number: usize,
semantics: &ReflectSemantics, semantics: &ShaderSemantics,
) -> Result<ShaderReflection, ShaderReflectError>; ) -> Result<ShaderReflection, ShaderReflectError>;
} }
#[derive(Debug, Default)]
pub struct ReflectMeta {
pub parameter_meta: FxHashMap<String, VariableMeta>,
pub variable_meta: FxHashMap<VariableSemantics, VariableMeta>,
pub texture_meta: FxHashMap<SemanticMap<TextureSemantics>, TextureBinding>,
pub texture_size_meta: FxHashMap<SemanticMap<TextureSemantics>, TextureSizeMeta>,
}
pub use semantics::ShaderReflection; pub use semantics::ShaderReflection;
#[inline(always)] #[inline(always)]

View file

@ -1,65 +1,91 @@
use crate::reflect::ReflectMeta;
use bitflags::bitflags; use bitflags::bitflags;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use std::str::FromStr; use std::str::FromStr;
/// The maximum number of bindings allowed in a shader.
pub const MAX_BINDINGS_COUNT: u32 = 16; pub const MAX_BINDINGS_COUNT: u32 = 16;
/// The maximum size of the push constant range.
pub const MAX_PUSH_BUFFER_SIZE: u32 = 128; pub const MAX_PUSH_BUFFER_SIZE: u32 = 128;
/// The type of a uniform.
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
pub enum UniformType { pub enum UniformType {
MVP, /// A matrix of 4x4 floats (`mat4`).
Size, Mat4,
/// A vector of 4 floats (`vec4`).
Vec4,
/// An unsigned integer (`uint`).
Unsigned, Unsigned,
/// A signed integer (`int`).
Signed, Signed,
/// A floating point number (`float`).
Float, Float,
} }
/// Unique semantics are builtin uniforms passed by the shader runtime
/// that are always available.
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
#[repr(i32)] #[repr(i32)]
pub enum VariableSemantics { pub enum UniqueSemantics {
// mat4, MVP // mat4, MVP
/// The Model View Projection matrix for the frame.
MVP = 0, MVP = 0,
// vec4, viewport size of current pass // vec4, viewport size of current pass
/// The viewport size of the current pass.
Output = 1, Output = 1,
// vec4, viewport size of final pass // vec4, viewport size of final pass
/// The viewport size of the final pass.
FinalViewport = 2, FinalViewport = 2,
// uint, frame count with modulo // uint, frame count with modulo
/// The frame count, possibly with shader-defined modulo.
FrameCount = 3, FrameCount = 3,
// int, frame direction // int, frame direction
/// The frame direction.
FrameDirection = 4, FrameDirection = 4,
/// A user defined float parameter.
// float, user defined parameter, array // float, user defined parameter, array
FloatParameter = 5, FloatParameter = 5,
} }
impl VariableSemantics { impl UniqueSemantics {
pub const fn semantics(self) -> SemanticMap<VariableSemantics, ()> { /// Produce a `Semantic` for this `UniqueSemantics`.
SemanticMap { pub const fn semantics(self) -> Semantic<UniqueSemantics, ()> {
Semantic {
semantics: self, semantics: self,
index: (), index: (),
} }
} }
/// Get the type of the uniform when bound.
pub const fn binding_type(&self) -> UniformType { pub const fn binding_type(&self) -> UniformType {
match self { match self {
VariableSemantics::MVP => UniformType::MVP, UniqueSemantics::MVP => UniformType::Mat4,
VariableSemantics::Output => UniformType::Size, UniqueSemantics::Output => UniformType::Vec4,
VariableSemantics::FinalViewport => UniformType::Size, UniqueSemantics::FinalViewport => UniformType::Vec4,
VariableSemantics::FrameCount => UniformType::Unsigned, UniqueSemantics::FrameCount => UniformType::Unsigned,
VariableSemantics::FrameDirection => UniformType::Signed, UniqueSemantics::FrameDirection => UniformType::Signed,
VariableSemantics::FloatParameter => UniformType::Float, UniqueSemantics::FloatParameter => UniformType::Float,
} }
} }
} }
/// Texture semantics relate to input or output textures.
///
/// Texture semantics are used to relate both texture samplers and `*Size` uniforms.
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)] #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
#[repr(i32)] #[repr(i32)]
pub enum TextureSemantics { pub enum TextureSemantics {
/// The original input of the filter chain.
Original = 0, Original = 0,
/// The input from the previous shader pass, or the input on the first shader pass.
Source = 1, Source = 1,
/// The input frames from previous frames.
OriginalHistory = 2, OriginalHistory = 2,
/// The output from previous shader passes in the same frame.
PassOutput = 3, PassOutput = 3,
/// The output from previous shader passes in the previous frame.
PassFeedback = 4, PassFeedback = 4,
/// A user provided lookup texture.
User = 5, User = 5,
} }
@ -76,6 +102,7 @@ impl TextureSemantics {
TextureSemantics::User, TextureSemantics::User,
]; ];
/// Get the name of the size uniform for this semantics when bound.
pub fn size_uniform_name(&self) -> &'static str { pub fn size_uniform_name(&self) -> &'static str {
match self { match self {
TextureSemantics::Original => "OriginalSize", TextureSemantics::Original => "OriginalSize",
@ -87,6 +114,7 @@ impl TextureSemantics {
} }
} }
/// Get the name of the texture sampler for this semantics when bound.
pub fn texture_name(&self) -> &'static str { pub fn texture_name(&self) -> &'static str {
match self { match self {
TextureSemantics::Original => "Original", TextureSemantics::Original => "Original",
@ -98,33 +126,42 @@ impl TextureSemantics {
} }
} }
pub fn is_array(&self) -> bool { /// Returns whether or not textures of this semantics are indexed or unique.
///
/// Only Original and Source are unique, all other textures can be indexed.
pub fn is_indexed(&self) -> bool {
!matches!(self, TextureSemantics::Original | TextureSemantics::Source) !matches!(self, TextureSemantics::Original | TextureSemantics::Source)
} }
pub const fn semantics(self, index: usize) -> SemanticMap<TextureSemantics> { /// Produce a `Semantic` for this `TextureSemantics` of the given index.
SemanticMap { pub const fn semantics(self, index: usize) -> Semantic<TextureSemantics> {
Semantic {
semantics: self, semantics: self,
index, index,
} }
} }
} }
pub struct TypeInfo { pub(crate) struct TypeInfo {
pub size: u32, pub size: u32,
pub columns: u32, pub columns: u32,
} }
pub trait ValidateTypeSemantics<T> {
pub(crate) trait ValidateTypeSemantics<T> {
fn validate_type(&self, ty: &T) -> Option<TypeInfo>; fn validate_type(&self, ty: &T) -> Option<TypeInfo>;
} }
/// A unit of unique or indexed semantic.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct SemanticMap<T, I = usize> { pub struct Semantic<T, I = usize> {
/// The semantics of this unit.
pub semantics: T, pub semantics: T,
/// The index of the semantic if not unique.
pub index: I, pub index: I,
} }
bitflags! { bitflags! {
/// The pipeline stage for which a uniform is bound.
pub struct BindingStage: u8 { pub struct BindingStage: u8 {
const NONE = 0b00000000; const NONE = 0b00000000;
const VERTEX = 0b00000001; const VERTEX = 0b00000001;
@ -132,64 +169,86 @@ bitflags! {
} }
} }
impl BindingStage { /// Reflection information for the Uniform Buffer
pub fn clear(&mut self) {
self.bits = 0;
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct UboReflection { pub struct UboReflection {
/// The binding point for this UBO.
pub binding: u32, pub binding: u32,
/// Get this size of this UBO buffer. /// The size of the UBO buffer. UBO sizes returned by reflection is always aligned to a 16 byte boundary.
/// The size returned by reflection is always aligned to a 16 byte boundary.
pub size: u32, pub size: u32,
/// The mask indicating for which stages the UBO should be bound.
pub stage_mask: BindingStage, pub stage_mask: BindingStage,
} }
/// Reflection information for the Push Constant Block
#[derive(Debug)] #[derive(Debug)]
pub struct PushReflection { pub struct PushReflection {
/// The size returned by reflection is always aligned to a 16 byte boundary. /// The size of the Push Constant range. The size returned by reflection is always aligned to a 16 byte boundary.
pub size: u32, pub size: u32,
/// The mask indicating for which stages the Push Constant range should be bound.
pub stage_mask: BindingStage, pub stage_mask: BindingStage,
} }
/// The offset of a uniform member.
///
/// A uniform can be bound to **either** the UBO, or as a Push Constant. Binding
/// the same variable name to both locations will result in indeterminate results.
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum MemberOffset { pub enum MemberOffset {
/// The offset of the uniform member within the UBO.
Ubo(usize), Ubo(usize),
/// The offset of the uniform member within the Push Constant range.
PushConstant(usize), PushConstant(usize),
} }
/// Reflection information about a non-texture related uniform variable.
#[derive(Debug)] #[derive(Debug)]
pub struct VariableMeta { pub struct VariableMeta {
// this might bite us in the back because retroarch keeps separate UBO/push offsets.. eh // this might bite us in the back because retroarch keeps separate UBO/push offsets.. eh
/// The offset of this variable uniform.
pub offset: MemberOffset, pub offset: MemberOffset,
pub components: u32, /// The size of the uniform.
pub size: u32,
/// The name of the uniform.
pub id: String, pub id: String,
} }
/// Reflection information about a texture size uniform variable.
#[derive(Debug)] #[derive(Debug)]
pub struct TextureSizeMeta { pub struct TextureSizeMeta {
// this might bite us in the back because retroarch keeps separate UBO/push offsets.. // this might bite us in the back because retroarch keeps separate UBO/push offsets..
/// The offset of this size uniform.
pub offset: MemberOffset, pub offset: MemberOffset,
/// The mask indicating for which stages the texture size uniform should be bound.
pub stage_mask: BindingStage, pub stage_mask: BindingStage,
/// The name of the uniform.
pub id: String, pub id: String,
} }
/// Reflection information about texture samplers.
#[derive(Debug)] #[derive(Debug)]
pub struct TextureBinding { pub struct TextureBinding {
/// The binding index of the texture.
pub binding: u32, pub binding: u32,
} }
/// Reflection information about a shader.
#[derive(Debug)] #[derive(Debug)]
pub struct ShaderReflection { pub struct ShaderReflection {
/// Reflection information about the UBO for this shader.
pub ubo: Option<UboReflection>, pub ubo: Option<UboReflection>,
/// Reflection information about the Push Constant range for this shader.
pub push_constant: Option<PushReflection>, pub push_constant: Option<PushReflection>,
pub meta: ReflectMeta, /// Metadata about the bindings required for this shader.
pub meta: BindingMeta,
} }
/// Metadata about a uniform variable.
pub trait UniformMeta { pub trait UniformMeta {
/// The offset of this uniform.
fn offset(&self) -> MemberOffset; fn offset(&self) -> MemberOffset;
/// The name of this uniform in the shader.
fn id(&self) -> &str; fn id(&self) -> &str;
} }
@ -207,35 +266,36 @@ impl UniformMeta for TextureSizeMeta {
fn offset(&self) -> MemberOffset { fn offset(&self) -> MemberOffset {
self.offset self.offset
} }
fn id(&self) -> &str { fn id(&self) -> &str {
&self.id &self.id
} }
} }
pub trait TextureSemanticMap<T> { /// A trait for maps that can return texture semantic units.
fn get_texture_semantic(&self, name: &str) -> Option<SemanticMap<TextureSemantics>>; pub trait TextureSemanticMap {
/// Get the texture semantic for the given variable name.
fn get_texture_semantic(&self, name: &str) -> Option<Semantic<TextureSemantics>>;
} }
impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, UniformSemantic> { impl TextureSemanticMap for FxHashMap<String, UniformSemantic> {
fn get_texture_semantic(&self, name: &str) -> Option<SemanticMap<TextureSemantics>> { fn get_texture_semantic(&self, name: &str) -> Option<Semantic<TextureSemantics>> {
match self.get(name) { match self.get(name) {
None => { None => {
if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS
.iter() .iter()
.find(|f| name.starts_with(f.size_uniform_name())) .find(|f| name.starts_with(f.size_uniform_name()))
{ {
if semantics.is_array() { if semantics.is_indexed() {
let index = &name[semantics.size_uniform_name().len()..]; let index = &name[semantics.size_uniform_name().len()..];
let Ok(index) = usize::from_str(index) else { let Ok(index) = usize::from_str(index) else {
return None; return None;
}; };
return Some(SemanticMap { return Some(Semantic {
semantics: *semantics, semantics: *semantics,
index, index,
}); });
} else if name == semantics.size_uniform_name() { } else if name == semantics.size_uniform_name() {
return Some(SemanticMap { return Some(Semantic {
semantics: *semantics, semantics: *semantics,
index: 0, index: 0,
}); });
@ -243,29 +303,29 @@ impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, UniformSemantic>
} }
None None
} }
Some(UniformSemantic::Variable(_)) => None, Some(UniformSemantic::Unique(_)) => None,
Some(UniformSemantic::Texture(texture)) => Some(*texture), Some(UniformSemantic::Texture(texture)) => Some(*texture),
} }
} }
} }
impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, SemanticMap<TextureSemantics>> { impl TextureSemanticMap for FxHashMap<String, Semantic<TextureSemantics>> {
fn get_texture_semantic(&self, name: &str) -> Option<SemanticMap<TextureSemantics>> { fn get_texture_semantic(&self, name: &str) -> Option<Semantic<TextureSemantics>> {
match self.get(name) { match self.get(name) {
None => { None => {
if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS
.iter() .iter()
.find(|f| name.starts_with(f.texture_name())) .find(|f| name.starts_with(f.texture_name()))
{ {
if semantics.is_array() { if semantics.is_indexed() {
let index = &name[semantics.texture_name().len()..]; let index = &name[semantics.texture_name().len()..];
let Ok(index) = usize::from_str(index) else {return None}; let Ok(index) = usize::from_str(index) else {return None};
return Some(SemanticMap { return Some(Semantic {
semantics: *semantics, semantics: *semantics,
index, index,
}); });
} else if name == semantics.texture_name() { } else if name == semantics.texture_name() {
return Some(SemanticMap { return Some(Semantic {
semantics: *semantics, semantics: *semantics,
index: 0, index: 0,
}); });
@ -278,70 +338,98 @@ impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, SemanticMap<Textu
} }
} }
pub trait VariableSemanticMap<T> { /// A trait for maps that can return unique semantic units.
fn get_variable_semantic(&self, name: &str) -> Option<SemanticMap<VariableSemantics, ()>>; pub trait UniqueSemanticMap {
/// Get the unique semantic for the given variable name.
fn get_unique_semantic(&self, name: &str) -> Option<Semantic<UniqueSemantics, ()>>;
} }
impl VariableSemanticMap<UniformSemantic> for FxHashMap<String, UniformSemantic> { impl UniqueSemanticMap for FxHashMap<String, UniformSemantic> {
fn get_variable_semantic(&self, name: &str) -> Option<SemanticMap<VariableSemantics, ()>> { fn get_unique_semantic(&self, name: &str) -> Option<Semantic<UniqueSemantics, ()>> {
match self.get(name) { match self.get(name) {
// existing uniforms in the semantic map have priority // existing uniforms in the semantic map have priority
None => match name { None => match name {
"MVP" => Some(SemanticMap { "MVP" => Some(Semantic {
semantics: VariableSemantics::MVP, semantics: UniqueSemantics::MVP,
index: (), index: (),
}), }),
"OutputSize" => Some(SemanticMap { "OutputSize" => Some(Semantic {
semantics: VariableSemantics::Output, semantics: UniqueSemantics::Output,
index: (), index: (),
}), }),
"FinalViewportSize" => Some(SemanticMap { "FinalViewportSize" => Some(Semantic {
semantics: VariableSemantics::FinalViewport, semantics: UniqueSemantics::FinalViewport,
index: (), index: (),
}), }),
"FrameCount" => Some(SemanticMap { "FrameCount" => Some(Semantic {
semantics: VariableSemantics::FrameCount, semantics: UniqueSemantics::FrameCount,
index: (), index: (),
}), }),
"FrameDirection" => Some(SemanticMap { "FrameDirection" => Some(Semantic {
semantics: VariableSemantics::FrameDirection, semantics: UniqueSemantics::FrameDirection,
index: (), index: (),
}), }),
_ => None, _ => None,
}, },
Some(UniformSemantic::Variable(variable)) => Some(*variable), Some(UniformSemantic::Unique(variable)) => Some(*variable),
Some(UniformSemantic::Texture(_)) => None, Some(UniformSemantic::Texture(_)) => None,
} }
} }
} }
/// Semantic assignment of a shader uniform to filter chain semantics.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum UniformSemantic { pub enum UniformSemantic {
Variable(SemanticMap<VariableSemantics, ()>), /// A unique semantic.
Texture(SemanticMap<TextureSemantics>), Unique(Semantic<UniqueSemantics, ()>),
/// A texture related semantic.
Texture(Semantic<TextureSemantics>),
} }
/// The runtime provided maps of uniform and texture variables to filter chain semantics.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ReflectSemantics { pub struct ShaderSemantics {
/// A map of uniform names to filter chain semantics.
pub uniform_semantics: FxHashMap<String, UniformSemantic>, pub uniform_semantics: FxHashMap<String, UniformSemantic>,
pub texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>>, /// A map of texture names to filter chain semantics.
pub texture_semantics: FxHashMap<String, Semantic<TextureSemantics>>,
} }
/// The binding of a uniform after the shader has been linked.
///
/// Used in combination with [`MemberOffset`](crate::reflect::semantics::MemberOffset) to keep track
/// of semantics at each frame pass.
#[derive(Debug, Clone, Eq, Hash, PartialEq)] #[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub enum UniformBinding { pub enum UniformBinding {
/// A user parameter (`float`) binding.
Parameter(String), Parameter(String),
SemanticVariable(VariableSemantics), /// A known semantic binding.
TextureSize(SemanticMap<TextureSemantics>), SemanticVariable(UniqueSemantics),
/// A texture size (`float4`) binding.
TextureSize(Semantic<TextureSemantics>),
} }
impl From<VariableSemantics> for UniformBinding { impl From<UniqueSemantics> for UniformBinding {
fn from(value: VariableSemantics) -> Self { fn from(value: UniqueSemantics) -> Self {
UniformBinding::SemanticVariable(value) UniformBinding::SemanticVariable(value)
} }
} }
impl From<SemanticMap<TextureSemantics>> for UniformBinding { impl From<Semantic<TextureSemantics>> for UniformBinding {
fn from(value: SemanticMap<TextureSemantics>) -> Self { fn from(value: Semantic<TextureSemantics>) -> Self {
UniformBinding::TextureSize(value) UniformBinding::TextureSize(value)
} }
} }
/// Reflection metadata about the various bindings for this shader.
#[derive(Debug, Default)]
pub struct BindingMeta {
/// A map of parameter names to uniform binding metadata.
pub parameter_meta: FxHashMap<String, VariableMeta>,
/// A map of unique semantics to uniform binding metadata.
pub unique_meta: FxHashMap<UniqueSemantics, VariableMeta>,
/// A map of texture semantics to texture binding points.
pub texture_meta: FxHashMap<Semantic<TextureSemantics>, TextureBinding>,
/// A map of texture semantics to texture size uniform binding metadata.
pub texture_size_meta: FxHashMap<Semantic<TextureSemantics>, TextureSizeMeta>,
}

View file

@ -3,13 +3,13 @@ use librashader_common::image::{Image, UVDirection};
use librashader_common::{ImageFormat, Size}; use librashader_common::{ImageFormat, Size};
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_reflect::back::cross::GlslangHlslContext; use librashader_reflect::back::cross::CrossHlslContext;
use librashader_reflect::back::targets::HLSL; use librashader_reflect::back::targets::HLSL;
use librashader_reflect::back::{CompileShader, CompilerBackend, FromCompilation}; use librashader_reflect::back::{CompileShader, CompilerBackend, FromCompilation};
use librashader_reflect::front::shaderc::GlslangCompilation; use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::semantics::{ use librashader_reflect::reflect::semantics::{
ReflectSemantics, SemanticMap, TextureSemantics, UniformBinding, UniformSemantic, ShaderSemantics, Semantic, TextureSemantics, UniformBinding, UniformSemantic,
VariableSemantics, UniqueSemantics,
}; };
use librashader_reflect::reflect::ReflectShader; use librashader_reflect::reflect::ReflectShader;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -45,7 +45,7 @@ type ShaderPassMeta = (
ShaderPassConfig, ShaderPassConfig,
ShaderSource, ShaderSource,
CompilerBackend< CompilerBackend<
impl CompileShader<HLSL, Options = Option<()>, Context = GlslangHlslContext> + ReflectShader, impl CompileShader<HLSL, Options = Option<()>, Context =CrossHlslContext> + ReflectShader,
>, >,
); );
@ -218,7 +218,7 @@ impl FilterChain {
fn init_passes( fn init_passes(
device: &ID3D11Device, device: &ID3D11Device,
passes: Vec<ShaderPassMeta>, passes: Vec<ShaderPassMeta>,
semantics: &ReflectSemantics, semantics: &ShaderSemantics,
) -> error::Result<Vec<FilterPass>> { ) -> error::Result<Vec<FilterPass>> {
// let mut filters = Vec::new(); // let mut filters = Vec::new();
let mut filters = Vec::new(); let mut filters = Vec::new();
@ -290,7 +290,7 @@ impl FilterChain {
uniform_bindings.insert(UniformBinding::Parameter(param.id.clone()), param.offset); uniform_bindings.insert(UniformBinding::Parameter(param.id.clone()), param.offset);
} }
for (semantics, param) in &reflection.meta.variable_meta { for (semantics, param) in &reflection.meta.unique_meta {
uniform_bindings.insert(UniformBinding::SemanticVariable(*semantics), param.offset); uniform_bindings.insert(UniformBinding::SemanticVariable(*semantics), param.offset);
} }
@ -414,9 +414,9 @@ impl FilterChain {
fn load_preset( fn load_preset(
passes: Vec<ShaderPassConfig>, passes: Vec<ShaderPassConfig>,
textures: &[TextureConfig], textures: &[TextureConfig],
) -> error::Result<(Vec<ShaderPassMeta>, ReflectSemantics)> { ) -> error::Result<(Vec<ShaderPassMeta>, ShaderSemantics)> {
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default(); let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> = let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> =
Default::default(); Default::default();
let passes = passes let passes = passes
@ -431,8 +431,8 @@ impl FilterChain {
for parameter in source.parameters.iter() { for parameter in source.parameters.iter() {
uniform_semantics.insert( uniform_semantics.insert(
parameter.id.clone(), parameter.id.clone(),
UniformSemantic::Variable(SemanticMap { UniformSemantic::Unique(Semantic {
semantics: VariableSemantics::FloatParameter, semantics: UniqueSemantics::FloatParameter,
index: (), index: (),
}), }),
); );
@ -456,7 +456,7 @@ impl FilterChain {
&mut texture_semantics, &mut texture_semantics,
); );
let semantics = ReflectSemantics { let semantics = ShaderSemantics {
uniform_semantics, uniform_semantics,
texture_semantics, texture_semantics,
}; };

View file

@ -3,10 +3,10 @@ use crate::texture::Texture;
use librashader_common::{ImageFormat, Size}; use librashader_common::{ImageFormat, Size};
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_presets::ShaderPassConfig; use librashader_presets::ShaderPassConfig;
use librashader_reflect::back::cross::GlslangHlslContext; use librashader_reflect::back::cross::CrossHlslContext;
use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::reflect::semantics::{ use librashader_reflect::reflect::semantics::{
BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, VariableSemantics, BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics,
}; };
use librashader_reflect::reflect::ShaderReflection; use librashader_reflect::reflect::ShaderReflection;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -32,7 +32,7 @@ pub struct ConstantBufferBinding {
// slang_process.cpp 141 // slang_process.cpp 141
pub struct FilterPass { pub struct FilterPass {
pub reflection: ShaderReflection, pub reflection: ShaderReflection,
pub compiled: ShaderCompilerOutput<String, GlslangHlslContext>, pub compiled: ShaderCompilerOutput<String, CrossHlslContext>,
pub vertex_shader: ID3D11VertexShader, pub vertex_shader: ID3D11VertexShader,
pub vertex_layout: ID3D11InputLayout, pub vertex_layout: ID3D11InputLayout,
pub pixel_shader: ID3D11PixelShader, pub pixel_shader: ID3D11PixelShader,
@ -95,19 +95,19 @@ impl FilterPass {
let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None); let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None);
// Bind MVP // Bind MVP
if let Some(offset) = self.uniform_bindings.get(&VariableSemantics::MVP.into()) { if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::MVP.into()) {
self.uniform_storage.bind_mat4(*offset, mvp, None); self.uniform_storage.bind_mat4(*offset, mvp, None);
} }
// bind OutputSize // bind OutputSize
if let Some(offset) = self.uniform_bindings.get(&VariableSemantics::Output.into()) { if let Some(offset) = self.uniform_bindings.get(&UniqueSemantics::Output.into()) {
self.uniform_storage.bind_vec4(*offset, fb_size, None); self.uniform_storage.bind_vec4(*offset, fb_size, None);
} }
// bind FinalViewportSize // bind FinalViewportSize
if let Some(offset) = self if let Some(offset) = self
.uniform_bindings .uniform_bindings
.get(&VariableSemantics::FinalViewport.into()) .get(&UniqueSemantics::FinalViewport.into())
{ {
self.uniform_storage.bind_vec4(*offset, viewport_size, None); self.uniform_storage.bind_vec4(*offset, viewport_size, None);
} }
@ -115,7 +115,7 @@ impl FilterPass {
// bind FrameCount // bind FrameCount
if let Some(offset) = self if let Some(offset) = self
.uniform_bindings .uniform_bindings
.get(&VariableSemantics::FrameCount.into()) .get(&UniqueSemantics::FrameCount.into())
{ {
self.uniform_storage.bind_scalar(*offset, frame_count, None); self.uniform_storage.bind_scalar(*offset, frame_count, None);
} }
@ -123,7 +123,7 @@ impl FilterPass {
// bind FrameDirection // bind FrameDirection
if let Some(offset) = self if let Some(offset) = self
.uniform_bindings .uniform_bindings
.get(&VariableSemantics::FrameDirection.into()) .get(&UniqueSemantics::FrameDirection.into())
{ {
self.uniform_storage self.uniform_storage
.bind_scalar(*offset, frame_direction, None); .bind_scalar(*offset, frame_direction, None);

View file

@ -1,9 +1,9 @@
use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig}; use librashader_presets::{ShaderPassConfig, ShaderPreset, TextureConfig};
use librashader_reflect::reflect::semantics::{MemberOffset, ReflectSemantics, SemanticMap, TextureSemantics, UniformBinding, UniformMeta, UniformSemantic, VariableSemantics}; use librashader_reflect::reflect::semantics::{MemberOffset, ShaderSemantics, Semantic, TextureSemantics, UniformBinding, UniformMeta, UniformSemantic, UniqueSemantics};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation}; use librashader_reflect::back::{CompilerBackend, CompileShader, FromCompilation};
use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion}; use librashader_reflect::back::cross::{CrossGlslContext, GlslVersion};
use librashader_reflect::back::targets::GLSL; use librashader_reflect::back::targets::GLSL;
use librashader_reflect::front::shaderc::GlslangCompilation; use librashader_reflect::front::shaderc::GlslangCompilation;
use spirv_cross::spirv::Decoration; use spirv_cross::spirv::Decoration;
@ -79,7 +79,7 @@ type ShaderPassMeta = (
ShaderPassConfig, ShaderPassConfig,
ShaderSource, ShaderSource,
CompilerBackend< CompilerBackend<
impl CompileShader<GLSL, Options = GlVersion, Context = GlslangGlslContext> + ReflectShader, impl CompileShader<GLSL, Options =GlslVersion, Context =CrossGlslContext> + ReflectShader,
>, >,
); );
@ -154,9 +154,9 @@ impl<T: GLInterface> FilterChainImpl<T> {
fn load_preset( fn load_preset(
passes: Vec<ShaderPassConfig>, passes: Vec<ShaderPassConfig>,
textures: &[TextureConfig], textures: &[TextureConfig],
) -> error::Result<(Vec<ShaderPassMeta>, ReflectSemantics)> { ) -> error::Result<(Vec<ShaderPassMeta>, ShaderSemantics)> {
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default(); let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> = let mut texture_semantics: FxHashMap<String, Semantic<TextureSemantics>> =
Default::default(); Default::default();
let passes = passes let passes = passes
@ -171,8 +171,8 @@ impl<T: GLInterface> FilterChainImpl<T> {
for parameter in source.parameters.iter() { for parameter in source.parameters.iter() {
uniform_semantics.insert( uniform_semantics.insert(
parameter.id.clone(), parameter.id.clone(),
UniformSemantic::Variable(SemanticMap { UniformSemantic::Unique(Semantic {
semantics: VariableSemantics::FloatParameter, semantics: UniqueSemantics::FloatParameter,
index: (), index: (),
}), }),
); );
@ -196,7 +196,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
&mut texture_semantics, &mut texture_semantics,
); );
let semantics = ReflectSemantics { let semantics = ShaderSemantics {
uniform_semantics, uniform_semantics,
texture_semantics, texture_semantics,
}; };
@ -205,9 +205,9 @@ impl<T: GLInterface> FilterChainImpl<T> {
} }
fn init_passes( fn init_passes(
version: GlVersion, version: GlslVersion,
passes: Vec<ShaderPassMeta>, passes: Vec<ShaderPassMeta>,
semantics: &ReflectSemantics, semantics: &ShaderSemantics,
) -> error::Result<Box<[FilterPass<T>]>> { ) -> error::Result<Box<[FilterPass<T>]>> {
let mut filters = Vec::new(); let mut filters = Vec::new();
@ -216,7 +216,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
let reflection = reflect.reflect(index, semantics)?; let reflection = reflect.reflect(index, semantics)?;
let glsl = reflect.compile(version)?; let glsl = reflect.compile(version)?;
let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?; let vertex_resources = glsl.context.artifact.vertex.get_shader_resources()?;
// todo: split this out. // todo: split this out.
let (program, ubo_location) = unsafe { let (program, ubo_location) = unsafe {
@ -230,7 +230,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
for res in vertex_resources.stage_inputs { for res in vertex_resources.stage_inputs {
let loc = glsl let loc = glsl
.context .context
.compiler .artifact
.vertex .vertex
.get_decoration(res.id, Decoration::Location)?; .get_decoration(res.id, Decoration::Location)?;
let mut name = res.name; let mut name = res.name;
@ -302,7 +302,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
); );
} }
for (semantics, param) in &reflection.meta.variable_meta { for (semantics, param) in &reflection.meta.unique_meta {
uniform_bindings.insert( uniform_bindings.insert(
UniformBinding::SemanticVariable(*semantics), UniformBinding::SemanticVariable(*semantics),
(Self::reflect_uniform_location(program, param), param.offset), (Self::reflect_uniform_location(program, param), param.offset),

View file

@ -1,5 +1,5 @@
use gl::types::{GLsizei, GLuint}; use gl::types::{GLsizei, GLuint};
use librashader_reflect::back::cross::GlslangGlslContext; use librashader_reflect::back::cross::CrossGlslContext;
use librashader_reflect::back::ShaderCompilerOutput; use librashader_reflect::back::ShaderCompilerOutput;
use librashader_reflect::reflect::ShaderReflection; use librashader_reflect::reflect::ShaderReflection;
@ -7,7 +7,7 @@ use librashader_common::{ImageFormat, Size};
use librashader_preprocess::ShaderSource; use librashader_preprocess::ShaderSource;
use librashader_presets::ShaderPassConfig; use librashader_presets::ShaderPassConfig;
use librashader_reflect::reflect::semantics::{ use librashader_reflect::reflect::semantics::{
MemberOffset, TextureSemantics, UniformBinding, VariableSemantics, MemberOffset, TextureSemantics, UniformBinding, UniqueSemantics,
}; };
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -21,7 +21,7 @@ use crate::texture::Texture;
pub struct FilterPass<T: GLInterface> { pub struct FilterPass<T: GLInterface> {
pub reflection: ShaderReflection, pub reflection: ShaderReflection,
pub compiled: ShaderCompilerOutput<String, GlslangGlslContext>, pub compiled: ShaderCompilerOutput<String, CrossGlslContext>,
pub program: GLuint, pub program: GLuint,
pub ubo_location: UniformLocation<GLuint>, pub ubo_location: UniformLocation<GLuint>,
pub ubo_ring: Option<T::UboRing>, pub ubo_ring: Option<T::UboRing>,
@ -127,7 +127,7 @@ impl<T: GLInterface> FilterPass<T> {
source: &Texture, source: &Texture,
) { ) {
// Bind MVP // Bind MVP
if let Some((location, offset)) = self.uniform_bindings.get(&VariableSemantics::MVP.into()) if let Some((location, offset)) = self.uniform_bindings.get(&UniqueSemantics::MVP.into())
{ {
self.uniform_storage self.uniform_storage
.bind_mat4(*offset, mvp, location.location()); .bind_mat4(*offset, mvp, location.location());
@ -135,7 +135,7 @@ impl<T: GLInterface> FilterPass<T> {
// bind OutputSize // bind OutputSize
if let Some((location, offset)) = if let Some((location, offset)) =
self.uniform_bindings.get(&VariableSemantics::Output.into()) self.uniform_bindings.get(&UniqueSemantics::Output.into())
{ {
self.uniform_storage self.uniform_storage
.bind_vec4(*offset, fb_size, location.location()); .bind_vec4(*offset, fb_size, location.location());
@ -144,7 +144,7 @@ impl<T: GLInterface> FilterPass<T> {
// bind FinalViewportSize // bind FinalViewportSize
if let Some((location, offset)) = self if let Some((location, offset)) = self
.uniform_bindings .uniform_bindings
.get(&VariableSemantics::FinalViewport.into()) .get(&UniqueSemantics::FinalViewport.into())
{ {
self.uniform_storage self.uniform_storage
.bind_vec4(*offset, viewport.output.size, location.location()); .bind_vec4(*offset, viewport.output.size, location.location());
@ -153,7 +153,7 @@ impl<T: GLInterface> FilterPass<T> {
// bind FrameCount // bind FrameCount
if let Some((location, offset)) = self if let Some((location, offset)) = self
.uniform_bindings .uniform_bindings
.get(&VariableSemantics::FrameCount.into()) .get(&UniqueSemantics::FrameCount.into())
{ {
self.uniform_storage self.uniform_storage
.bind_scalar(*offset, frame_count, location.location()); .bind_scalar(*offset, frame_count, location.location());
@ -162,7 +162,7 @@ impl<T: GLInterface> FilterPass<T> {
// bind FrameDirection // bind FrameDirection
if let Some((location, offset)) = self if let Some((location, offset)) = self
.uniform_bindings .uniform_bindings
.get(&VariableSemantics::FrameDirection.into()) .get(&UniqueSemantics::FrameDirection.into())
{ {
self.uniform_storage self.uniform_storage
.bind_scalar(*offset, frame_direction, location.location()); .bind_scalar(*offset, frame_direction, location.location());

View file

@ -1,6 +1,6 @@
use gl::types::{GLenum, GLuint}; use gl::types::{GLenum, GLuint};
use librashader_reflect::back::cross::GlVersion; use librashader_reflect::back::cross::GlslVersion;
pub trait RingBuffer<T> { pub trait RingBuffer<T> {
fn current(&self) -> &T; fn current(&self) -> &T;
@ -69,7 +69,7 @@ pub unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint {
shader shader
} }
pub fn gl_get_version() -> GlVersion { pub fn gl_get_version() -> GlslVersion {
let mut maj_ver = 0; let mut maj_ver = 0;
let mut min_ver = 0; let mut min_ver = 0;
unsafe { unsafe {
@ -79,40 +79,40 @@ pub fn gl_get_version() -> GlVersion {
match maj_ver { match maj_ver {
3 => match min_ver { 3 => match min_ver {
3 => GlVersion::V3_30, 3 => GlslVersion::V3_30,
2 => GlVersion::V1_50, 2 => GlslVersion::V1_50,
1 => GlVersion::V1_40, 1 => GlslVersion::V1_40,
0 => GlVersion::V1_30, 0 => GlslVersion::V1_30,
_ => GlVersion::V1_50, _ => GlslVersion::V1_50,
}, },
4 => match min_ver { 4 => match min_ver {
6 => GlVersion::V4_60, 6 => GlslVersion::V4_60,
5 => GlVersion::V4_50, 5 => GlslVersion::V4_50,
4 => GlVersion::V4_40, 4 => GlslVersion::V4_40,
3 => GlVersion::V4_30, 3 => GlslVersion::V4_30,
2 => GlVersion::V4_20, 2 => GlslVersion::V4_20,
1 => GlVersion::V4_10, 1 => GlslVersion::V4_10,
0 => GlVersion::V4_00, 0 => GlslVersion::V4_00,
_ => GlVersion::V1_50, _ => GlslVersion::V1_50,
}, },
_ => GlVersion::V1_50, _ => GlslVersion::V1_50,
} }
} }
pub fn gl_u16_to_version(version: u16) -> GlVersion { pub fn gl_u16_to_version(version: u16) -> GlslVersion {
match version { match version {
0 => gl_get_version(), 0 => gl_get_version(),
300 => GlVersion::V1_30, 300 => GlslVersion::V1_30,
310 => GlVersion::V1_40, 310 => GlslVersion::V1_40,
320 => GlVersion::V1_50, 320 => GlslVersion::V1_50,
330 => GlVersion::V3_30, 330 => GlslVersion::V3_30,
400 => GlVersion::V4_00, 400 => GlslVersion::V4_00,
410 => GlVersion::V4_10, 410 => GlslVersion::V4_10,
420 => GlVersion::V4_20, 420 => GlslVersion::V4_20,
430 => GlVersion::V4_30, 430 => GlslVersion::V4_30,
440 => GlVersion::V4_40, 440 => GlslVersion::V4_40,
450 => GlVersion::V4_50, 450 => GlslVersion::V4_50,
460 => GlVersion::V4_60, 460 => GlslVersion::V4_60,
_ => GlVersion::V1_50, _ => GlslVersion::V1_50,
} }
} }

View file

@ -1,12 +1,12 @@
use librashader_presets::{ShaderPassConfig, TextureConfig}; use librashader_presets::{ShaderPassConfig, TextureConfig};
use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, UniformSemantic}; use librashader_reflect::reflect::semantics::{Semantic, TextureSemantics, UniformSemantic};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
/// A map for variable names and uniform semantics /// A map for variable names and uniform semantics
pub type UniformSemanticsMap = FxHashMap<String, UniformSemantic>; pub type UniformSemanticsMap = FxHashMap<String, UniformSemantic>;
/// A map for sampler names and texture semantics. /// A map for sampler names and texture semantics.
pub type TextureSemanticsMap = FxHashMap<String, SemanticMap<TextureSemantics>>; pub type TextureSemanticsMap = FxHashMap<String, Semantic<TextureSemantics>>;
/// Insert the available semantics for the input pass config into the provided semantic maps. /// Insert the available semantics for the input pass config into the provided semantic maps.
pub fn insert_pass_semantics( pub fn insert_pass_semantics(
@ -28,14 +28,14 @@ pub fn insert_pass_semantics(
// PassOutput // PassOutput
texture_semantics.insert( texture_semantics.insert(
alias.clone(), alias.clone(),
SemanticMap { Semantic {
semantics: TextureSemantics::PassOutput, semantics: TextureSemantics::PassOutput,
index, index,
}, },
); );
uniform_semantics.insert( uniform_semantics.insert(
format!("{alias}Size"), format!("{alias}Size"),
UniformSemantic::Texture(SemanticMap { UniformSemantic::Texture(Semantic {
semantics: TextureSemantics::PassOutput, semantics: TextureSemantics::PassOutput,
index, index,
}), }),
@ -44,14 +44,14 @@ pub fn insert_pass_semantics(
// PassFeedback // PassFeedback
texture_semantics.insert( texture_semantics.insert(
format!("{alias}Feedback"), format!("{alias}Feedback"),
SemanticMap { Semantic {
semantics: TextureSemantics::PassFeedback, semantics: TextureSemantics::PassFeedback,
index, index,
}, },
); );
uniform_semantics.insert( uniform_semantics.insert(
format!("{alias}FeedbackSize"), format!("{alias}FeedbackSize"),
UniformSemantic::Texture(SemanticMap { UniformSemantic::Texture(Semantic {
semantics: TextureSemantics::PassFeedback, semantics: TextureSemantics::PassFeedback,
index, index,
}), }),
@ -67,7 +67,7 @@ pub fn insert_lut_semantics(
for (index, texture) in textures.iter().enumerate() { for (index, texture) in textures.iter().enumerate() {
texture_semantics.insert( texture_semantics.insert(
texture.name.clone(), texture.name.clone(),
SemanticMap { Semantic {
semantics: TextureSemantics::User, semantics: TextureSemantics::User,
index, index,
}, },
@ -75,7 +75,7 @@ pub fn insert_lut_semantics(
uniform_semantics.insert( uniform_semantics.insert(
format!("{}Size", texture.name), format!("{}Size", texture.name),
UniformSemantic::Texture(SemanticMap { UniformSemantic::Texture(Semantic {
semantics: TextureSemantics::User, semantics: TextureSemantics::User,
index, index,
}), }),

View file

@ -38,27 +38,23 @@ pub mod preprocess {
pub mod reflect { pub mod reflect {
/// Supported shader compiler targets. /// Supported shader compiler targets.
pub mod targets { pub mod targets {
/// Shader compiler target for GLSL.
pub use librashader_reflect::back::targets::GLSL; pub use librashader_reflect::back::targets::GLSL;
/// Shader compiler target for HLSL.
pub use librashader_reflect::back::targets::HLSL; pub use librashader_reflect::back::targets::HLSL;
/// Shader compiler target for SPIR-V.
pub use librashader_reflect::back::targets::SPIRV; pub use librashader_reflect::back::targets::SPIRV;
} }
pub use librashader_reflect::error::*; pub use librashader_reflect::error::*;
pub use librashader_reflect::reflect::{ pub use librashader_reflect::reflect::{
semantics, ReflectMeta, ReflectShader, ShaderReflection, ReflectShader, semantics, ShaderReflection,
}; };
pub use librashader_reflect::back::{ pub use librashader_reflect::back::{
targets::OutputTarget, CompileShader, CompilerBackend, FromCompilation, CompilerBackend, CompileShader, FromCompilation, ShaderCompilerOutput,
ShaderCompilerOutput, targets::OutputTarget,
}; };
pub use librashader_reflect::front::shaderc::GlslangCompilation; pub use librashader_reflect::front::shaderc::GlslangCompilation;
pub use librashader_reflect::reflect::semantics::BindingMeta;
} }
/// Shader runtimes to execute a filter chain on a GPU surface. /// Shader runtimes to execute a filter chain on a GPU surface.