ci: add a full test suite for reflecting things

This commit is contained in:
chyyran 2024-02-21 01:00:23 -05:00 committed by Ronny Chan
parent b378c45039
commit 9741ab2cd1
6 changed files with 183 additions and 2 deletions

35
.github/workflows/full-test.yml vendored Normal file
View file

@ -0,0 +1,35 @@
name: integration test shader reflection
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
env:
CARGO_TERM_COLOR: always
jobs:
approve-full-test:
name: "approval"
runs-on: ubuntu-latest
steps:
- name: Approve
run: echo Full test suite needs approval by a maintainer
test:
environment:
name: full-test
runs-on: windows-latest
needs: [approve-full-test]
continue-on-error: false
steps:
- name: Checkout repository
uses: actions/checkout@v3
with:
submodules: recursive
- name: Install nightly Rust
uses: actions-rs/toolchain@v1.0.6
with:
toolchain: nightly
override: true
- name: Test
run: cargo test -p librashader --test reflect -- --nocapture

3
Cargo.lock generated
View file

@ -1462,6 +1462,7 @@ name = "librashader"
version = "0.2.2"
dependencies = [
"ash",
"glob",
"halfbrown",
"icrate 0.1.0",
"librashader-cache",
@ -1477,6 +1478,8 @@ dependencies = [
"librashader-runtime-vk",
"librashader-runtime-wgpu",
"objc2 0.5.0",
"once_cell",
"rayon",
"wgpu",
"wgpu-types",
"windows 0.48.0",

View file

@ -741,6 +741,7 @@ mod test {
use crate::front::{Glslang, ShaderInputCompiler};
use crate::reflect::semantics::{Semantic, ShaderSemantics, UniformSemantic, UniqueSemantics};
use librashader_common::map::FastHashMap;
use librashader_preprocess::ShaderSource;
use spirv_cross::glsl;
use spirv_cross::glsl::{CompilerOptions, Version};
@ -748,7 +749,7 @@ mod test {
#[test]
pub fn test_into() {
let result = ShaderSource::load("../test/basic.slang").unwrap();
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut uniform_semantics: FastHashMap<String, UniformSemantic> = Default::default();
for (_index, param) in result.parameters.iter().enumerate() {
uniform_semantics.insert(

View file

@ -74,6 +74,11 @@ full = ["runtime-all", "reflect-all", "preprocess", "presets"]
# cache hack
docsrs = ["librashader-cache/docsrs", "objc2/unstable-docsrs"]
[dev-dependencies]
glob = "0.3.1"
rayon = "1.6.1"
once_cell = "1.19.0"
[package.metadata.docs.rs]
targets = [ "x86_64-pc-windows-msvc",
"x86_64-unknown-linux-gnu",

View file

@ -141,9 +141,9 @@ pub mod reflect {
pub use librashader_reflect::back::targets::DXIL;
pub use librashader_reflect::back::targets::GLSL;
pub use librashader_reflect::back::targets::HLSL;
pub use librashader_reflect::back::targets::MSL;
pub use librashader_reflect::back::targets::SPIRV;
pub use librashader_reflect::back::targets::WGSL;
pub use librashader_reflect::back::targets::MSL;
}
pub use librashader_reflect::error::*;

View file

@ -0,0 +1,137 @@
use glob::glob;
use librashader::preprocess::ShaderSource;
use librashader::presets::ShaderPreset;
use rayon::prelude::*;
use std::error::Error;
use std::path::PathBuf;
use std::sync::RwLock;
use librashader::reflect::cross::SpirvCross;
use librashader::reflect::naga::Naga;
use librashader::reflect::targets::*;
use librashader::reflect::CompilePresetTarget;
use librashader::reflect::FromCompilation;
use librashader::reflect::OutputTarget;
use librashader::reflect::SpirvCompilation;
use once_cell::sync::Lazy;
static ALL_SLANG_PRESETS: Lazy<RwLock<Vec<(PathBuf, ShaderPreset)>>> =
Lazy::new(|| RwLock::new(collect_all_loadable_slang_presets()));
fn collect_all_slang_presets() -> Vec<(PathBuf, ShaderPreset)> {
let presets = glob("../test/shaders_slang/**/*.slangp")
.unwrap()
.collect::<Vec<_>>()
.into_par_iter()
.filter_map(|entry| {
if let Ok(path) = entry {
if let Ok(preset) = ShaderPreset::try_parse(&path) {
println!("[INFO] Parsing preset {path:?}");
return Some((path, preset));
}
}
return None;
})
.collect();
presets
}
fn collect_all_loadable_slang_presets() -> Vec<(PathBuf, ShaderPreset)> {
let mut presets = collect_all_slang_presets();
presets.retain(|(_, preset)| {
!preset
.shaders
.par_iter()
.any(|shader| ShaderSource::load(&shader.name).is_err())
});
presets
}
#[test]
pub fn preprocess_all_slang_presets_parsed() {
let presets = collect_all_slang_presets();
for (path, preset) in presets {
preset.shaders.into_par_iter().for_each(|shader| {
if let Err(e) = ShaderSource::load(&shader.name) {
eprintln!(
"[ERROR] Failed to preprocess shader {} from preset {}: {:?}",
shader.name.display(),
path.display(),
e
);
}
})
}
}
fn compile_presets<O: OutputTarget, R>()
where
O: Sized,
O: FromCompilation<SpirvCompilation, R>,
{
let presets = ALL_SLANG_PRESETS.read().unwrap();
presets.par_iter().for_each(|(path, preset)| {
println!(
"[INFO] Compiling {path:?} into {} reflecting with {}",
std::any::type_name::<O>(),
std::any::type_name::<R>()
);
if let Err(e) = O::compile_preset_passes::<SpirvCompilation, R, Box<dyn Error>>(
preset.shaders.clone(),
&preset.textures,
) {
eprintln!("[ERROR] {:?} ({path:?})", e);
}
});
}
#[test]
#[cfg(feature = "reflect-cross")]
pub fn compile_all_slang_presets_spirv_cross() {
compile_presets::<SPIRV, SpirvCross>();
}
#[test]
#[cfg(feature = "reflect-cross")]
pub fn compile_all_slang_presets_hlsl_cross() {
compile_presets::<HLSL, SpirvCross>();
}
#[test]
#[cfg(feature = "reflect-cross")]
pub fn compile_all_slang_presets_glsl_cross() {
compile_presets::<GLSL, SpirvCross>();
}
#[test]
#[cfg(feature = "reflect-cross")]
pub fn compile_all_slang_presets_msl_cross() {
compile_presets::<MSL, SpirvCross>();
}
#[test]
#[cfg(all(target_os = "windows", feature = "reflect-dxil"))]
pub fn compile_all_slang_presets_dxil_cross() {
compile_presets::<DXIL, SpirvCross>();
}
#[test]
#[cfg(feature = "reflect-naga")]
pub fn compile_all_slang_presets_spirv_naga() {
compile_presets::<SPIRV, Naga>();
}
#[test]
#[cfg(feature = "reflect-naga")]
pub fn compile_all_slang_presets_msl_naga() {
compile_presets::<MSL, Naga>();
}
#[test]
#[cfg(feature = "reflect-naga")]
pub fn compile_all_slang_presets_wgsl_naga() {
compile_presets::<WGSL, Naga>();
}