reflect: document and rename some structs
This commit is contained in:
parent
5d668a2233
commit
e804ffd310
17 changed files with 356 additions and 219 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -5,3 +5,4 @@
|
|||
*.rdc
|
||||
*.cap
|
||||
/.vs/
|
||||
librashader_runtime_*.exe
|
||||
|
|
|
@ -5,17 +5,22 @@ use crate::front::shaderc::GlslangCompilation;
|
|||
use crate::reflect::cross::{CompiledProgram, GlslReflect, HlslReflect};
|
||||
use crate::reflect::ReflectShader;
|
||||
|
||||
pub type GlVersion = spirv_cross::glsl::Version;
|
||||
pub struct GlslangGlslContext {
|
||||
/// The GLSL version to use.
|
||||
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 compiler: CompiledProgram<spirv_cross::glsl::Target>,
|
||||
/// The compiled program artifact after compilation.
|
||||
pub artifact: CompiledProgram<spirv_cross::glsl::Target>,
|
||||
}
|
||||
|
||||
impl FromCompilation<GlslangCompilation> for GLSL {
|
||||
type Target = GLSL;
|
||||
type Options = GlVersion;
|
||||
type Context = GlslangGlslContext;
|
||||
type Output = impl CompileShader<Self::Target, Options = GlVersion, Context = GlslangGlslContext>
|
||||
type Options = GlslVersion;
|
||||
type Context = CrossGlslContext;
|
||||
type Output = impl CompileShader<Self::Target, Options = GlslVersion, Context = CrossGlslContext>
|
||||
+ ReflectShader;
|
||||
|
||||
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>,
|
||||
}
|
||||
|
||||
impl FromCompilation<GlslangCompilation> for HLSL {
|
||||
type Target = HLSL;
|
||||
type Options = Option<()>;
|
||||
type Context = GlslangHlslContext;
|
||||
type Context = CrossHlslContext;
|
||||
type Output = impl CompileShader<Self::Target, Options = Self::Options, Context = Self::Context>
|
||||
+ ReflectShader;
|
||||
|
||||
|
|
|
@ -3,21 +3,29 @@ pub mod targets;
|
|||
|
||||
use crate::back::targets::OutputTarget;
|
||||
use crate::error::{ShaderCompileError, ShaderReflectError};
|
||||
use crate::reflect::semantics::ReflectSemantics;
|
||||
use crate::reflect::semantics::ShaderSemantics;
|
||||
use crate::reflect::{ReflectShader, ShaderReflection};
|
||||
use std::fmt::Debug;
|
||||
|
||||
/// The output of the shader compiler.
|
||||
#[derive(Debug)]
|
||||
pub struct ShaderCompilerOutput<T, Context = ()> {
|
||||
/// The output for the vertex shader.
|
||||
pub vertex: T,
|
||||
/// The output for the fragment shader.
|
||||
pub fragment: T,
|
||||
/// Additional context provided by the shader compiler.
|
||||
pub context: Context,
|
||||
}
|
||||
|
||||
/// A trait for objects that can be compiled into a shader.
|
||||
pub trait CompileShader<T: OutputTarget> {
|
||||
/// Options provided to the compiler.
|
||||
type Options;
|
||||
/// Additional context returned by the compiler after compilation.
|
||||
type Context;
|
||||
|
||||
/// Consume the object and return the compiled output of the shader.
|
||||
fn compile(
|
||||
self,
|
||||
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> {
|
||||
/// The target that the transformed object is expected to compile for.
|
||||
type Target: OutputTarget;
|
||||
/// Options provided to the compiler.
|
||||
type Options;
|
||||
/// Additional context returned by the compiler after compilation.
|
||||
type Context;
|
||||
|
||||
/// The output type after conversion.
|
||||
type Output: CompileShader<Self::Target, Context = Self::Context, Options = Self::Options>
|
||||
+ ReflectShader;
|
||||
|
||||
/// Tries to convert the input object into an object ready for compilation.
|
||||
fn from_compilation(compile: T) -> Result<CompilerBackend<Self::Output>, ShaderReflectError>;
|
||||
}
|
||||
|
||||
/// A wrapper for a compiler backend.
|
||||
pub struct CompilerBackend<T> {
|
||||
pub(crate) backend: T,
|
||||
}
|
||||
|
@ -62,7 +77,7 @@ where
|
|||
fn reflect(
|
||||
&mut self,
|
||||
pass_number: usize,
|
||||
semantics: &ReflectSemantics,
|
||||
semantics: &ShaderSemantics,
|
||||
) -> Result<ShaderReflection, ShaderReflectError> {
|
||||
self.backend.reflect(pass_number, semantics)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
/// Marker trait for shader compiler targets.
|
||||
pub trait OutputTarget {
|
||||
/// The output format for the target.
|
||||
type Output;
|
||||
}
|
||||
|
||||
/// Shader compiler target for GLSL.
|
||||
pub struct GLSL;
|
||||
/// Shader compiler target for HLSL.
|
||||
pub struct HLSL;
|
||||
/// Shader compiler target for SPIR-V.
|
||||
pub struct SPIRV;
|
||||
/// Shader compiler target for MSL
|
||||
pub struct MSL;
|
||||
|
||||
impl OutputTarget for GLSL {
|
||||
|
|
|
@ -1,69 +1,100 @@
|
|||
use crate::reflect::semantics::MemberOffset;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Error type for shader compilation.
|
||||
#[non_exhaustive]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ShaderCompileError {
|
||||
/// Compile error from naga.
|
||||
#[cfg(feature = "unstable-rust-pipeline")]
|
||||
#[error("shader")]
|
||||
NagaCompileError(Vec<naga::front::glsl::Error>),
|
||||
|
||||
/// Compilation error from shaderc (glslang).
|
||||
#[error("shaderc")]
|
||||
ShaderCCompileError(#[from] shaderc::Error),
|
||||
|
||||
/// Error when initializing the shaderc compiler.
|
||||
#[error("shaderc init")]
|
||||
ShaderCInitError,
|
||||
|
||||
/// Error when transpiling from spirv-cross.
|
||||
#[error("cross")]
|
||||
SpirvCrossCompileError(#[from] spirv_cross::ErrorCode),
|
||||
}
|
||||
|
||||
/// The error kind encountered when reflecting shader semantics.
|
||||
#[derive(Debug)]
|
||||
pub enum SemanticsErrorKind {
|
||||
/// The number of uniform buffers was invalid. Only one UBO is permitted.
|
||||
InvalidUniformBufferCount(usize),
|
||||
/// The number of push constant blocks was invalid. Only one push constant block is permitted.
|
||||
InvalidPushBufferSize(u32),
|
||||
/// The location of a varying was invalid.
|
||||
InvalidLocation(u32),
|
||||
/// The requested descriptor set was invalid. Only descriptor set 0 is available.
|
||||
InvalidDescriptorSet(u32),
|
||||
/// The number of inputs to the shader was invalid.
|
||||
InvalidInputCount(usize),
|
||||
/// The number of outputs declared was invalid.
|
||||
InvalidOutputCount(usize),
|
||||
/// The declared binding point was invalid.
|
||||
InvalidBinding(u32),
|
||||
/// The declared resource type was invalid.
|
||||
InvalidResourceType,
|
||||
/// The range of a struct member was invalid.
|
||||
InvalidRange(u32),
|
||||
/// The requested uniform or texture name was not provided semantics.
|
||||
UnknownSemantics(String),
|
||||
/// The type of the requested uniform was not compatible with the provided semantics.
|
||||
InvalidTypeForSemantic(String),
|
||||
}
|
||||
|
||||
/// Error type for shader reflection.
|
||||
#[non_exhaustive]
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ShaderReflectError {
|
||||
/// Compile error from naga.
|
||||
#[cfg(feature = "unstable-rust-pipeline")]
|
||||
#[error("shader")]
|
||||
NagaCompileError(#[from] naga::front::spv::Error),
|
||||
|
||||
/// Parse error from rspirv.
|
||||
#[cfg(feature = "unstable-rust-pipeline")]
|
||||
#[error("rspirv")]
|
||||
RspirvParseError(#[from] rspirv::binary::ParseState),
|
||||
|
||||
/// Reflection error from spirv-cross.
|
||||
#[error("spirv")]
|
||||
SpirvCrossError(#[from] spirv_cross::ErrorCode),
|
||||
/// Error when validating vertex shader semantics.
|
||||
#[error("error when verifying vertex semantics")]
|
||||
VertexSemanticError(SemanticsErrorKind),
|
||||
/// Error when validating fragment shader semantics.
|
||||
#[error("error when verifying texture semantics")]
|
||||
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 },
|
||||
/// 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")]
|
||||
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")]
|
||||
MismatchedOffset {
|
||||
semantic: String,
|
||||
vertex: MemberOffset,
|
||||
fragment: MemberOffset,
|
||||
},
|
||||
/// The size of the given uniform did not match up in both the vertex and fragment shader.
|
||||
#[error("mismatched component")]
|
||||
MismatchedComponent {
|
||||
MismatchedSize {
|
||||
semantic: String,
|
||||
vertex: u32,
|
||||
fragment: u32,
|
||||
},
|
||||
/// The binding number is already in use.
|
||||
#[error("the binding is already in use")]
|
||||
BindingInUse(u32),
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use librashader_preprocess::ShaderSource;
|
|||
use naga::front::glsl::{Options, Parser};
|
||||
use naga::{Module, ShaderStage};
|
||||
|
||||
/// A reflectable shader compilation via naga.
|
||||
#[derive(Debug)]
|
||||
pub struct NagaCompilation {
|
||||
pub(crate) vertex: Module,
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::error::ShaderCompileError;
|
|||
use librashader_preprocess::ShaderSource;
|
||||
use shaderc::{CompilationArtifact, CompileOptions, Limit, ShaderKind};
|
||||
|
||||
/// A reflectable shader compilation via glslang (shaderc).
|
||||
pub struct GlslangCompilation {
|
||||
pub(crate) vertex: CompilationArtifact,
|
||||
pub(crate) fragment: CompilationArtifact,
|
||||
|
|
|
@ -1,19 +1,14 @@
|
|||
use crate::error::{SemanticsErrorKind, ShaderCompileError, ShaderReflectError};
|
||||
use crate::front::shaderc::GlslangCompilation;
|
||||
use crate::reflect::semantics::{
|
||||
BindingStage, MemberOffset, PushReflection, ReflectSemantics, ShaderReflection, TextureBinding,
|
||||
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 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};
|
||||
use crate::reflect::{align_uniform_size, ReflectShader};
|
||||
use std::ops::Deref;
|
||||
|
||||
use spirv_cross::hlsl::ShaderModel;
|
||||
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::{CompileShader, ShaderCompilerOutput};
|
||||
|
||||
|
@ -49,7 +44,7 @@ where
|
|||
pub(crate) type HlslReflect = CrossReflect<hlsl::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> {
|
||||
let (Type::Float { ref array, vecsize, columns } | Type::Int { ref array, vecsize, columns } | Type::UInt { ref array, vecsize, columns }) = *ty else {
|
||||
return None
|
||||
|
@ -60,16 +55,16 @@ impl ValidateTypeSemantics<Type> for VariableSemantics {
|
|||
}
|
||||
|
||||
let valid = match self {
|
||||
VariableSemantics::MVP => {
|
||||
UniqueSemantics::MVP => {
|
||||
matches!(ty, Type::Float { .. }) && vecsize == 4 && columns == 4
|
||||
}
|
||||
VariableSemantics::FrameCount => {
|
||||
UniqueSemantics::FrameCount => {
|
||||
matches!(ty, Type::UInt { .. }) && vecsize == 1 && columns == 1
|
||||
}
|
||||
VariableSemantics::FrameDirection => {
|
||||
UniqueSemantics::FrameDirection => {
|
||||
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 == 4 && columns == 1,
|
||||
|
@ -299,8 +294,8 @@ where
|
|||
ast: &Ast<T>,
|
||||
resource: &Resource,
|
||||
pass_number: usize,
|
||||
semantics: &ReflectSemantics,
|
||||
meta: &mut ReflectMeta,
|
||||
semantics: &ShaderSemantics,
|
||||
meta: &mut BindingMeta,
|
||||
offset_type: impl Fn(usize) -> MemberOffset,
|
||||
blame: SemanticErrorBlame,
|
||||
) -> Result<(), ShaderReflectError> {
|
||||
|
@ -319,13 +314,13 @@ where
|
|||
_ => 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 {
|
||||
return Err(blame.error(SemanticsErrorKind::InvalidTypeForSemantic(name)))
|
||||
};
|
||||
|
||||
match ¶meter.semantics {
|
||||
VariableSemantics::FloatParameter => {
|
||||
UniqueSemantics::FloatParameter => {
|
||||
let offset = offset_type(range.offset);
|
||||
if let Some(meta) = meta.parameter_meta.get(&name) {
|
||||
if offset != meta.offset {
|
||||
|
@ -335,10 +330,10 @@ where
|
|||
fragment: offset,
|
||||
});
|
||||
}
|
||||
if meta.components != typeinfo.size {
|
||||
return Err(ShaderReflectError::MismatchedComponent {
|
||||
if meta.size != typeinfo.size {
|
||||
return Err(ShaderReflectError::MismatchedSize {
|
||||
semantic: name,
|
||||
vertex: meta.components,
|
||||
vertex: meta.size,
|
||||
fragment: typeinfo.size,
|
||||
});
|
||||
}
|
||||
|
@ -348,14 +343,14 @@ where
|
|||
VariableMeta {
|
||||
id: name,
|
||||
offset,
|
||||
components: typeinfo.size,
|
||||
size: typeinfo.size,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
semantics => {
|
||||
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 {
|
||||
return Err(ShaderReflectError::MismatchedOffset {
|
||||
semantic: name,
|
||||
|
@ -363,20 +358,20 @@ where
|
|||
fragment: offset,
|
||||
});
|
||||
}
|
||||
if meta.components != typeinfo.size * typeinfo.columns {
|
||||
return Err(ShaderReflectError::MismatchedComponent {
|
||||
if meta.size != typeinfo.size * typeinfo.columns {
|
||||
return Err(ShaderReflectError::MismatchedSize {
|
||||
semantic: name,
|
||||
vertex: meta.components,
|
||||
vertex: meta.size,
|
||||
fragment: typeinfo.size,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
meta.variable_meta.insert(
|
||||
meta.unique_meta.insert(
|
||||
*semantics,
|
||||
VariableMeta {
|
||||
id: name,
|
||||
offset,
|
||||
components: typeinfo.size * typeinfo.columns,
|
||||
size: typeinfo.size * typeinfo.columns,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -493,8 +488,8 @@ where
|
|||
&self,
|
||||
texture: TextureData,
|
||||
pass_number: usize,
|
||||
semantics: &ReflectSemantics,
|
||||
meta: &mut ReflectMeta,
|
||||
semantics: &ShaderSemantics,
|
||||
meta: &mut BindingMeta,
|
||||
) -> Result<(), ShaderReflectError> {
|
||||
let Some(semantic) = semantics.texture_semantics.get_texture_semantic(texture.name) else {
|
||||
return Err(SemanticErrorBlame::Fragment.error(SemanticsErrorKind::UnknownSemantics(texture.name.to_string())))
|
||||
|
@ -609,7 +604,7 @@ where
|
|||
fn reflect(
|
||||
&mut self,
|
||||
pass_number: usize,
|
||||
semantics: &ReflectSemantics,
|
||||
semantics: &ShaderSemantics,
|
||||
) -> Result<ShaderReflection, ShaderReflectError> {
|
||||
let vertex_res = self.vertex.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 mut meta = ReflectMeta::default();
|
||||
let mut meta = BindingMeta::default();
|
||||
|
||||
if let Some(ubo) = vertex_ubo {
|
||||
Self::reflect_buffer_range_metas(
|
||||
|
@ -700,7 +695,7 @@ where
|
|||
|
||||
impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
|
||||
type Options = glsl::Version;
|
||||
type Context = GlslangGlslContext;
|
||||
type Context = CrossGlslContext;
|
||||
|
||||
fn compile(
|
||||
mut self,
|
||||
|
@ -820,9 +815,9 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
|
|||
Ok(ShaderCompilerOutput {
|
||||
vertex: self.vertex.compile()?,
|
||||
fragment: self.fragment.compile()?,
|
||||
context: GlslangGlslContext {
|
||||
context: CrossGlslContext {
|
||||
sampler_bindings: texture_fixups,
|
||||
compiler: CompiledProgram {
|
||||
artifact: CompiledProgram {
|
||||
vertex: CompiledAst(self.vertex),
|
||||
fragment: CompiledAst(self.fragment),
|
||||
},
|
||||
|
@ -833,12 +828,12 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
|
|||
|
||||
impl CompileShader<HLSL> for CrossReflect<hlsl::Target> {
|
||||
type Options = Option<()>;
|
||||
type Context = GlslangHlslContext;
|
||||
type Context = CrossHlslContext;
|
||||
|
||||
fn compile(
|
||||
mut self,
|
||||
_options: Self::Options,
|
||||
) -> Result<ShaderCompilerOutput<String, GlslangHlslContext>, ShaderCompileError> {
|
||||
) -> Result<ShaderCompilerOutput<String, CrossHlslContext>, ShaderCompileError> {
|
||||
let mut options = hlsl::CompilerOptions::default();
|
||||
options.shader_model = ShaderModel::V5_0;
|
||||
|
||||
|
@ -848,7 +843,7 @@ impl CompileShader<HLSL> for CrossReflect<hlsl::Target> {
|
|||
Ok(ShaderCompilerOutput {
|
||||
vertex: self.vertex.compile()?,
|
||||
fragment: self.fragment.compile()?,
|
||||
context: GlslangHlslContext {
|
||||
context: CrossHlslContext {
|
||||
compiler: CompiledProgram {
|
||||
vertex: CompiledAst(self.vertex),
|
||||
fragment: CompiledAst(self.fragment),
|
||||
|
@ -867,7 +862,7 @@ mod test {
|
|||
use crate::back::CompileShader;
|
||||
use crate::front::shaderc::GlslangCompilation;
|
||||
use crate::reflect::semantics::{
|
||||
ReflectSemantics, SemanticMap, UniformSemantic, VariableSemantics,
|
||||
ShaderSemantics, Semantic, UniformSemantic, UniqueSemantics,
|
||||
};
|
||||
use librashader_preprocess::ShaderSource;
|
||||
use spirv_cross::glsl;
|
||||
|
@ -881,8 +876,8 @@ mod test {
|
|||
for (_index, param) in result.parameters.iter().enumerate() {
|
||||
uniform_semantics.insert(
|
||||
param.id.clone(),
|
||||
UniformSemantic::Variable(SemanticMap {
|
||||
semantics: VariableSemantics::FloatParameter,
|
||||
UniformSemantic::Unique(Semantic {
|
||||
semantics: UniqueSemantics::FloatParameter,
|
||||
index: (),
|
||||
}),
|
||||
);
|
||||
|
@ -892,7 +887,7 @@ mod test {
|
|||
let _shader_reflection = reflect
|
||||
.reflect(
|
||||
0,
|
||||
&ReflectSemantics {
|
||||
&ShaderSemantics {
|
||||
uniform_semantics,
|
||||
texture_semantics: Default::default(),
|
||||
},
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
use crate::error::ShaderReflectError;
|
||||
use crate::reflect::semantics::{
|
||||
SemanticMap, TextureBinding, TextureSemantics, TextureSizeMeta, VariableMeta, VariableSemantics,
|
||||
Semantic, TextureBinding, TextureSemantics, TextureSizeMeta, UniqueSemantics, VariableMeta,
|
||||
};
|
||||
use rustc_hash::FxHashMap;
|
||||
use semantics::ReflectSemantics;
|
||||
use semantics::ShaderSemantics;
|
||||
|
||||
/// Reflection via spirv-cross.
|
||||
pub mod cross;
|
||||
|
||||
/// Shader semantics and reflection information.
|
||||
pub mod semantics;
|
||||
|
||||
#[cfg(feature = "unstable-rust-pipeline")]
|
||||
|
@ -14,22 +16,17 @@ mod naga;
|
|||
#[cfg(feature = "unstable-rust-pipeline")]
|
||||
mod rspirv;
|
||||
|
||||
/// A trait for compilation outputs that can provide reflection information.
|
||||
pub trait ReflectShader {
|
||||
/// Reflect the shader as the given pass within the shader preset, against the provided
|
||||
/// semantic map.
|
||||
fn reflect(
|
||||
&mut self,
|
||||
pass_number: usize,
|
||||
semantics: &ReflectSemantics,
|
||||
semantics: &ShaderSemantics,
|
||||
) -> 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;
|
||||
|
||||
#[inline(always)]
|
||||
|
|
|
@ -1,65 +1,91 @@
|
|||
use crate::reflect::ReflectMeta;
|
||||
use bitflags::bitflags;
|
||||
use rustc_hash::FxHashMap;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// The maximum number of bindings allowed in a shader.
|
||||
pub const MAX_BINDINGS_COUNT: u32 = 16;
|
||||
/// The maximum size of the push constant range.
|
||||
pub const MAX_PUSH_BUFFER_SIZE: u32 = 128;
|
||||
|
||||
/// The type of a uniform.
|
||||
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone, Hash)]
|
||||
pub enum UniformType {
|
||||
MVP,
|
||||
Size,
|
||||
/// A matrix of 4x4 floats (`mat4`).
|
||||
Mat4,
|
||||
/// A vector of 4 floats (`vec4`).
|
||||
Vec4,
|
||||
/// An unsigned integer (`uint`).
|
||||
Unsigned,
|
||||
/// A signed integer (`int`).
|
||||
Signed,
|
||||
/// A floating point number (`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)]
|
||||
#[repr(i32)]
|
||||
pub enum VariableSemantics {
|
||||
pub enum UniqueSemantics {
|
||||
// mat4, MVP
|
||||
/// The Model View Projection matrix for the frame.
|
||||
MVP = 0,
|
||||
// vec4, viewport size of current pass
|
||||
/// The viewport size of the current pass.
|
||||
Output = 1,
|
||||
// vec4, viewport size of final pass
|
||||
/// The viewport size of the final pass.
|
||||
FinalViewport = 2,
|
||||
// uint, frame count with modulo
|
||||
/// The frame count, possibly with shader-defined modulo.
|
||||
FrameCount = 3,
|
||||
// int, frame direction
|
||||
/// The frame direction.
|
||||
FrameDirection = 4,
|
||||
/// A user defined float parameter.
|
||||
// float, user defined parameter, array
|
||||
FloatParameter = 5,
|
||||
}
|
||||
|
||||
impl VariableSemantics {
|
||||
pub const fn semantics(self) -> SemanticMap<VariableSemantics, ()> {
|
||||
SemanticMap {
|
||||
impl UniqueSemantics {
|
||||
/// Produce a `Semantic` for this `UniqueSemantics`.
|
||||
pub const fn semantics(self) -> Semantic<UniqueSemantics, ()> {
|
||||
Semantic {
|
||||
semantics: self,
|
||||
index: (),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the type of the uniform when bound.
|
||||
pub const fn binding_type(&self) -> UniformType {
|
||||
match self {
|
||||
VariableSemantics::MVP => UniformType::MVP,
|
||||
VariableSemantics::Output => UniformType::Size,
|
||||
VariableSemantics::FinalViewport => UniformType::Size,
|
||||
VariableSemantics::FrameCount => UniformType::Unsigned,
|
||||
VariableSemantics::FrameDirection => UniformType::Signed,
|
||||
VariableSemantics::FloatParameter => UniformType::Float,
|
||||
UniqueSemantics::MVP => UniformType::Mat4,
|
||||
UniqueSemantics::Output => UniformType::Vec4,
|
||||
UniqueSemantics::FinalViewport => UniformType::Vec4,
|
||||
UniqueSemantics::FrameCount => UniformType::Unsigned,
|
||||
UniqueSemantics::FrameDirection => UniformType::Signed,
|
||||
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)]
|
||||
#[repr(i32)]
|
||||
pub enum TextureSemantics {
|
||||
/// The original input of the filter chain.
|
||||
Original = 0,
|
||||
/// The input from the previous shader pass, or the input on the first shader pass.
|
||||
Source = 1,
|
||||
/// The input frames from previous frames.
|
||||
OriginalHistory = 2,
|
||||
/// The output from previous shader passes in the same frame.
|
||||
PassOutput = 3,
|
||||
/// The output from previous shader passes in the previous frame.
|
||||
PassFeedback = 4,
|
||||
/// A user provided lookup texture.
|
||||
User = 5,
|
||||
}
|
||||
|
||||
|
@ -76,6 +102,7 @@ impl TextureSemantics {
|
|||
TextureSemantics::User,
|
||||
];
|
||||
|
||||
/// Get the name of the size uniform for this semantics when bound.
|
||||
pub fn size_uniform_name(&self) -> &'static str {
|
||||
match self {
|
||||
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 {
|
||||
match self {
|
||||
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)
|
||||
}
|
||||
|
||||
pub const fn semantics(self, index: usize) -> SemanticMap<TextureSemantics> {
|
||||
SemanticMap {
|
||||
/// Produce a `Semantic` for this `TextureSemantics` of the given index.
|
||||
pub const fn semantics(self, index: usize) -> Semantic<TextureSemantics> {
|
||||
Semantic {
|
||||
semantics: self,
|
||||
index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TypeInfo {
|
||||
pub(crate) struct TypeInfo {
|
||||
pub size: u32,
|
||||
pub columns: u32,
|
||||
}
|
||||
pub trait ValidateTypeSemantics<T> {
|
||||
|
||||
pub(crate) trait ValidateTypeSemantics<T> {
|
||||
fn validate_type(&self, ty: &T) -> Option<TypeInfo>;
|
||||
}
|
||||
|
||||
/// A unit of unique or indexed semantic.
|
||||
#[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,
|
||||
/// The index of the semantic if not unique.
|
||||
pub index: I,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// The pipeline stage for which a uniform is bound.
|
||||
pub struct BindingStage: u8 {
|
||||
const NONE = 0b00000000;
|
||||
const VERTEX = 0b00000001;
|
||||
|
@ -132,64 +169,86 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
impl BindingStage {
|
||||
pub fn clear(&mut self) {
|
||||
self.bits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Reflection information for the Uniform Buffer
|
||||
#[derive(Debug)]
|
||||
pub struct UboReflection {
|
||||
/// The binding point for this UBO.
|
||||
pub binding: u32,
|
||||
/// Get this size of this UBO buffer.
|
||||
/// The size returned by reflection is always aligned to a 16 byte boundary.
|
||||
/// The size of the UBO buffer. UBO sizes returned by reflection is always aligned to a 16 byte boundary.
|
||||
pub size: u32,
|
||||
/// The mask indicating for which stages the UBO should be bound.
|
||||
pub stage_mask: BindingStage,
|
||||
}
|
||||
|
||||
/// Reflection information for the Push Constant Block
|
||||
#[derive(Debug)]
|
||||
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,
|
||||
/// The mask indicating for which stages the Push Constant range should be bound.
|
||||
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)]
|
||||
pub enum MemberOffset {
|
||||
/// The offset of the uniform member within the UBO.
|
||||
Ubo(usize),
|
||||
/// The offset of the uniform member within the Push Constant range.
|
||||
PushConstant(usize),
|
||||
}
|
||||
|
||||
|
||||
/// Reflection information about a non-texture related uniform variable.
|
||||
#[derive(Debug)]
|
||||
pub struct VariableMeta {
|
||||
// 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 components: u32,
|
||||
/// The size of the uniform.
|
||||
pub size: u32,
|
||||
/// The name of the uniform.
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
/// Reflection information about a texture size uniform variable.
|
||||
#[derive(Debug)]
|
||||
pub struct TextureSizeMeta {
|
||||
// this might bite us in the back because retroarch keeps separate UBO/push offsets..
|
||||
/// The offset of this size uniform.
|
||||
pub offset: MemberOffset,
|
||||
/// The mask indicating for which stages the texture size uniform should be bound.
|
||||
pub stage_mask: BindingStage,
|
||||
/// The name of the uniform.
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
/// Reflection information about texture samplers.
|
||||
#[derive(Debug)]
|
||||
pub struct TextureBinding {
|
||||
/// The binding index of the texture.
|
||||
pub binding: u32,
|
||||
}
|
||||
|
||||
/// Reflection information about a shader.
|
||||
#[derive(Debug)]
|
||||
pub struct ShaderReflection {
|
||||
/// Reflection information about the UBO for this shader.
|
||||
pub ubo: Option<UboReflection>,
|
||||
/// Reflection information about the Push Constant range for this shader.
|
||||
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 {
|
||||
/// The offset of this uniform.
|
||||
fn offset(&self) -> MemberOffset;
|
||||
/// The name of this uniform in the shader.
|
||||
fn id(&self) -> &str;
|
||||
}
|
||||
|
||||
|
@ -207,35 +266,36 @@ impl UniformMeta for TextureSizeMeta {
|
|||
fn offset(&self) -> MemberOffset {
|
||||
self.offset
|
||||
}
|
||||
|
||||
fn id(&self) -> &str {
|
||||
&self.id
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TextureSemanticMap<T> {
|
||||
fn get_texture_semantic(&self, name: &str) -> Option<SemanticMap<TextureSemantics>>;
|
||||
/// A trait for maps that can return texture semantic units.
|
||||
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> {
|
||||
fn get_texture_semantic(&self, name: &str) -> Option<SemanticMap<TextureSemantics>> {
|
||||
impl TextureSemanticMap for FxHashMap<String, UniformSemantic> {
|
||||
fn get_texture_semantic(&self, name: &str) -> Option<Semantic<TextureSemantics>> {
|
||||
match self.get(name) {
|
||||
None => {
|
||||
if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS
|
||||
.iter()
|
||||
.find(|f| name.starts_with(f.size_uniform_name()))
|
||||
{
|
||||
if semantics.is_array() {
|
||||
if semantics.is_indexed() {
|
||||
let index = &name[semantics.size_uniform_name().len()..];
|
||||
let Ok(index) = usize::from_str(index) else {
|
||||
return None;
|
||||
};
|
||||
return Some(SemanticMap {
|
||||
return Some(Semantic {
|
||||
semantics: *semantics,
|
||||
index,
|
||||
});
|
||||
} else if name == semantics.size_uniform_name() {
|
||||
return Some(SemanticMap {
|
||||
return Some(Semantic {
|
||||
semantics: *semantics,
|
||||
index: 0,
|
||||
});
|
||||
|
@ -243,29 +303,29 @@ impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, UniformSemantic>
|
|||
}
|
||||
None
|
||||
}
|
||||
Some(UniformSemantic::Variable(_)) => None,
|
||||
Some(UniformSemantic::Unique(_)) => None,
|
||||
Some(UniformSemantic::Texture(texture)) => Some(*texture),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, SemanticMap<TextureSemantics>> {
|
||||
fn get_texture_semantic(&self, name: &str) -> Option<SemanticMap<TextureSemantics>> {
|
||||
impl TextureSemanticMap for FxHashMap<String, Semantic<TextureSemantics>> {
|
||||
fn get_texture_semantic(&self, name: &str) -> Option<Semantic<TextureSemantics>> {
|
||||
match self.get(name) {
|
||||
None => {
|
||||
if let Some(semantics) = TextureSemantics::TEXTURE_SEMANTICS
|
||||
.iter()
|
||||
.find(|f| name.starts_with(f.texture_name()))
|
||||
{
|
||||
if semantics.is_array() {
|
||||
if semantics.is_indexed() {
|
||||
let index = &name[semantics.texture_name().len()..];
|
||||
let Ok(index) = usize::from_str(index) else {return None};
|
||||
return Some(SemanticMap {
|
||||
return Some(Semantic {
|
||||
semantics: *semantics,
|
||||
index,
|
||||
});
|
||||
} else if name == semantics.texture_name() {
|
||||
return Some(SemanticMap {
|
||||
return Some(Semantic {
|
||||
semantics: *semantics,
|
||||
index: 0,
|
||||
});
|
||||
|
@ -278,70 +338,98 @@ impl TextureSemanticMap<UniformSemantic> for FxHashMap<String, SemanticMap<Textu
|
|||
}
|
||||
}
|
||||
|
||||
pub trait VariableSemanticMap<T> {
|
||||
fn get_variable_semantic(&self, name: &str) -> Option<SemanticMap<VariableSemantics, ()>>;
|
||||
/// A trait for maps that can return unique semantic units.
|
||||
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> {
|
||||
fn get_variable_semantic(&self, name: &str) -> Option<SemanticMap<VariableSemantics, ()>> {
|
||||
impl UniqueSemanticMap for FxHashMap<String, UniformSemantic> {
|
||||
fn get_unique_semantic(&self, name: &str) -> Option<Semantic<UniqueSemantics, ()>> {
|
||||
match self.get(name) {
|
||||
// existing uniforms in the semantic map have priority
|
||||
None => match name {
|
||||
"MVP" => Some(SemanticMap {
|
||||
semantics: VariableSemantics::MVP,
|
||||
"MVP" => Some(Semantic {
|
||||
semantics: UniqueSemantics::MVP,
|
||||
index: (),
|
||||
}),
|
||||
"OutputSize" => Some(SemanticMap {
|
||||
semantics: VariableSemantics::Output,
|
||||
"OutputSize" => Some(Semantic {
|
||||
semantics: UniqueSemantics::Output,
|
||||
index: (),
|
||||
}),
|
||||
"FinalViewportSize" => Some(SemanticMap {
|
||||
semantics: VariableSemantics::FinalViewport,
|
||||
"FinalViewportSize" => Some(Semantic {
|
||||
semantics: UniqueSemantics::FinalViewport,
|
||||
index: (),
|
||||
}),
|
||||
"FrameCount" => Some(SemanticMap {
|
||||
semantics: VariableSemantics::FrameCount,
|
||||
"FrameCount" => Some(Semantic {
|
||||
semantics: UniqueSemantics::FrameCount,
|
||||
index: (),
|
||||
}),
|
||||
"FrameDirection" => Some(SemanticMap {
|
||||
semantics: VariableSemantics::FrameDirection,
|
||||
"FrameDirection" => Some(Semantic {
|
||||
semantics: UniqueSemantics::FrameDirection,
|
||||
index: (),
|
||||
}),
|
||||
_ => None,
|
||||
},
|
||||
Some(UniformSemantic::Variable(variable)) => Some(*variable),
|
||||
Some(UniformSemantic::Unique(variable)) => Some(*variable),
|
||||
Some(UniformSemantic::Texture(_)) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Semantic assignment of a shader uniform to filter chain semantics.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum UniformSemantic {
|
||||
Variable(SemanticMap<VariableSemantics, ()>),
|
||||
Texture(SemanticMap<TextureSemantics>),
|
||||
/// A unique semantic.
|
||||
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)]
|
||||
pub struct ReflectSemantics {
|
||||
pub struct ShaderSemantics {
|
||||
/// A map of uniform names to filter chain semantics.
|
||||
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)]
|
||||
pub enum UniformBinding {
|
||||
/// A user parameter (`float`) binding.
|
||||
Parameter(String),
|
||||
SemanticVariable(VariableSemantics),
|
||||
TextureSize(SemanticMap<TextureSemantics>),
|
||||
/// A known semantic binding.
|
||||
SemanticVariable(UniqueSemantics),
|
||||
/// A texture size (`float4`) binding.
|
||||
TextureSize(Semantic<TextureSemantics>),
|
||||
}
|
||||
|
||||
impl From<VariableSemantics> for UniformBinding {
|
||||
fn from(value: VariableSemantics) -> Self {
|
||||
impl From<UniqueSemantics> for UniformBinding {
|
||||
fn from(value: UniqueSemantics) -> Self {
|
||||
UniformBinding::SemanticVariable(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SemanticMap<TextureSemantics>> for UniformBinding {
|
||||
fn from(value: SemanticMap<TextureSemantics>) -> Self {
|
||||
impl From<Semantic<TextureSemantics>> for UniformBinding {
|
||||
fn from(value: Semantic<TextureSemantics>) -> Self {
|
||||
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>,
|
||||
}
|
||||
|
|
|
@ -3,13 +3,13 @@ use librashader_common::image::{Image, UVDirection};
|
|||
use librashader_common::{ImageFormat, Size};
|
||||
use librashader_preprocess::ShaderSource;
|
||||
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::{CompileShader, CompilerBackend, FromCompilation};
|
||||
use librashader_reflect::front::shaderc::GlslangCompilation;
|
||||
use librashader_reflect::reflect::semantics::{
|
||||
ReflectSemantics, SemanticMap, TextureSemantics, UniformBinding, UniformSemantic,
|
||||
VariableSemantics,
|
||||
ShaderSemantics, Semantic, TextureSemantics, UniformBinding, UniformSemantic,
|
||||
UniqueSemantics,
|
||||
};
|
||||
use librashader_reflect::reflect::ReflectShader;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
@ -45,7 +45,7 @@ type ShaderPassMeta = (
|
|||
ShaderPassConfig,
|
||||
ShaderSource,
|
||||
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(
|
||||
device: &ID3D11Device,
|
||||
passes: Vec<ShaderPassMeta>,
|
||||
semantics: &ReflectSemantics,
|
||||
semantics: &ShaderSemantics,
|
||||
) -> error::Result<Vec<FilterPass>> {
|
||||
// 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);
|
||||
}
|
||||
|
||||
for (semantics, param) in &reflection.meta.variable_meta {
|
||||
for (semantics, param) in &reflection.meta.unique_meta {
|
||||
uniform_bindings.insert(UniformBinding::SemanticVariable(*semantics), param.offset);
|
||||
}
|
||||
|
||||
|
@ -414,9 +414,9 @@ impl FilterChain {
|
|||
fn load_preset(
|
||||
passes: Vec<ShaderPassConfig>,
|
||||
textures: &[TextureConfig],
|
||||
) -> error::Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
|
||||
) -> error::Result<(Vec<ShaderPassMeta>, ShaderSemantics)> {
|
||||
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();
|
||||
|
||||
let passes = passes
|
||||
|
@ -431,8 +431,8 @@ impl FilterChain {
|
|||
for parameter in source.parameters.iter() {
|
||||
uniform_semantics.insert(
|
||||
parameter.id.clone(),
|
||||
UniformSemantic::Variable(SemanticMap {
|
||||
semantics: VariableSemantics::FloatParameter,
|
||||
UniformSemantic::Unique(Semantic {
|
||||
semantics: UniqueSemantics::FloatParameter,
|
||||
index: (),
|
||||
}),
|
||||
);
|
||||
|
@ -456,7 +456,7 @@ impl FilterChain {
|
|||
&mut texture_semantics,
|
||||
);
|
||||
|
||||
let semantics = ReflectSemantics {
|
||||
let semantics = ShaderSemantics {
|
||||
uniform_semantics,
|
||||
texture_semantics,
|
||||
};
|
||||
|
|
|
@ -3,10 +3,10 @@ use crate::texture::Texture;
|
|||
use librashader_common::{ImageFormat, Size};
|
||||
use librashader_preprocess::ShaderSource;
|
||||
use librashader_presets::ShaderPassConfig;
|
||||
use librashader_reflect::back::cross::GlslangHlslContext;
|
||||
use librashader_reflect::back::cross::CrossHlslContext;
|
||||
use librashader_reflect::back::ShaderCompilerOutput;
|
||||
use librashader_reflect::reflect::semantics::{
|
||||
BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, VariableSemantics,
|
||||
BindingStage, MemberOffset, TextureBinding, TextureSemantics, UniformBinding, UniqueSemantics,
|
||||
};
|
||||
use librashader_reflect::reflect::ShaderReflection;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
@ -32,7 +32,7 @@ pub struct ConstantBufferBinding {
|
|||
// slang_process.cpp 141
|
||||
pub struct FilterPass {
|
||||
pub reflection: ShaderReflection,
|
||||
pub compiled: ShaderCompilerOutput<String, GlslangHlslContext>,
|
||||
pub compiled: ShaderCompilerOutput<String, CrossHlslContext>,
|
||||
pub vertex_shader: ID3D11VertexShader,
|
||||
pub vertex_layout: ID3D11InputLayout,
|
||||
pub pixel_shader: ID3D11PixelShader,
|
||||
|
@ -95,19 +95,19 @@ impl FilterPass {
|
|||
let mut samplers: [Option<ID3D11SamplerState>; 16] = std::array::from_fn(|_| None);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// bind FinalViewportSize
|
||||
if let Some(offset) = self
|
||||
.uniform_bindings
|
||||
.get(&VariableSemantics::FinalViewport.into())
|
||||
.get(&UniqueSemantics::FinalViewport.into())
|
||||
{
|
||||
self.uniform_storage.bind_vec4(*offset, viewport_size, None);
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ impl FilterPass {
|
|||
// bind FrameCount
|
||||
if let Some(offset) = self
|
||||
.uniform_bindings
|
||||
.get(&VariableSemantics::FrameCount.into())
|
||||
.get(&UniqueSemantics::FrameCount.into())
|
||||
{
|
||||
self.uniform_storage.bind_scalar(*offset, frame_count, None);
|
||||
}
|
||||
|
@ -123,7 +123,7 @@ impl FilterPass {
|
|||
// bind FrameDirection
|
||||
if let Some(offset) = self
|
||||
.uniform_bindings
|
||||
.get(&VariableSemantics::FrameDirection.into())
|
||||
.get(&UniqueSemantics::FrameDirection.into())
|
||||
{
|
||||
self.uniform_storage
|
||||
.bind_scalar(*offset, frame_direction, None);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
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 librashader_preprocess::ShaderSource;
|
||||
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::front::shaderc::GlslangCompilation;
|
||||
use spirv_cross::spirv::Decoration;
|
||||
|
@ -79,7 +79,7 @@ type ShaderPassMeta = (
|
|||
ShaderPassConfig,
|
||||
ShaderSource,
|
||||
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(
|
||||
passes: Vec<ShaderPassConfig>,
|
||||
textures: &[TextureConfig],
|
||||
) -> error::Result<(Vec<ShaderPassMeta>, ReflectSemantics)> {
|
||||
) -> error::Result<(Vec<ShaderPassMeta>, ShaderSemantics)> {
|
||||
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();
|
||||
|
||||
let passes = passes
|
||||
|
@ -171,8 +171,8 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
for parameter in source.parameters.iter() {
|
||||
uniform_semantics.insert(
|
||||
parameter.id.clone(),
|
||||
UniformSemantic::Variable(SemanticMap {
|
||||
semantics: VariableSemantics::FloatParameter,
|
||||
UniformSemantic::Unique(Semantic {
|
||||
semantics: UniqueSemantics::FloatParameter,
|
||||
index: (),
|
||||
}),
|
||||
);
|
||||
|
@ -196,7 +196,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
&mut texture_semantics,
|
||||
);
|
||||
|
||||
let semantics = ReflectSemantics {
|
||||
let semantics = ShaderSemantics {
|
||||
uniform_semantics,
|
||||
texture_semantics,
|
||||
};
|
||||
|
@ -205,9 +205,9 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
}
|
||||
|
||||
fn init_passes(
|
||||
version: GlVersion,
|
||||
version: GlslVersion,
|
||||
passes: Vec<ShaderPassMeta>,
|
||||
semantics: &ReflectSemantics,
|
||||
semantics: &ShaderSemantics,
|
||||
) -> error::Result<Box<[FilterPass<T>]>> {
|
||||
let mut filters = Vec::new();
|
||||
|
||||
|
@ -216,7 +216,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
let reflection = reflect.reflect(index, semantics)?;
|
||||
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.
|
||||
let (program, ubo_location) = unsafe {
|
||||
|
@ -230,7 +230,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
|
|||
for res in vertex_resources.stage_inputs {
|
||||
let loc = glsl
|
||||
.context
|
||||
.compiler
|
||||
.artifact
|
||||
.vertex
|
||||
.get_decoration(res.id, Decoration::Location)?;
|
||||
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(
|
||||
UniformBinding::SemanticVariable(*semantics),
|
||||
(Self::reflect_uniform_location(program, param), param.offset),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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::reflect::ShaderReflection;
|
||||
|
||||
|
@ -7,7 +7,7 @@ use librashader_common::{ImageFormat, Size};
|
|||
use librashader_preprocess::ShaderSource;
|
||||
use librashader_presets::ShaderPassConfig;
|
||||
use librashader_reflect::reflect::semantics::{
|
||||
MemberOffset, TextureSemantics, UniformBinding, VariableSemantics,
|
||||
MemberOffset, TextureSemantics, UniformBinding, UniqueSemantics,
|
||||
};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
|
@ -21,7 +21,7 @@ use crate::texture::Texture;
|
|||
|
||||
pub struct FilterPass<T: GLInterface> {
|
||||
pub reflection: ShaderReflection,
|
||||
pub compiled: ShaderCompilerOutput<String, GlslangGlslContext>,
|
||||
pub compiled: ShaderCompilerOutput<String, CrossGlslContext>,
|
||||
pub program: GLuint,
|
||||
pub ubo_location: UniformLocation<GLuint>,
|
||||
pub ubo_ring: Option<T::UboRing>,
|
||||
|
@ -127,7 +127,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
source: &Texture,
|
||||
) {
|
||||
// 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
|
||||
.bind_mat4(*offset, mvp, location.location());
|
||||
|
@ -135,7 +135,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
|
||||
// bind OutputSize
|
||||
if let Some((location, offset)) =
|
||||
self.uniform_bindings.get(&VariableSemantics::Output.into())
|
||||
self.uniform_bindings.get(&UniqueSemantics::Output.into())
|
||||
{
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset, fb_size, location.location());
|
||||
|
@ -144,7 +144,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
// bind FinalViewportSize
|
||||
if let Some((location, offset)) = self
|
||||
.uniform_bindings
|
||||
.get(&VariableSemantics::FinalViewport.into())
|
||||
.get(&UniqueSemantics::FinalViewport.into())
|
||||
{
|
||||
self.uniform_storage
|
||||
.bind_vec4(*offset, viewport.output.size, location.location());
|
||||
|
@ -153,7 +153,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
// bind FrameCount
|
||||
if let Some((location, offset)) = self
|
||||
.uniform_bindings
|
||||
.get(&VariableSemantics::FrameCount.into())
|
||||
.get(&UniqueSemantics::FrameCount.into())
|
||||
{
|
||||
self.uniform_storage
|
||||
.bind_scalar(*offset, frame_count, location.location());
|
||||
|
@ -162,7 +162,7 @@ impl<T: GLInterface> FilterPass<T> {
|
|||
// bind FrameDirection
|
||||
if let Some((location, offset)) = self
|
||||
.uniform_bindings
|
||||
.get(&VariableSemantics::FrameDirection.into())
|
||||
.get(&UniqueSemantics::FrameDirection.into())
|
||||
{
|
||||
self.uniform_storage
|
||||
.bind_scalar(*offset, frame_direction, location.location());
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use gl::types::{GLenum, GLuint};
|
||||
|
||||
use librashader_reflect::back::cross::GlVersion;
|
||||
use librashader_reflect::back::cross::GlslVersion;
|
||||
|
||||
pub trait RingBuffer<T> {
|
||||
fn current(&self) -> &T;
|
||||
|
@ -69,7 +69,7 @@ pub unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint {
|
|||
shader
|
||||
}
|
||||
|
||||
pub fn gl_get_version() -> GlVersion {
|
||||
pub fn gl_get_version() -> GlslVersion {
|
||||
let mut maj_ver = 0;
|
||||
let mut min_ver = 0;
|
||||
unsafe {
|
||||
|
@ -79,40 +79,40 @@ pub fn gl_get_version() -> GlVersion {
|
|||
|
||||
match maj_ver {
|
||||
3 => match min_ver {
|
||||
3 => GlVersion::V3_30,
|
||||
2 => GlVersion::V1_50,
|
||||
1 => GlVersion::V1_40,
|
||||
0 => GlVersion::V1_30,
|
||||
_ => GlVersion::V1_50,
|
||||
3 => GlslVersion::V3_30,
|
||||
2 => GlslVersion::V1_50,
|
||||
1 => GlslVersion::V1_40,
|
||||
0 => GlslVersion::V1_30,
|
||||
_ => GlslVersion::V1_50,
|
||||
},
|
||||
4 => match min_ver {
|
||||
6 => GlVersion::V4_60,
|
||||
5 => GlVersion::V4_50,
|
||||
4 => GlVersion::V4_40,
|
||||
3 => GlVersion::V4_30,
|
||||
2 => GlVersion::V4_20,
|
||||
1 => GlVersion::V4_10,
|
||||
0 => GlVersion::V4_00,
|
||||
_ => GlVersion::V1_50,
|
||||
6 => GlslVersion::V4_60,
|
||||
5 => GlslVersion::V4_50,
|
||||
4 => GlslVersion::V4_40,
|
||||
3 => GlslVersion::V4_30,
|
||||
2 => GlslVersion::V4_20,
|
||||
1 => GlslVersion::V4_10,
|
||||
0 => GlslVersion::V4_00,
|
||||
_ => 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 {
|
||||
0 => gl_get_version(),
|
||||
300 => GlVersion::V1_30,
|
||||
310 => GlVersion::V1_40,
|
||||
320 => GlVersion::V1_50,
|
||||
330 => GlVersion::V3_30,
|
||||
400 => GlVersion::V4_00,
|
||||
410 => GlVersion::V4_10,
|
||||
420 => GlVersion::V4_20,
|
||||
430 => GlVersion::V4_30,
|
||||
440 => GlVersion::V4_40,
|
||||
450 => GlVersion::V4_50,
|
||||
460 => GlVersion::V4_60,
|
||||
_ => GlVersion::V1_50,
|
||||
300 => GlslVersion::V1_30,
|
||||
310 => GlslVersion::V1_40,
|
||||
320 => GlslVersion::V1_50,
|
||||
330 => GlslVersion::V3_30,
|
||||
400 => GlslVersion::V4_00,
|
||||
410 => GlslVersion::V4_10,
|
||||
420 => GlslVersion::V4_20,
|
||||
430 => GlslVersion::V4_30,
|
||||
440 => GlslVersion::V4_40,
|
||||
450 => GlslVersion::V4_50,
|
||||
460 => GlslVersion::V4_60,
|
||||
_ => GlslVersion::V1_50,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
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;
|
||||
|
||||
/// A map for variable names and uniform semantics
|
||||
pub type UniformSemanticsMap = FxHashMap<String, UniformSemantic>;
|
||||
|
||||
/// 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.
|
||||
pub fn insert_pass_semantics(
|
||||
|
@ -28,14 +28,14 @@ pub fn insert_pass_semantics(
|
|||
// PassOutput
|
||||
texture_semantics.insert(
|
||||
alias.clone(),
|
||||
SemanticMap {
|
||||
Semantic {
|
||||
semantics: TextureSemantics::PassOutput,
|
||||
index,
|
||||
},
|
||||
);
|
||||
uniform_semantics.insert(
|
||||
format!("{alias}Size"),
|
||||
UniformSemantic::Texture(SemanticMap {
|
||||
UniformSemantic::Texture(Semantic {
|
||||
semantics: TextureSemantics::PassOutput,
|
||||
index,
|
||||
}),
|
||||
|
@ -44,14 +44,14 @@ pub fn insert_pass_semantics(
|
|||
// PassFeedback
|
||||
texture_semantics.insert(
|
||||
format!("{alias}Feedback"),
|
||||
SemanticMap {
|
||||
Semantic {
|
||||
semantics: TextureSemantics::PassFeedback,
|
||||
index,
|
||||
},
|
||||
);
|
||||
uniform_semantics.insert(
|
||||
format!("{alias}FeedbackSize"),
|
||||
UniformSemantic::Texture(SemanticMap {
|
||||
UniformSemantic::Texture(Semantic {
|
||||
semantics: TextureSemantics::PassFeedback,
|
||||
index,
|
||||
}),
|
||||
|
@ -67,7 +67,7 @@ pub fn insert_lut_semantics(
|
|||
for (index, texture) in textures.iter().enumerate() {
|
||||
texture_semantics.insert(
|
||||
texture.name.clone(),
|
||||
SemanticMap {
|
||||
Semantic {
|
||||
semantics: TextureSemantics::User,
|
||||
index,
|
||||
},
|
||||
|
@ -75,7 +75,7 @@ pub fn insert_lut_semantics(
|
|||
|
||||
uniform_semantics.insert(
|
||||
format!("{}Size", texture.name),
|
||||
UniformSemantic::Texture(SemanticMap {
|
||||
UniformSemantic::Texture(Semantic {
|
||||
semantics: TextureSemantics::User,
|
||||
index,
|
||||
}),
|
||||
|
|
|
@ -38,27 +38,23 @@ pub mod preprocess {
|
|||
pub mod reflect {
|
||||
/// Supported shader compiler targets.
|
||||
pub mod targets {
|
||||
/// Shader compiler target for GLSL.
|
||||
pub use librashader_reflect::back::targets::GLSL;
|
||||
|
||||
/// Shader compiler target for 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::error::*;
|
||||
|
||||
pub use librashader_reflect::reflect::{
|
||||
semantics, ReflectMeta, ReflectShader, ShaderReflection,
|
||||
ReflectShader, semantics, ShaderReflection,
|
||||
};
|
||||
|
||||
pub use librashader_reflect::back::{
|
||||
targets::OutputTarget, CompileShader, CompilerBackend, FromCompilation,
|
||||
ShaderCompilerOutput,
|
||||
CompilerBackend, CompileShader, FromCompilation, ShaderCompilerOutput,
|
||||
targets::OutputTarget,
|
||||
};
|
||||
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.
|
||||
|
|
Loading…
Add table
Reference in a new issue