updated API further to just use optionals. Updated tests
This commit is contained in:
@@ -1,14 +1,28 @@
|
||||
use shade_runner as sr;
|
||||
use std::path::PathBuf;
|
||||
use shaderc::ShaderKind;
|
||||
|
||||
fn main() {
|
||||
let project_root = std::env::current_dir().expect("failed to get root directory");
|
||||
|
||||
// let project_root = std::env::current_dir().expect("failed to get root directory");
|
||||
// let mut vert_path = project_root.clone();
|
||||
// vert_path.push(PathBuf::from("examples/shaders/vert.glsl"));
|
||||
// let mut frag_path = project_root.clone();
|
||||
// frag_path.push(PathBuf::from("examples/shaders/frag.glsl"));
|
||||
// let shader = sr::load(vert_path, frag_path).expect("Failed to compile");
|
||||
// let vulkano_entry = sr::parse(&shader).expect("failed to parse");
|
||||
// dbg!(vulkano_entry);
|
||||
// Compile a vertex shader
|
||||
let mut vert_path = project_root.clone();
|
||||
vert_path.push(PathBuf::from("examples/shaders/vert.glsl"));
|
||||
|
||||
let vertex_shader = sr::load(vert_path, None, ShaderKind::Vertex, None)
|
||||
.expect("Failed to compile");
|
||||
|
||||
|
||||
// Compile a fragment shader
|
||||
let mut frag_path = project_root.clone();
|
||||
frag_path.push(PathBuf::from("examples/shaders/frag.glsl"));
|
||||
|
||||
let fragment_shader = sr::load(frag_path, None, ShaderKind::Fragment, None)
|
||||
.expect("Failed to compile");
|
||||
|
||||
let vertex_entry = sr::parse(&vertex_shader).expect("failed to parse");
|
||||
dbg!(vertex_entry);
|
||||
|
||||
let fragment_entry = sr::parse(&fragment_shader).expect("failed to parse");
|
||||
dbg!(fragment_entry);
|
||||
}
|
||||
|
||||
@@ -4,32 +4,56 @@ use shaderc::{ShaderKind, CompileOptions};
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub fn compile<T>(path: T, shader_kind: ShaderKind) -> Result<Vec<u32>, CompileError>
|
||||
pub fn compile<T>(path: T, include_path: Option<T>, shader_kind: ShaderKind, compiler_options: Option<CompileOptions>) -> Result<Vec<u32>, CompileError>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler)?;
|
||||
compile_with_options(path, shader_kind, options)
|
||||
compile_with_options(&read_to_string(&path), include_path, shader_kind, compiler_options)
|
||||
}
|
||||
|
||||
pub fn compile_with_options<T>(path: T, shader_kind: ShaderKind, mut options: CompileOptions) -> Result<Vec<u32>, CompileError>
|
||||
pub fn compile_from_string<T>(input: &str, include_path: Option<T>, shader_kind: ShaderKind, compiler_options: Option<CompileOptions>) -> Result<Vec<u32>, CompileError>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
compile_with_options(input, include_path, shader_kind, compiler_options)
|
||||
}
|
||||
|
||||
pub fn compile_with_options<T>(src: &str, include_path: Option<T>, shader_kind: ShaderKind, options: Option<CompileOptions>)
|
||||
-> Result<Vec<u32>, CompileError>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
// TODO Probably shouldn't create this every time.
|
||||
let mut compiler = shaderc::Compiler::new().ok_or(CompileError::CreateCompiler)?;
|
||||
let mut f = File::open(&path).map_err(CompileError::Open)?;
|
||||
let mut src = String::new();
|
||||
f.read_to_string(&mut src).map_err(CompileError::Open)?;
|
||||
|
||||
let mut options = {
|
||||
match options {
|
||||
None => CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap(),
|
||||
Some(option) => option,
|
||||
}
|
||||
};
|
||||
|
||||
let path = {
|
||||
if let Some(path) = &include_path {
|
||||
options.set_include_callback(|path, include_type, folder_path, depth| {
|
||||
get_include(path, include_type, folder_path, depth)
|
||||
});
|
||||
path.as_ref().to_str().ok_or(CompileError::InvalidPath)?
|
||||
} else {
|
||||
options.set_include_callback(|path, include_type, folder_path, depth| {
|
||||
default_get_include(path, include_type, folder_path, depth)
|
||||
});
|
||||
""
|
||||
}
|
||||
};
|
||||
|
||||
let result = compiler
|
||||
.compile_into_spirv(
|
||||
src.as_str(),
|
||||
src,
|
||||
shader_kind,
|
||||
path.as_ref().to_str().ok_or(CompileError::InvalidPath)?,
|
||||
path,
|
||||
"main",
|
||||
Some(&options),
|
||||
)
|
||||
@@ -38,6 +62,26 @@ pub fn compile_with_options<T>(path: T, shader_kind: ShaderKind, mut options: Co
|
||||
Ok(data.to_owned())
|
||||
}
|
||||
|
||||
pub fn read_to_string<'a, T>(path: &T) -> Cow<'a, str>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let mut f = File::open(path).map_err(CompileError::Open).expect("");
|
||||
let mut src = String::new();
|
||||
f.read_to_string(&mut src).map_err(CompileError::Open).expect("");
|
||||
Cow::Owned(src)
|
||||
}
|
||||
|
||||
fn default_get_include(
|
||||
path: &str,
|
||||
include_type: IncludeType,
|
||||
folder_path: &str,
|
||||
_depth: usize,
|
||||
) -> Result<ResolvedInclude, String> {
|
||||
// TODO: Does this print out anything meaningful?
|
||||
Err(format!("No include path given for {}", path).to_string())
|
||||
}
|
||||
|
||||
fn get_include(
|
||||
path: &str,
|
||||
include_type: IncludeType,
|
||||
|
||||
93
src/lib.rs
93
src/lib.rs
@@ -15,6 +15,7 @@ use spirv_reflect as sr;
|
||||
use vulkano as vk;
|
||||
use std::path::Path;
|
||||
use shaderc::ShaderKind;
|
||||
use std::borrow::Borrow;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CompiledShaders {
|
||||
@@ -28,74 +29,38 @@ pub struct CompiledShader {
|
||||
pub spriv: Vec<u32>,
|
||||
}
|
||||
|
||||
pub fn load<T>(input: T, shader_kind: ShaderKind) -> Result<CompiledShader, Error>
|
||||
pub fn load<T>(input: T, include_path: Option<T>, shader_kind: ShaderKind, compiler_options: Option<CompileOptions>)
|
||||
-> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
Ok(CompiledShader { spriv: compiler::compile(input, shader_kind).map_err(Error::Compile)? })
|
||||
}
|
||||
|
||||
|
||||
/// Loads and compiles the vertex shader
|
||||
pub fn load_vertex<T>(vertex: T) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let vertex = compiler::compile(vertex, ShaderKind::Vertex).map_err(Error::Compile)?;
|
||||
Ok(CompiledShader { spriv: vertex })
|
||||
}
|
||||
|
||||
/// Loads and compiles the fragment shader
|
||||
pub fn load_fragment<T>(fragment: T) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let fragment = compiler::compile(fragment, ShaderKind::Fragment).map_err(Error::Compile)?;
|
||||
Ok(CompiledShader { spriv: fragment })
|
||||
}
|
||||
|
||||
/// Loads and compiles the geometry shader
|
||||
pub fn load_geometry<T>(geometry: T) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let geometry = compiler::compile(geometry, ShaderKind::Geometry).map_err(Error::Compile)?;
|
||||
Ok(CompiledShader { spriv: geometry })
|
||||
}
|
||||
|
||||
/// Loads and compiles the tessellation shader
|
||||
pub fn load_tessellation_control<T>(tessellation_control: T) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let tess = compiler::compile(tessellation_control, ShaderKind::TessControl).map_err(Error::Compile)?;
|
||||
Ok(CompiledShader { spriv: tess })
|
||||
}
|
||||
|
||||
/// Loads and compiles the tessellation shader
|
||||
pub fn load_tessellation_evaluation<T>(tessellation_evaluation: T) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let tess = compiler::compile(tessellation_evaluation, ShaderKind::TessEvaluation).map_err(Error::Compile)?;
|
||||
Ok(CompiledShader { spriv: tess })
|
||||
}
|
||||
|
||||
pub fn load_compute<T>(compute: T) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap();
|
||||
load_compute_with_options(compute, options)
|
||||
}
|
||||
|
||||
pub fn load_compute_with_options<T>(compute: T, options: CompileOptions) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let compute = compiler::compile_with_options(compute, ShaderKind::Compute, options).map_err(Error::Compile)?;
|
||||
Ok(CompiledShader {
|
||||
spriv: compute,
|
||||
spriv: compiler::compile(input, include_path, shader_kind, compiler_options).map_err(Error::Compile)?
|
||||
})
|
||||
}
|
||||
|
||||
pub fn load_from_string<T>(source: &str, include_path: Option<T>, shader_kind: ShaderKind, compiler_options: Option<CompileOptions>) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
Ok(CompiledShader {
|
||||
spriv: compiler::compile_from_string(source, include_path, shader_kind, compiler_options).map_err(Error::Compile)?
|
||||
})
|
||||
}
|
||||
|
||||
pub fn load_compute<T>(compute: T, compiler_options: Option<CompileOptions>) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
load_compute_from_string(&compiler::read_to_string(&compute), Some(compute), compiler_options)
|
||||
}
|
||||
|
||||
pub fn load_compute_from_string<T>(source : &str, include_path : Option<T>, compiler_options: Option<CompileOptions>) -> Result<CompiledShader, Error>
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
Ok(CompiledShader {
|
||||
spriv: compiler::compile_from_string(source, include_path, ShaderKind::Compute, compiler_options).map_err(Error::Compile)?
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
718
tests/tests.rs
718
tests/tests.rs
@@ -1,345 +1,373 @@
|
||||
//use color_backtrace;
|
||||
//use difference::{Changeset, Difference};
|
||||
//use shade_runner::*;
|
||||
//use std::borrow::Cow;
|
||||
//use std::collections::HashMap;
|
||||
//use std::path::{Path, PathBuf};
|
||||
//use vulkano::descriptor::descriptor::*;
|
||||
//use vulkano::descriptor::pipeline_layout::{PipelineLayoutDesc, PipelineLayoutDescPcRange};
|
||||
//use vulkano::format::*;
|
||||
//use vulkano::pipeline::shader::ShaderInterfaceDefEntry;
|
||||
//
|
||||
//fn setup() {
|
||||
// color_backtrace::install();
|
||||
//}
|
||||
//
|
||||
//fn difference(e: &str, t: &str) -> String {
|
||||
// let diffs = Changeset::new(&e, &t, "");
|
||||
// diffs
|
||||
// .diffs
|
||||
// .iter()
|
||||
// .filter(|d| match d {
|
||||
// Difference::Add(_) => true,
|
||||
// Difference::Rem(_) => true,
|
||||
// _ => false,
|
||||
// })
|
||||
// .map(|d| match d {
|
||||
// Difference::Add(a) => format!("add: {}", a),
|
||||
// Difference::Rem(a) => format!("remove: {}", a),
|
||||
// _ => "".to_string(),
|
||||
// })
|
||||
// .collect::<Vec<String>>()
|
||||
// .join("\n")
|
||||
//}
|
||||
//
|
||||
//fn descriptor_layout<T>(desc: &T) -> String
|
||||
//where
|
||||
// T: PipelineLayoutDesc,
|
||||
//{
|
||||
// let num_sets = desc.num_sets();
|
||||
// let mut r = format!("{:?}", num_sets);
|
||||
// for n in 0..num_sets {
|
||||
// let num_bindings = desc.num_bindings_in_set(n);
|
||||
// r = format!("{:?}{:?}", r, num_bindings);
|
||||
// for b in num_bindings {
|
||||
// r = format!("{:?}{:?}", r, desc.descriptor(n, b));
|
||||
// }
|
||||
// }
|
||||
// let num_push_constants = desc.num_push_constants_ranges();
|
||||
// r = format!("{:?}{:?}", r, num_push_constants);
|
||||
// for i in 0..num_push_constants {
|
||||
// r = format!("{:?}{:?}", r, desc.push_constants_range(i));
|
||||
// }
|
||||
// r
|
||||
//}
|
||||
//
|
||||
//fn parse<T>(vertex: T, fragment: T) -> shade_runner::Entry
|
||||
//where
|
||||
// T: AsRef<Path>,
|
||||
//{
|
||||
// let project_root = std::env::current_dir().expect("failed to get root directory");
|
||||
// let mut path = project_root.clone();
|
||||
// path.push(PathBuf::from("tests/shaders/"));
|
||||
// let mut vertex_path = path.clone();
|
||||
// vertex_path.push(vertex);
|
||||
// let mut fragment_path = path.clone();
|
||||
// fragment_path.push(fragment);
|
||||
// let shader = shade_runner::load(vertex_path, fragment_path).expect("Failed to compile");
|
||||
// shade_runner::parse(&shader).unwrap()
|
||||
//}
|
||||
//
|
||||
//fn do_test<T>(a: &T, b: &T)
|
||||
//where
|
||||
// T: std::fmt::Debug,
|
||||
//{
|
||||
// let a = format!("{:?}", a);
|
||||
// let b = format!("{:?}", b);
|
||||
// assert_eq!(&a, &b, "\n\nDifference: {}", difference(&a, &b));
|
||||
//}
|
||||
//
|
||||
//#[test]
|
||||
//fn test_shade1() {
|
||||
// setup();
|
||||
// let target = Entry {
|
||||
// compute_layout: Default::default(),
|
||||
// frag_input: FragInput { inputs: Vec::new() },
|
||||
// frag_output: FragOutput {
|
||||
// outputs: vec![ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32B32A32Sfloat,
|
||||
// name: Some(Cow::Borrowed("f_color")),
|
||||
// }],
|
||||
// },
|
||||
// frag_layout: FragLayout {
|
||||
// layout_data: LayoutData {
|
||||
// num_sets: 0,
|
||||
// num_bindings: HashMap::new(),
|
||||
// descriptions: HashMap::new(),
|
||||
// num_constants: 0,
|
||||
// pc_ranges: Vec::new(),
|
||||
// },
|
||||
// },
|
||||
// vert_input: VertInput {
|
||||
// inputs: vec![ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32Sfloat,
|
||||
// name: Some(Cow::Borrowed("position")),
|
||||
// }],
|
||||
// },
|
||||
// vert_output: VertOutput {
|
||||
// outputs: Vec::new(),
|
||||
// },
|
||||
// vert_layout: VertLayout {
|
||||
// layout_data: LayoutData {
|
||||
// num_sets: 0,
|
||||
// num_bindings: HashMap::new(),
|
||||
// descriptions: HashMap::new(),
|
||||
// num_constants: 0,
|
||||
// pc_ranges: Vec::new(),
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// let entry = parse("vert1.glsl", "frag1.glsl");
|
||||
// do_test(&entry, &target);
|
||||
//}
|
||||
//
|
||||
//#[test]
|
||||
//fn test_shade2() {
|
||||
// setup();
|
||||
// let target = Entry {
|
||||
// compute_layout: Default::default(),
|
||||
// frag_input: FragInput {
|
||||
// inputs: vec![
|
||||
// ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32B32A32Sfloat,
|
||||
// name: Some(Cow::Borrowed("cool")),
|
||||
// },
|
||||
// ShaderInterfaceDefEntry {
|
||||
// location: 1..2,
|
||||
// format: Format::R32G32Sfloat,
|
||||
// name: Some(Cow::Borrowed("yep")),
|
||||
// },
|
||||
// ShaderInterfaceDefEntry {
|
||||
// location: 2..3,
|
||||
// format: Format::R32Sfloat,
|
||||
// name: Some(Cow::Borrowed("monkey")),
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// frag_output: FragOutput {
|
||||
// outputs: vec![ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32B32A32Sfloat,
|
||||
// name: Some(Cow::Borrowed("f_color")),
|
||||
// }],
|
||||
// },
|
||||
// frag_layout: FragLayout {
|
||||
// layout_data: LayoutData {
|
||||
// num_sets: 0,
|
||||
// num_bindings: HashMap::new(),
|
||||
// descriptions: HashMap::new(),
|
||||
// num_constants: 0,
|
||||
// pc_ranges: Vec::new(),
|
||||
// },
|
||||
// },
|
||||
// vert_input: VertInput {
|
||||
// inputs: vec![ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32Sfloat,
|
||||
// name: Some(Cow::Borrowed("position")),
|
||||
// }],
|
||||
// },
|
||||
// vert_output: VertOutput {
|
||||
// outputs: vec![
|
||||
// ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32B32A32Sfloat,
|
||||
// name: Some(Cow::Borrowed("cool")),
|
||||
// },
|
||||
// ShaderInterfaceDefEntry {
|
||||
// location: 1..2,
|
||||
// format: Format::R32G32Sfloat,
|
||||
// name: Some(Cow::Borrowed("yep")),
|
||||
// },
|
||||
// ShaderInterfaceDefEntry {
|
||||
// location: 2..3,
|
||||
// format: Format::R32Sfloat,
|
||||
// name: Some(Cow::Borrowed("monkey")),
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// vert_layout: VertLayout {
|
||||
// layout_data: LayoutData {
|
||||
// num_sets: 0,
|
||||
// num_bindings: HashMap::new(),
|
||||
// descriptions: HashMap::new(),
|
||||
// num_constants: 0,
|
||||
// pc_ranges: Vec::new(),
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// let entry = parse("vert2.glsl", "frag2.glsl");
|
||||
// do_test(&entry, &target);
|
||||
//}
|
||||
//
|
||||
//#[test]
|
||||
//fn test_shade3() {
|
||||
// setup();
|
||||
// let target = Entry {
|
||||
// compute_layout: Default::default(),
|
||||
// frag_input: FragInput { inputs: Vec::new() },
|
||||
// frag_output: FragOutput {
|
||||
// outputs: vec![ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32B32A32Sfloat,
|
||||
// name: Some(Cow::Borrowed("f_color")),
|
||||
// }],
|
||||
// },
|
||||
// frag_layout: FragLayout {
|
||||
// layout_data: LayoutData {
|
||||
// num_sets: 1,
|
||||
// num_bindings: vec![(0, 1)].into_iter().collect(),
|
||||
// descriptions: vec![(
|
||||
// 0,
|
||||
// vec![(
|
||||
// 0,
|
||||
// DescriptorDesc {
|
||||
// ty: DescriptorDescTy::CombinedImageSampler(DescriptorImageDesc {
|
||||
// sampled: true,
|
||||
// dimensions: DescriptorImageDescDimensions::TwoDimensional,
|
||||
// format: None,
|
||||
// multisampled: false,
|
||||
// array_layers: DescriptorImageDescArray::NonArrayed,
|
||||
// }),
|
||||
// array_count: 1,
|
||||
// stages: ShaderStages {
|
||||
// fragment: true,
|
||||
// ..ShaderStages::none()
|
||||
// },
|
||||
// readonly: true,
|
||||
// },
|
||||
// )]
|
||||
// .into_iter()
|
||||
// .collect(),
|
||||
// )]
|
||||
// .into_iter()
|
||||
// .collect(),
|
||||
// num_constants: 0,
|
||||
// pc_ranges: Vec::new(),
|
||||
// },
|
||||
// },
|
||||
// vert_input: VertInput {
|
||||
// inputs: vec![ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32Sfloat,
|
||||
// name: Some(Cow::Borrowed("position")),
|
||||
// }],
|
||||
// },
|
||||
// vert_output: VertOutput {
|
||||
// outputs: Vec::new(),
|
||||
// },
|
||||
// vert_layout: VertLayout {
|
||||
// layout_data: LayoutData {
|
||||
// num_sets: 0,
|
||||
// num_bindings: HashMap::new(),
|
||||
// descriptions: HashMap::new(),
|
||||
// num_constants: 0,
|
||||
// pc_ranges: Vec::new(),
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// let entry = parse("vert3.glsl", "frag3.glsl");
|
||||
// do_test(&entry.frag_input, &target.frag_input);
|
||||
// do_test(&entry.frag_output, &target.frag_output);
|
||||
// do_test(&entry.vert_input, &target.vert_input);
|
||||
// do_test(&entry.vert_output, &target.vert_output);
|
||||
// do_test(
|
||||
// &descriptor_layout(&entry.frag_layout),
|
||||
// &descriptor_layout(&target.frag_layout),
|
||||
// );
|
||||
// do_test(
|
||||
// &descriptor_layout(&entry.vert_layout),
|
||||
// &descriptor_layout(&target.vert_layout),
|
||||
// );
|
||||
//}
|
||||
//
|
||||
//#[test]
|
||||
//fn test_shade4() {
|
||||
// setup();
|
||||
// let target = Entry {
|
||||
// compute_layout: Default::default(),
|
||||
// frag_input: FragInput { inputs: Vec::new() },
|
||||
// frag_output: FragOutput {
|
||||
// outputs: vec![ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32B32A32Sfloat,
|
||||
// name: Some(Cow::Borrowed("f_color")),
|
||||
// }],
|
||||
// },
|
||||
// frag_layout: FragLayout {
|
||||
// layout_data: LayoutData {
|
||||
// num_sets: 0,
|
||||
// num_bindings: HashMap::new(),
|
||||
// descriptions: HashMap::new(),
|
||||
// num_constants: 1,
|
||||
// pc_ranges: vec![PipelineLayoutDescPcRange {
|
||||
// offset: 0,
|
||||
// size: 16,
|
||||
// stages: ShaderStages {
|
||||
// fragment: true,
|
||||
// ..ShaderStages::none()
|
||||
// },
|
||||
// }],
|
||||
// },
|
||||
// },
|
||||
// vert_input: VertInput {
|
||||
// inputs: vec![ShaderInterfaceDefEntry {
|
||||
// location: 0..1,
|
||||
// format: Format::R32G32Sfloat,
|
||||
// name: Some(Cow::Borrowed("position")),
|
||||
// }],
|
||||
// },
|
||||
// vert_output: VertOutput {
|
||||
// outputs: Vec::new(),
|
||||
// },
|
||||
// vert_layout: VertLayout {
|
||||
// layout_data: LayoutData {
|
||||
// num_sets: 0,
|
||||
// num_bindings: HashMap::new(),
|
||||
// descriptions: HashMap::new(),
|
||||
// num_constants: 0,
|
||||
// pc_ranges: Vec::new(),
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
// let entry = parse("vert4.glsl", "frag4.glsl");
|
||||
// do_test(&entry.frag_input, &target.frag_input);
|
||||
// do_test(&entry.frag_output, &target.frag_output);
|
||||
// do_test(&entry.vert_input, &target.vert_input);
|
||||
// do_test(&entry.vert_output, &target.vert_output);
|
||||
// do_test(
|
||||
// &descriptor_layout(&entry.frag_layout),
|
||||
// &descriptor_layout(&target.frag_layout),
|
||||
// );
|
||||
//}
|
||||
use color_backtrace;
|
||||
use difference::{Changeset, Difference};
|
||||
use shade_runner::*;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use vulkano::descriptor::descriptor::*;
|
||||
use vulkano::descriptor::pipeline_layout::{PipelineLayoutDesc, PipelineLayoutDescPcRange};
|
||||
use vulkano::format::*;
|
||||
use vulkano::pipeline::shader::ShaderInterfaceDefEntry;
|
||||
use shaderc::ShaderKind;
|
||||
|
||||
fn setup() {
|
||||
color_backtrace::install();
|
||||
}
|
||||
|
||||
fn difference(e: &str, t: &str) -> String {
|
||||
let diffs = Changeset::new(&e, &t, "");
|
||||
diffs
|
||||
.diffs
|
||||
.iter()
|
||||
.filter(|d| match d {
|
||||
Difference::Add(_) => true,
|
||||
Difference::Rem(_) => true,
|
||||
_ => false,
|
||||
})
|
||||
.map(|d| match d {
|
||||
Difference::Add(a) => format!("add: {}", a),
|
||||
Difference::Rem(a) => format!("remove: {}", a),
|
||||
_ => "".to_string(),
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
fn descriptor_layout<T>(desc: &T) -> String
|
||||
where
|
||||
T: PipelineLayoutDesc,
|
||||
{
|
||||
let num_sets = desc.num_sets();
|
||||
let mut r = format!("{:?}", num_sets);
|
||||
for n in 0..num_sets {
|
||||
let num_bindings = desc.num_bindings_in_set(n);
|
||||
r = format!("{:?}{:?}", r, num_bindings);
|
||||
for b in num_bindings {
|
||||
r = format!("{:?}{:?}", r, desc.descriptor(n, b));
|
||||
}
|
||||
}
|
||||
let num_push_constants = desc.num_push_constants_ranges();
|
||||
r = format!("{:?}{:?}", r, num_push_constants);
|
||||
for i in 0..num_push_constants {
|
||||
r = format!("{:?}{:?}", r, desc.push_constants_range(i));
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
fn parse<T>(input: T, shader_kind: ShaderKind) -> shade_runner::Entry
|
||||
where
|
||||
T: AsRef<Path>,
|
||||
{
|
||||
let project_root = std::env::current_dir().expect("failed to get root directory");
|
||||
let mut path = project_root.clone();
|
||||
path.push(PathBuf::from("tests/shaders/"));
|
||||
|
||||
let mut shader_path = path.clone();
|
||||
shader_path.push(input);
|
||||
|
||||
let shader = shade_runner::load(shader_path, None, shader_kind, None).expect("Failed to compile");
|
||||
|
||||
shade_runner::parse(&shader).unwrap()
|
||||
}
|
||||
|
||||
fn do_test<T>(a: &T, b: &T)
|
||||
where
|
||||
T: std::fmt::Debug,
|
||||
{
|
||||
let a = format!("{:?}", a);
|
||||
let b = format!("{:?}", b);
|
||||
assert_eq!(&a, &b, "\n\nDifference: {}", difference(&a, &b));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shade1() {
|
||||
setup();
|
||||
let frag_target = Entry {
|
||||
input: Some(Input { inputs: Vec::new() }),
|
||||
output: Some(Output {
|
||||
outputs: vec![ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32B32A32Sfloat,
|
||||
name: Some(Cow::Borrowed("f_color")),
|
||||
}],
|
||||
}),
|
||||
layout: Layout {
|
||||
layout_data: LayoutData {
|
||||
num_sets: 0,
|
||||
num_bindings: HashMap::new(),
|
||||
descriptions: HashMap::new(),
|
||||
num_constants: 0,
|
||||
pc_ranges: Vec::new(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let vert_target = Entry {
|
||||
input: Some(Input {
|
||||
inputs: vec![ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32Sfloat,
|
||||
name: Some(Cow::Borrowed("position")),
|
||||
}],
|
||||
}),
|
||||
output: Some(Output {
|
||||
outputs: Vec::new(),
|
||||
}),
|
||||
layout: Layout {
|
||||
layout_data: LayoutData {
|
||||
num_sets: 0,
|
||||
num_bindings: HashMap::new(),
|
||||
descriptions: HashMap::new(),
|
||||
num_constants: 0,
|
||||
pc_ranges: Vec::new(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let vert_entry = parse("vert1.glsl", ShaderKind::Vertex);
|
||||
let frag_entry = parse("frag1.glsl", ShaderKind::Fragment);
|
||||
do_test(&vert_entry, &vert_target);
|
||||
do_test(&frag_entry, &frag_target);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shade2() {
|
||||
setup();
|
||||
let frag_target = Entry {
|
||||
input: Some(Input {
|
||||
inputs: vec![
|
||||
ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32B32A32Sfloat,
|
||||
name: Some(Cow::Borrowed("cool")),
|
||||
},
|
||||
ShaderInterfaceDefEntry {
|
||||
location: 1..2,
|
||||
format: Format::R32G32Sfloat,
|
||||
name: Some(Cow::Borrowed("yep")),
|
||||
},
|
||||
ShaderInterfaceDefEntry {
|
||||
location: 2..3,
|
||||
format: Format::R32Sfloat,
|
||||
name: Some(Cow::Borrowed("monkey")),
|
||||
},
|
||||
],
|
||||
}),
|
||||
output: Some(Output {
|
||||
outputs: vec![ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32B32A32Sfloat,
|
||||
name: Some(Cow::Borrowed("f_color")),
|
||||
}],
|
||||
}),
|
||||
layout: Layout {
|
||||
layout_data: LayoutData {
|
||||
num_sets: 0,
|
||||
num_bindings: HashMap::new(),
|
||||
descriptions: HashMap::new(),
|
||||
num_constants: 0,
|
||||
pc_ranges: Vec::new(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let vert_target = Entry {
|
||||
input: Some(Input {
|
||||
inputs: vec![ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32Sfloat,
|
||||
name: Some(Cow::Borrowed("position")),
|
||||
}],
|
||||
}),
|
||||
output: Some(Output {
|
||||
outputs: vec![
|
||||
ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32B32A32Sfloat,
|
||||
name: Some(Cow::Borrowed("cool")),
|
||||
},
|
||||
ShaderInterfaceDefEntry {
|
||||
location: 1..2,
|
||||
format: Format::R32G32Sfloat,
|
||||
name: Some(Cow::Borrowed("yep")),
|
||||
},
|
||||
ShaderInterfaceDefEntry {
|
||||
location: 2..3,
|
||||
format: Format::R32Sfloat,
|
||||
name: Some(Cow::Borrowed("monkey")),
|
||||
},
|
||||
],
|
||||
}),
|
||||
layout: Layout {
|
||||
layout_data: LayoutData {
|
||||
num_sets: 0,
|
||||
num_bindings: HashMap::new(),
|
||||
descriptions: HashMap::new(),
|
||||
num_constants: 0,
|
||||
pc_ranges: Vec::new(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let vert_entry = parse("vert2.glsl", ShaderKind::Vertex);
|
||||
let frag_entry = parse("frag2.glsl", ShaderKind::Fragment);
|
||||
do_test(&vert_entry, &vert_target);
|
||||
do_test(&frag_entry, &frag_target);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shade3() {
|
||||
setup();
|
||||
let frag_target = Entry {
|
||||
input: Some(Input { inputs: Vec::new() }),
|
||||
output: Some(Output {
|
||||
outputs: vec![ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32B32A32Sfloat,
|
||||
name: Some(Cow::Borrowed("f_color")),
|
||||
}],
|
||||
}),
|
||||
layout: Layout {
|
||||
layout_data: LayoutData {
|
||||
num_sets: 1,
|
||||
num_bindings: vec![(0, 1)].into_iter().collect(),
|
||||
descriptions: vec![(
|
||||
0,
|
||||
vec![(
|
||||
0,
|
||||
DescriptorDesc {
|
||||
ty: DescriptorDescTy::CombinedImageSampler(DescriptorImageDesc {
|
||||
sampled: true,
|
||||
dimensions: DescriptorImageDescDimensions::TwoDimensional,
|
||||
format: None,
|
||||
multisampled: false,
|
||||
array_layers: DescriptorImageDescArray::NonArrayed,
|
||||
}),
|
||||
array_count: 1,
|
||||
stages: ShaderStages {
|
||||
fragment: true,
|
||||
..ShaderStages::none()
|
||||
},
|
||||
readonly: true,
|
||||
},
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
)]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
num_constants: 0,
|
||||
pc_ranges: Vec::new(),
|
||||
},
|
||||
},
|
||||
};
|
||||
let vert_target = Entry {
|
||||
input: Some(Input {
|
||||
inputs: vec![ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32Sfloat,
|
||||
name: Some(Cow::Borrowed("position")),
|
||||
}],
|
||||
}),
|
||||
output: Some(Output {
|
||||
outputs: Vec::new(),
|
||||
}),
|
||||
layout: Layout {
|
||||
layout_data: LayoutData {
|
||||
num_sets: 0,
|
||||
num_bindings: HashMap::new(),
|
||||
descriptions: HashMap::new(),
|
||||
num_constants: 0,
|
||||
pc_ranges: Vec::new(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let vert_entry = parse("vert3.glsl", ShaderKind::Vertex);
|
||||
let frag_entry = parse("frag3.glsl", ShaderKind::Fragment);
|
||||
|
||||
do_test(&vert_entry.input, &vert_target.input);
|
||||
do_test(&vert_entry.output, &vert_target.output);
|
||||
|
||||
do_test(&frag_entry.input, &frag_target.input);
|
||||
do_test(&frag_entry.output, &frag_target.output);
|
||||
|
||||
do_test(
|
||||
&descriptor_layout(&frag_entry.layout),
|
||||
&descriptor_layout(&frag_target.layout),
|
||||
);
|
||||
do_test(
|
||||
&descriptor_layout(&vert_entry.layout),
|
||||
&descriptor_layout(&vert_target.layout),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shade4() {
|
||||
setup();
|
||||
let frag_target = Entry {
|
||||
input: Some(Input { inputs: Vec::new() }),
|
||||
output: Some(Output {
|
||||
outputs: vec![ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32B32A32Sfloat,
|
||||
name: Some(Cow::Borrowed("f_color")),
|
||||
}],
|
||||
}),
|
||||
layout: Layout {
|
||||
layout_data: LayoutData {
|
||||
num_sets: 0,
|
||||
num_bindings: HashMap::new(),
|
||||
descriptions: HashMap::new(),
|
||||
num_constants: 1,
|
||||
pc_ranges: vec![PipelineLayoutDescPcRange {
|
||||
offset: 0,
|
||||
size: 16,
|
||||
stages: ShaderStages {
|
||||
fragment: true,
|
||||
..ShaderStages::none()
|
||||
},
|
||||
}],
|
||||
},
|
||||
},
|
||||
};
|
||||
let vert_target = Entry {
|
||||
input: Some(Input {
|
||||
inputs: vec![ShaderInterfaceDefEntry {
|
||||
location: 0..1,
|
||||
format: Format::R32G32Sfloat,
|
||||
name: Some(Cow::Borrowed("position")),
|
||||
}],
|
||||
}),
|
||||
output: Some(Output {
|
||||
outputs: Vec::new(),
|
||||
}),
|
||||
layout: Layout {
|
||||
layout_data: LayoutData {
|
||||
num_sets: 0,
|
||||
num_bindings: HashMap::new(),
|
||||
descriptions: HashMap::new(),
|
||||
num_constants: 0,
|
||||
pc_ranges: Vec::new(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let vert_entry = parse("vert4.glsl", ShaderKind::Vertex);
|
||||
let frag_entry = parse("frag4.glsl", ShaderKind::Fragment);
|
||||
|
||||
do_test(&vert_entry.input, &vert_target.input);
|
||||
do_test(&vert_entry.output, &vert_target.output);
|
||||
|
||||
do_test(&frag_entry.input, &frag_target.input);
|
||||
do_test(&frag_entry.output, &frag_target.output);
|
||||
|
||||
do_test(
|
||||
&descriptor_layout(&frag_entry.layout),
|
||||
&descriptor_layout(&frag_target.layout),
|
||||
);
|
||||
do_test(
|
||||
&descriptor_layout(&vert_entry.layout),
|
||||
&descriptor_layout(&vert_target.layout),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user