From fafb5e52a69ed2c26f40a6d7912669bd8f42bdad Mon Sep 17 00:00:00 2001 From: mitchellhansen Date: Sun, 8 Mar 2020 18:08:14 -0700 Subject: [PATCH] updated API further to just use optionals. Updated tests --- examples/compile.rs | 30 +- src/compiler.rs | 78 +++-- src/lib.rs | 63 +--- tests/tests.rs | 718 +++++++++++++++++++++++--------------------- 4 files changed, 470 insertions(+), 419 deletions(-) diff --git a/examples/compile.rs b/examples/compile.rs index 6fb33df..8f3cc0b 100644 --- a/examples/compile.rs +++ b/examples/compile.rs @@ -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); } diff --git a/src/compiler.rs b/src/compiler.rs index 22ad593..7b4cfce 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -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(path: T, shader_kind: ShaderKind) -> Result, CompileError> -where - T: AsRef, +pub fn compile(path: T, include_path: Option, shader_kind: ShaderKind, compiler_options: Option) -> Result, CompileError> + where + T: AsRef, +{ + compile_with_options(&read_to_string(&path), include_path, shader_kind, compiler_options) +} + +pub fn compile_from_string(input: &str, include_path: Option, shader_kind: ShaderKind, compiler_options: Option) -> Result, CompileError> + where + T: AsRef, { - let mut options = CompileOptions::new().ok_or(CompileError::CreateCompiler)?; - compile_with_options(path, shader_kind, options) + compile_with_options(input, include_path, shader_kind, compiler_options) } -pub fn compile_with_options(path: T, shader_kind: ShaderKind, mut options: CompileOptions) -> Result, CompileError> +pub fn compile_with_options(src: &str, include_path: Option, shader_kind: ShaderKind, options: Option) + -> Result, CompileError> where T: AsRef, { // 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)?; - options.set_include_callback(|path, include_type, folder_path, depth| { - get_include(path, include_type, folder_path, depth) - }); + + 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(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, +{ + 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 { + // 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, @@ -59,12 +103,12 @@ fn get_include( .to_str() .ok_or("Path has invalid characters".to_string())? .to_owned(); - let p = p.canonicalize().map_err(|_|"Failed to parse include path".to_string())?; + let p = p.canonicalize().map_err(|_| "Failed to parse include path".to_string())?; let mut content = String::new(); File::open(p) - .map_err(|_|"Couldn't open include directory".to_string())? + .map_err(|_| "Couldn't open include directory".to_string())? .read_to_string(&mut content) - .map_err(|_|"Failed to read included shader".to_string())?; + .map_err(|_| "Failed to read included shader".to_string())?; Ok(ResolvedInclude { resolved_name, content, diff --git a/src/lib.rs b/src/lib.rs index 35d4d62..b9f48ee 100644 --- a/src/lib.rs +++ b/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, } -pub fn load(input: T, shader_kind: ShaderKind) -> Result +pub fn load(input: T, include_path: Option, shader_kind: ShaderKind, compiler_options: Option) + -> Result where T: AsRef, { - Ok(CompiledShader { spriv: compiler::compile(input, shader_kind).map_err(Error::Compile)? }) -} - - -/// Loads and compiles the vertex shader -pub fn load_vertex(vertex: T) -> Result - where - T: AsRef, -{ - 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(fragment: T) -> Result - where - T: AsRef, -{ - 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(geometry: T) -> Result - where - T: AsRef, -{ - 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(tessellation_control: T) -> Result - where - T: AsRef, -{ - let tess = compiler::compile(tessellation_control, ShaderKind::TessControl).map_err(Error::Compile)?; - Ok(CompiledShader { spriv: tess }) + Ok(CompiledShader { + spriv: compiler::compile(input, include_path, shader_kind, compiler_options).map_err(Error::Compile)? + }) } -/// Loads and compiles the tessellation shader -pub fn load_tessellation_evaluation(tessellation_evaluation: T) -> Result +pub fn load_from_string(source: &str, include_path: Option, shader_kind: ShaderKind, compiler_options: Option) -> Result where T: AsRef, { - let tess = compiler::compile(tessellation_evaluation, ShaderKind::TessEvaluation).map_err(Error::Compile)?; - Ok(CompiledShader { spriv: tess }) + Ok(CompiledShader { + spriv: compiler::compile_from_string(source, include_path, shader_kind, compiler_options).map_err(Error::Compile)? + }) } -pub fn load_compute(compute: T) -> Result +pub fn load_compute(compute: T, compiler_options: Option) -> Result where T: AsRef, { - let options = CompileOptions::new().ok_or(CompileError::CreateCompiler).unwrap(); - load_compute_with_options(compute, options) + load_compute_from_string(&compiler::read_to_string(&compute), Some(compute), compiler_options) } -pub fn load_compute_with_options(compute: T, options: CompileOptions) -> Result +pub fn load_compute_from_string(source : &str, include_path : Option, compiler_options: Option) -> Result where T: AsRef, { - let compute = compiler::compile_with_options(compute, ShaderKind::Compute, options).map_err(Error::Compile)?; Ok(CompiledShader { - spriv: compute, + spriv: compiler::compile_from_string(source, include_path, ShaderKind::Compute, compiler_options).map_err(Error::Compile)? }) } diff --git a/tests/tests.rs b/tests/tests.rs index 1c1d523..bda62b1 100644 --- a/tests/tests.rs +++ b/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::>() -// .join("\n") -//} -// -//fn descriptor_layout(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(vertex: T, fragment: T) -> shade_runner::Entry -//where -// T: AsRef, -//{ -// 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(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::>() + .join("\n") +} + +fn descriptor_layout(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(input: T, shader_kind: ShaderKind) -> shade_runner::Entry + where + T: AsRef, +{ + 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(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), + ); +}