reflect(wgsl): only analyze active ubo members
This commit is contained in:
parent
350508a7aa
commit
cbac011969
50
Cargo.lock
generated
50
Cargo.lock
generated
|
@ -1009,6 +1009,15 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fxhash"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "generic-array"
|
name = "generic-array"
|
||||||
version = "0.14.7"
|
version = "0.14.7"
|
||||||
|
@ -1643,7 +1652,8 @@ dependencies = [
|
||||||
"rspirv",
|
"rspirv",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"serde",
|
"serde",
|
||||||
"spirv",
|
"spirv 0.2.0+1.5.4",
|
||||||
|
"spirv-linker",
|
||||||
"spirv-to-dxil",
|
"spirv-to-dxil",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
@ -1924,7 +1934,7 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"petgraph",
|
"petgraph",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"spirv",
|
"spirv 0.3.0+sdk-1.3.268.0",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
|
@ -2612,12 +2622,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rspirv"
|
name = "rspirv"
|
||||||
version = "0.12.0+sdk-1.3.268.0"
|
version = "0.11.0+1.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "69cf3a93856b6e5946537278df0d3075596371b1950ccff012f02b0f7eafec8d"
|
checksum = "1503993b59ca9ae4127365c3293517576d7ce56be9f3d8abb1625c85ddc583ba"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc-hash",
|
"fxhash",
|
||||||
"spirv",
|
"num-traits",
|
||||||
|
"spirv 0.2.0+1.5.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2816,6 +2827,16 @@ dependencies = [
|
||||||
"lock_api",
|
"lock_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spirv"
|
||||||
|
version = "0.2.0+1.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spirv"
|
name = "spirv"
|
||||||
version = "0.3.0+sdk-1.3.268.0"
|
version = "0.3.0+sdk-1.3.268.0"
|
||||||
|
@ -2825,6 +2846,17 @@ dependencies = [
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spirv-linker"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5d236255ec7387809e18d57221d0fa428d6f909abc88524944cdfb7ebab01acb"
|
||||||
|
dependencies = [
|
||||||
|
"rspirv",
|
||||||
|
"thiserror",
|
||||||
|
"topological-sort",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spirv-to-dxil"
|
name = "spirv-to-dxil"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
|
@ -3023,6 +3055,12 @@ dependencies = [
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "topological-sort"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa7c7f42dea4b1b99439786f5633aeb9c14c1b53f75e282803c2ec2ad545873c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.40"
|
version = "0.1.40"
|
||||||
|
|
|
@ -23,10 +23,11 @@ librashader-preprocess = { path = "../librashader-preprocess", version = "0.2.0-
|
||||||
librashader-presets = { path = "../librashader-presets", version = "0.2.0-rc.2" }
|
librashader-presets = { path = "../librashader-presets", version = "0.2.0-rc.2" }
|
||||||
|
|
||||||
spirv_cross = { package = "librashader-spirv-cross", version = "0.25.1", optional = true }
|
spirv_cross = { package = "librashader-spirv-cross", version = "0.25.1", optional = true }
|
||||||
|
spirv-linker = "0.1.0"
|
||||||
|
|
||||||
naga = { version = "0.19.0", optional = true }
|
naga = { version = "0.19.0", optional = true }
|
||||||
rspirv = { version = "0.12.0", optional = true }
|
rspirv = { version = "0.11.0", optional = true }
|
||||||
spirv = { version = "0.3.0", optional = true}
|
spirv = { version = "0.2.0", optional = true}
|
||||||
|
|
||||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,10 @@ pub enum ShaderReflectError {
|
||||||
#[cfg(feature = "naga")]
|
#[cfg(feature = "naga")]
|
||||||
#[error("naga-spv")]
|
#[error("naga-spv")]
|
||||||
NagaInputError(#[from] naga::front::spv::Error),
|
NagaInputError(#[from] naga::front::spv::Error),
|
||||||
|
/// Error when transpiling from naga
|
||||||
|
#[cfg(feature = "naga")]
|
||||||
|
#[error("naga-spv")]
|
||||||
|
NagaReflectError(#[from] naga::WithSpan<naga::valid::ValidationError>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "unstable-naga")]
|
#[cfg(feature = "unstable-naga")]
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
mod lower_samplers;
|
mod lower_samplers;
|
||||||
pub mod msl;
|
pub mod msl;
|
||||||
pub mod spirv;
|
pub mod spirv;
|
||||||
|
mod trim_unused_inputs;
|
||||||
pub mod wgsl;
|
pub mod wgsl;
|
||||||
|
|
||||||
use crate::error::{SemanticsErrorKind, ShaderReflectError};
|
use crate::error::{SemanticsErrorKind, ShaderReflectError};
|
||||||
|
use bitflags::Flags;
|
||||||
|
|
||||||
use crate::front::SpirvCompilation;
|
use crate::front::SpirvCompilation;
|
||||||
|
use naga::valid::{Capabilities, ModuleInfo, ValidationFlags, Validator};
|
||||||
use naga::{
|
use naga::{
|
||||||
AddressSpace, Binding, GlobalVariable, Handle, ImageClass, Module, ResourceBinding, Scalar,
|
AddressSpace, Binding, Expression, GlobalVariable, Handle, ImageClass, Module, ResourceBinding,
|
||||||
ScalarKind, TypeInner, VectorSize,
|
Scalar, ScalarKind, StructMember, TypeInner, VectorSize,
|
||||||
};
|
};
|
||||||
use rspirv::binary::Assemble;
|
use rspirv::binary::Assemble;
|
||||||
use rspirv::dr::Builder;
|
use rspirv::dr::Builder;
|
||||||
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use crate::reflect::helper::{SemanticErrorBlame, TextureData, UboData};
|
use crate::reflect::helper::{SemanticErrorBlame, TextureData, UboData};
|
||||||
use crate::reflect::semantics::{
|
use crate::reflect::semantics::{
|
||||||
|
@ -602,6 +606,41 @@ impl NagaReflect {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_uniform_names(
|
||||||
|
module: &Module,
|
||||||
|
buffer_handle: Handle<GlobalVariable>,
|
||||||
|
blame: SemanticErrorBlame,
|
||||||
|
) -> Result<FxHashSet<&StructMember>, ShaderReflectError> {
|
||||||
|
let mut names = FxHashSet::default();
|
||||||
|
let ubo = &module.global_variables[buffer_handle];
|
||||||
|
|
||||||
|
let TypeInner::Struct { members, .. } = &module.types[ubo.ty].inner else {
|
||||||
|
return Err(blame.error(SemanticsErrorKind::InvalidResourceType));
|
||||||
|
};
|
||||||
|
|
||||||
|
// struct access is AccessIndex
|
||||||
|
for (_, fun) in module.functions.iter() {
|
||||||
|
for (_, expr) in fun.expressions.iter() {
|
||||||
|
let &Expression::AccessIndex { base, index } = expr else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let &Expression::GlobalVariable(base) = &fun.expressions[base] else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
if base == buffer_handle {
|
||||||
|
let member = members
|
||||||
|
.get(index as usize)
|
||||||
|
.ok_or(blame.error(SemanticsErrorKind::InvalidRange(index)))?;
|
||||||
|
names.insert(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(names)
|
||||||
|
}
|
||||||
|
|
||||||
fn reflect_buffer_struct_members(
|
fn reflect_buffer_struct_members(
|
||||||
module: &Module,
|
module: &Module,
|
||||||
resource: Handle<GlobalVariable>,
|
resource: Handle<GlobalVariable>,
|
||||||
|
@ -611,7 +650,10 @@ impl NagaReflect {
|
||||||
offset_type: UniformMemberBlock,
|
offset_type: UniformMemberBlock,
|
||||||
blame: SemanticErrorBlame,
|
blame: SemanticErrorBlame,
|
||||||
) -> Result<(), ShaderReflectError> {
|
) -> Result<(), ShaderReflectError> {
|
||||||
|
let reachable = Self::collect_uniform_names(&module, resource, blame)?;
|
||||||
|
|
||||||
let resource = &module.global_variables[resource];
|
let resource = &module.global_variables[resource];
|
||||||
|
|
||||||
let TypeInner::Struct { members, .. } = &module.types[resource.ty].inner else {
|
let TypeInner::Struct { members, .. } = &module.types[resource.ty].inner else {
|
||||||
return Err(blame.error(SemanticsErrorKind::InvalidResourceType));
|
return Err(blame.error(SemanticsErrorKind::InvalidResourceType));
|
||||||
};
|
};
|
||||||
|
@ -620,6 +662,11 @@ impl NagaReflect {
|
||||||
let Some(name) = member.name.clone() else {
|
let Some(name) = member.name.clone() else {
|
||||||
return Err(blame.error(SemanticsErrorKind::InvalidRange(member.offset)));
|
return Err(blame.error(SemanticsErrorKind::InvalidRange(member.offset)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !reachable.contains(member) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let member_type = &module.types[member.ty].inner;
|
let member_type = &module.types[member.ty].inner;
|
||||||
|
|
||||||
if let Some(parameter) = semantics.uniform_semantics.get_unique_semantic(&name) {
|
if let Some(parameter) = semantics.uniform_semantics.get_unique_semantic(&name) {
|
||||||
|
@ -884,7 +931,6 @@ impl ReflectShader for NagaReflect {
|
||||||
});
|
});
|
||||||
|
|
||||||
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 = BindingMeta::default();
|
let mut meta = BindingMeta::default();
|
||||||
|
|
||||||
if let Some(ubo) = vertex_ubo {
|
if let Some(ubo) = vertex_ubo {
|
||||||
|
@ -965,6 +1011,10 @@ impl ReflectShader for NagaReflect {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use crate::reflect::semantics::{Semantic, TextureSemantics, UniformSemantic};
|
||||||
|
use librashader_common::map::FastHashMap;
|
||||||
|
use librashader_preprocess::ShaderSource;
|
||||||
|
use librashader_presets::ShaderPreset;
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
// pub fn test_into() {
|
// pub fn test_into() {
|
||||||
|
@ -983,4 +1033,19 @@ mod test {
|
||||||
//
|
//
|
||||||
// println!("{outputs:#?}");
|
// println!("{outputs:#?}");
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// #[test]
|
||||||
|
// pub fn mega_bezel_reflect() {
|
||||||
|
// let preset = ShaderPreset::try_parse(
|
||||||
|
// "../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
||||||
|
// )
|
||||||
|
// .unwrap();
|
||||||
|
//
|
||||||
|
// let mut uniform_semantics: FastHashMap<String, UniformSemantic> = Default::default();
|
||||||
|
// let mut texture_semantics: FastHashMap<String, Semantic<TextureSemantics>> = Default::default();
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
129
librashader-reflect/src/reflect/naga/trim_unused_inputs.rs
Normal file
129
librashader-reflect/src/reflect/naga/trim_unused_inputs.rs
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
use rspirv::dr::{Builder, Module, Operand};
|
||||||
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
use spirv::{Op, StorageClass};
|
||||||
|
|
||||||
|
pub struct LinkInputs<'a> {
|
||||||
|
pub frag_builder: &'a mut Builder,
|
||||||
|
pub vert: &'a Module,
|
||||||
|
|
||||||
|
pub inputs: FxHashMap<spirv::Word, spirv::Word>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LinkInputs<'a> {
|
||||||
|
fn find_location(module: &Module, id: spirv::Word) -> Option<u32> {
|
||||||
|
module.annotations.iter().find_map(|op| {
|
||||||
|
if op.class.opcode != Op::Decorate {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
eprintln!("{:?}", op);
|
||||||
|
return None;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(vert: &'a Module, frag: &'a mut Builder) -> Self {
|
||||||
|
let mut inputs = FxHashMap::default();
|
||||||
|
|
||||||
|
for global in frag.module_ref().types_global_values.iter() {
|
||||||
|
if global.class.opcode == spirv::Op::Variable
|
||||||
|
&& global.operands[0] == Operand::StorageClass(StorageClass::Input)
|
||||||
|
{
|
||||||
|
if let Some(id) = global.result_id {
|
||||||
|
inputs.insert(id, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// for global in vert.types_global_values.iter() {
|
||||||
|
// if global.class.opcode == spirv::Op::Variable
|
||||||
|
// && global.operands[0] == Operand::StorageClass(StorageClass::Output)
|
||||||
|
// {
|
||||||
|
// if let Some(id) = global.result_id {
|
||||||
|
// inputs.insert(id, 0);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
let mut val = Self {
|
||||||
|
frag_builder: frag,
|
||||||
|
vert,
|
||||||
|
inputs,
|
||||||
|
};
|
||||||
|
val
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn do_pass(&mut self) {
|
||||||
|
let functions = &self.frag_builder.module_ref().functions;
|
||||||
|
|
||||||
|
// literally if it has any reference at all we can keep it
|
||||||
|
for function in functions {
|
||||||
|
for param in &function.parameters {
|
||||||
|
for op in ¶m.operands {
|
||||||
|
if let Some(word) = op.id_ref_any() {
|
||||||
|
if self.inputs.contains_key(&word) {
|
||||||
|
self.inputs.remove(&word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for block in &function.blocks {
|
||||||
|
for inst in &block.instructions {
|
||||||
|
for op in &inst.operands {
|
||||||
|
if let Some(word) = op.id_ref_any() {
|
||||||
|
if self.inputs.contains_key(&word) {
|
||||||
|
self.inputs.remove(&word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok well guess we dont
|
||||||
|
|
||||||
|
self.frag_builder.module_mut().debug_names.retain(|instr| {
|
||||||
|
for op in &instr.operands {
|
||||||
|
if let Some(word) = op.id_ref_any() {
|
||||||
|
if self.inputs.contains_key(&word) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
self.frag_builder.module_mut().annotations.retain(|instr| {
|
||||||
|
for op in &instr.operands {
|
||||||
|
if let Some(word) = op.id_ref_any() {
|
||||||
|
if self.inputs.contains_key(&word) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
for entry_point in self.frag_builder.module_mut().entry_points.iter_mut() {
|
||||||
|
entry_point.operands.retain(|op| {
|
||||||
|
if let Some(word) = op.id_ref_any() {
|
||||||
|
if self.inputs.contains_key(&word) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
self.frag_builder
|
||||||
|
.module_mut()
|
||||||
|
.types_global_values
|
||||||
|
.retain(|instr| {
|
||||||
|
let Some(id) = instr.result_id else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
!self.inputs.contains_key(&id)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,8 +4,8 @@ use crate::back::{CompileShader, ShaderCompilerOutput};
|
||||||
use crate::error::ShaderCompileError;
|
use crate::error::ShaderCompileError;
|
||||||
use crate::reflect::naga::{NagaLoweringOptions, NagaReflect};
|
use crate::reflect::naga::{NagaLoweringOptions, NagaReflect};
|
||||||
use naga::back::wgsl::WriterFlags;
|
use naga::back::wgsl::WriterFlags;
|
||||||
use naga::valid::{Capabilities, ValidationFlags};
|
use naga::valid::{Capabilities, ModuleInfo, ValidationFlags, Validator};
|
||||||
use naga::Module;
|
use naga::{Expression, Module, Statement};
|
||||||
|
|
||||||
impl CompileShader<WGSL> for NagaReflect {
|
impl CompileShader<WGSL> for NagaReflect {
|
||||||
type Options = NagaLoweringOptions;
|
type Options = NagaLoweringOptions;
|
||||||
|
@ -15,19 +15,20 @@ impl CompileShader<WGSL> for NagaReflect {
|
||||||
mut self,
|
mut self,
|
||||||
options: Self::Options,
|
options: Self::Options,
|
||||||
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
|
) -> Result<ShaderCompilerOutput<String, Self::Context>, ShaderCompileError> {
|
||||||
fn write_wgsl(module: &Module) -> Result<String, ShaderCompileError> {
|
fn write_wgsl(module: &Module, info: &ModuleInfo) -> Result<String, ShaderCompileError> {
|
||||||
let mut valid =
|
let wgsl = naga::back::wgsl::write_string(&module, &info, WriterFlags::empty())?;
|
||||||
naga::valid::Validator::new(ValidationFlags::all(), Capabilities::empty());
|
|
||||||
let info = valid.validate(&module)?;
|
|
||||||
|
|
||||||
let wgsl = naga::back::wgsl::write_string(&module, &info, WriterFlags::EXPLICIT_TYPES)?;
|
|
||||||
Ok(wgsl)
|
Ok(wgsl)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.do_lowering(&options);
|
self.do_lowering(&options);
|
||||||
|
|
||||||
let fragment = write_wgsl(&self.fragment)?;
|
let mut valid = Validator::new(ValidationFlags::all(), Capabilities::empty());
|
||||||
let vertex = write_wgsl(&self.vertex)?;
|
|
||||||
|
let vertex_info = valid.validate(&self.vertex)?;
|
||||||
|
let fragment_info = valid.validate(&self.fragment)?;
|
||||||
|
|
||||||
|
let fragment = write_wgsl(&self.fragment, &fragment_info)?;
|
||||||
|
let vertex = write_wgsl(&self.vertex, &vertex_info)?;
|
||||||
Ok(ShaderCompilerOutput {
|
Ok(ShaderCompilerOutput {
|
||||||
vertex,
|
vertex,
|
||||||
fragment,
|
fragment,
|
||||||
|
|
|
@ -26,7 +26,6 @@ thiserror = "1.0.50"
|
||||||
bytemuck = { version = "1.14.0", features = ["derive"] }
|
bytemuck = { version = "1.14.0", features = ["derive"] }
|
||||||
array-concat = "0.5.2"
|
array-concat = "0.5.2"
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# workaround for docsrs to not build metal-rs.
|
# workaround for docsrs to not build metal-rs.
|
||||||
wgpu_dx12 = ["wgpu/dx12"]
|
wgpu_dx12 = ["wgpu/dx12"]
|
||||||
|
|
|
@ -8,45 +8,45 @@ use wgpu::{Buffer, Device, RenderPass};
|
||||||
// WGPU does vertex expansion
|
// WGPU does vertex expansion
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Copy, Clone, Default, Zeroable, Pod)]
|
#[derive(Debug, Copy, Clone, Default, Zeroable, Pod)]
|
||||||
struct WgpuVertex {
|
pub struct WgpuVertex {
|
||||||
position: [f32; 2],
|
pub position: [f32; 4],
|
||||||
texcoord: [f32; 2],
|
pub texcoord: [f32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
const OFFSCREEN_VBO_DATA: [WgpuVertex; 4] = [
|
const OFFSCREEN_VBO_DATA: [WgpuVertex; 4] = [
|
||||||
WgpuVertex {
|
WgpuVertex {
|
||||||
position: [-1.0, -1.0],
|
position: [-1.0, -1.0, 0.0, 1.0],
|
||||||
texcoord: [0.0, 0.0],
|
texcoord: [0.0, 0.0],
|
||||||
},
|
},
|
||||||
WgpuVertex {
|
WgpuVertex {
|
||||||
position: [-1.0, 1.0],
|
position: [-1.0, 1.0, 0.0, 1.0],
|
||||||
texcoord: [0.0, 1.0],
|
texcoord: [0.0, 1.0],
|
||||||
},
|
},
|
||||||
WgpuVertex {
|
WgpuVertex {
|
||||||
position: [1.0, -1.0],
|
position: [1.0, -1.0, 0.0, 1.0],
|
||||||
texcoord: [1.0, 0.0],
|
texcoord: [1.0, 0.0],
|
||||||
},
|
},
|
||||||
WgpuVertex {
|
WgpuVertex {
|
||||||
position: [1.0, 1.0],
|
position: [1.0, 1.0, 0.0, 1.0],
|
||||||
texcoord: [1.0, 1.0],
|
texcoord: [1.0, 1.0],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const FINAL_VBO_DATA: [WgpuVertex; 4] = [
|
const FINAL_VBO_DATA: [WgpuVertex; 4] = [
|
||||||
WgpuVertex {
|
WgpuVertex {
|
||||||
position: [0.0, 0.0],
|
position: [0.0, 0.0, 0.0, 1.0],
|
||||||
texcoord: [0.0, 0.0],
|
texcoord: [0.0, 0.0],
|
||||||
},
|
},
|
||||||
WgpuVertex {
|
WgpuVertex {
|
||||||
position: [0.0, 1.0],
|
position: [0.0, 1.0, 0.0, 1.0],
|
||||||
texcoord: [0.0, 1.0],
|
texcoord: [0.0, 1.0],
|
||||||
},
|
},
|
||||||
WgpuVertex {
|
WgpuVertex {
|
||||||
position: [1.0, 0.0],
|
position: [1.0, 0.0, 0.0, 1.0],
|
||||||
texcoord: [1.0, 0.0],
|
texcoord: [1.0, 0.0],
|
||||||
},
|
},
|
||||||
WgpuVertex {
|
WgpuVertex {
|
||||||
position: [1.0, 1.0],
|
position: [1.0, 1.0, 0.0, 1.0],
|
||||||
texcoord: [1.0, 1.0],
|
texcoord: [1.0, 1.0],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -15,6 +15,7 @@ use rayon::prelude::*;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use rayon::ThreadPoolBuilder;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::buffer::WgpuStagedBuffer;
|
use crate::buffer::WgpuStagedBuffer;
|
||||||
|
@ -267,63 +268,73 @@ impl FilterChainWgpu {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
let passes_iter = passes.into_iter();
|
let passes_iter = passes.into_iter();
|
||||||
|
|
||||||
let filters: Vec<error::Result<FilterPass>> = passes_iter
|
let thread_pool = ThreadPoolBuilder::new()
|
||||||
.enumerate()
|
.stack_size(10 * 1048576)
|
||||||
.map(|(index, (config, source, mut reflect))| {
|
.build()
|
||||||
let reflection = reflect.reflect(index, semantics)?;
|
.unwrap();
|
||||||
let wgsl = reflect.compile(NagaLoweringOptions {
|
|
||||||
write_pcb_as_ubo: true,
|
|
||||||
sampler_bind_group: 1,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let ubo_size = reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize);
|
let filters = thread_pool.install(|| {
|
||||||
let push_size = reflection
|
let filters: Vec<error::Result<FilterPass>> = passes_iter
|
||||||
.push_constant
|
.enumerate()
|
||||||
.as_ref()
|
.map(|(index, (config, source, mut reflect))| {
|
||||||
.map_or(0, |push| push.size as wgpu::BufferAddress);
|
let reflection = reflect.reflect(index, semantics)?;
|
||||||
|
let wgsl = reflect.compile(NagaLoweringOptions {
|
||||||
|
write_pcb_as_ubo: true,
|
||||||
|
sampler_bind_group: 1,
|
||||||
|
})?;
|
||||||
|
|
||||||
let uniform_storage = UniformStorage::new_with_storage(
|
let ubo_size = reflection.ubo.as_ref().map_or(0, |ubo| ubo.size as usize);
|
||||||
WgpuStagedBuffer::new(
|
let push_size = reflection
|
||||||
&device,
|
.push_constant
|
||||||
wgpu::BufferUsages::UNIFORM,
|
.as_ref()
|
||||||
ubo_size as wgpu::BufferAddress,
|
.map_or(0, |push| push.size as wgpu::BufferAddress);
|
||||||
Some("ubo"),
|
|
||||||
),
|
|
||||||
WgpuStagedBuffer::new(
|
|
||||||
&device,
|
|
||||||
wgpu::BufferUsages::UNIFORM,
|
|
||||||
push_size as wgpu::BufferAddress,
|
|
||||||
Some("push"),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
let uniform_bindings = reflection.meta.create_binding_map(|param| param.offset());
|
let uniform_storage = UniformStorage::new_with_storage(
|
||||||
|
WgpuStagedBuffer::new(
|
||||||
|
&device,
|
||||||
|
wgpu::BufferUsages::UNIFORM,
|
||||||
|
ubo_size as wgpu::BufferAddress,
|
||||||
|
Some("ubo"),
|
||||||
|
),
|
||||||
|
WgpuStagedBuffer::new(
|
||||||
|
&device,
|
||||||
|
wgpu::BufferUsages::UNIFORM,
|
||||||
|
push_size as wgpu::BufferAddress,
|
||||||
|
Some("push"),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
let render_pass_format: Option<TextureFormat> =
|
let uniform_bindings =
|
||||||
if let Some(format) = config.get_format_override() {
|
reflection.meta.create_binding_map(|param| param.offset());
|
||||||
format.into()
|
|
||||||
} else {
|
|
||||||
source.format.into()
|
|
||||||
};
|
|
||||||
|
|
||||||
let graphics_pipeline = WgpuGraphicsPipeline::new(
|
let render_pass_format: Option<TextureFormat> =
|
||||||
Arc::clone(&device),
|
if let Some(format) = config.get_format_override() {
|
||||||
&wgsl,
|
format.into()
|
||||||
&reflection,
|
} else {
|
||||||
render_pass_format.unwrap_or(TextureFormat::Rgba8Unorm),
|
source.format.into()
|
||||||
);
|
};
|
||||||
|
|
||||||
Ok(FilterPass {
|
let graphics_pipeline = WgpuGraphicsPipeline::new(
|
||||||
device: Arc::clone(&device),
|
Arc::clone(&device),
|
||||||
reflection,
|
&wgsl,
|
||||||
uniform_storage,
|
&reflection,
|
||||||
uniform_bindings,
|
render_pass_format.unwrap_or(TextureFormat::Rgba8Unorm),
|
||||||
source,
|
);
|
||||||
config,
|
|
||||||
graphics_pipeline,
|
Ok(FilterPass {
|
||||||
|
device: Arc::clone(&device),
|
||||||
|
reflection,
|
||||||
|
uniform_storage,
|
||||||
|
uniform_bindings,
|
||||||
|
source,
|
||||||
|
config,
|
||||||
|
graphics_pipeline,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
.collect();
|
||||||
.collect();
|
filters
|
||||||
|
});
|
||||||
|
|
||||||
//
|
//
|
||||||
let filters: error::Result<Vec<FilterPass>> = filters.into_iter().collect();
|
let filters: error::Result<Vec<FilterPass>> = filters.into_iter().collect();
|
||||||
let filters = filters?;
|
let filters = filters?;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::draw_quad::WgpuVertex;
|
||||||
use crate::framebuffer::WgpuOutputView;
|
use crate::framebuffer::WgpuOutputView;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use librashader_reflect::back::wgsl::NagaWgslContext;
|
use librashader_reflect::back::wgsl::NagaWgslContext;
|
||||||
|
@ -152,17 +153,19 @@ impl PipelineLayoutObjects {
|
||||||
module: &self.vertex,
|
module: &self.vertex,
|
||||||
entry_point: &self.vertex_entry_name,
|
entry_point: &self.vertex_entry_name,
|
||||||
buffers: &[VertexBufferLayout {
|
buffers: &[VertexBufferLayout {
|
||||||
array_stride: 4 * std::mem::size_of::<f32>() as wgpu::BufferAddress,
|
array_stride: std::mem::size_of::<WgpuVertex>() as wgpu::BufferAddress,
|
||||||
step_mode: wgpu::VertexStepMode::Vertex,
|
step_mode: wgpu::VertexStepMode::Vertex,
|
||||||
attributes: &[
|
attributes: &[
|
||||||
wgpu::VertexAttribute {
|
wgpu::VertexAttribute {
|
||||||
format: wgpu::VertexFormat::Float32x2,
|
format: wgpu::VertexFormat::Float32x4,
|
||||||
offset: 0,
|
offset: bytemuck::offset_of!(WgpuVertex, position)
|
||||||
|
as wgpu::BufferAddress,
|
||||||
shader_location: 0,
|
shader_location: 0,
|
||||||
},
|
},
|
||||||
wgpu::VertexAttribute {
|
wgpu::VertexAttribute {
|
||||||
format: wgpu::VertexFormat::Float32x2,
|
format: wgpu::VertexFormat::Float32x2,
|
||||||
offset: (2 * std::mem::size_of::<f32>()) as wgpu::BufferAddress,
|
offset: bytemuck::offset_of!(WgpuVertex, texcoord)
|
||||||
|
as wgpu::BufferAddress,
|
||||||
shader_location: 1,
|
shader_location: 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -173,7 +176,7 @@ impl PipelineLayoutObjects {
|
||||||
entry_point: &self.fragment_entry_name,
|
entry_point: &self.fragment_entry_name,
|
||||||
targets: &[Some(wgpu::ColorTargetState {
|
targets: &[Some(wgpu::ColorTargetState {
|
||||||
format: framebuffer_format,
|
format: framebuffer_format,
|
||||||
blend: Some(wgpu::BlendState::REPLACE),
|
blend: None,
|
||||||
write_mask: wgpu::ColorWrites::ALL,
|
write_mask: wgpu::ColorWrites::ALL,
|
||||||
})],
|
})],
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -117,11 +117,19 @@ impl<'a> State<'a> {
|
||||||
|
|
||||||
let device = Arc::new(device);
|
let device = Arc::new(device);
|
||||||
let queue = Arc::new(queue);
|
let queue = Arc::new(queue);
|
||||||
|
//
|
||||||
|
// let preset = ShaderPreset::try_parse(
|
||||||
|
// "../test/basic.slangp",
|
||||||
|
// )
|
||||||
|
// .unwrap();
|
||||||
|
|
||||||
let preset = ShaderPreset::try_parse(
|
let preset =
|
||||||
"../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
ShaderPreset::try_parse("../test/shaders_slang/crt/crt-royale.slangp").unwrap();
|
||||||
)
|
|
||||||
.unwrap();
|
// let preset = ShaderPreset::try_parse(
|
||||||
|
// "../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp",
|
||||||
|
// )
|
||||||
|
// .unwrap();
|
||||||
|
|
||||||
let chain = FilterChainWgpu::load_from_preset(
|
let chain = FilterChainWgpu::load_from_preset(
|
||||||
preset,
|
preset,
|
||||||
|
|
|
@ -32,5 +32,5 @@ layout(location = 0) out vec4 FragColor;
|
||||||
layout(binding = 1) uniform sampler2D Source;
|
layout(binding = 1) uniform sampler2D Source;
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
FragColor = texture(Source, vTexCoord) * params.ColorMod * ColorMod2;
|
FragColor = texture(Source, vTexCoord) * params.ColorMod;
|
||||||
}
|
}
|
Loading…
Reference in a new issue