diff --git a/src/layouts.rs b/src/layouts.rs index e049937..789f918 100644 --- a/src/layouts.rs +++ b/src/layouts.rs @@ -62,17 +62,22 @@ unsafe impl PipelineLayoutDesc for FragLayout { .and_then(|s|s.get(&binding)) .map(|desc| { let mut desc = desc.clone(); - dbg!(&self.stages); desc.stages = self.stages.clone(); desc }) } fn num_push_constants_ranges(&self) -> usize { - 0 + self.layout_data.num_constants } - fn push_constants_range(&self, _num: usize) -> Option { - None + fn push_constants_range(&self, num: usize) -> Option { + self.layout_data.pc_ranges.get(num) + .map(|desc| { + let mut desc = desc.clone(); + desc.stages = self.stages.clone(); + desc + }) + } } diff --git a/src/reflection.rs b/src/reflection.rs index a19407b..113daab 100644 --- a/src/reflection.rs +++ b/src/reflection.rs @@ -1,11 +1,12 @@ -use crate::sr; -use crate::srvk::{SpirvTy,DescriptorDescInfo}; -use std::borrow::Cow; -use crate::vk::pipeline::shader::ShaderInterfaceDefEntry; +use crate::layouts::*; +use crate::sr; +use crate::srvk::{DescriptorDescInfo, SpirvTy}; use crate::vk::descriptor::descriptor::*; -use std::collections::HashMap; +use crate::vk::descriptor::pipeline_layout::PipelineLayoutDescPcRange; +use crate::vk::pipeline::shader::ShaderInterfaceDefEntry; use crate::CompiledShaders; -use crate::layouts::*; +use std::borrow::Cow; +use std::collections::HashMap; pub struct ShaderInterfaces { pub inputs: Vec, @@ -17,27 +18,37 @@ pub struct LayoutData { pub num_sets: usize, pub num_bindings: HashMap, pub descriptions: HashMap>, + pub num_constants: usize, + pub pc_ranges: Vec, } pub fn create_entry(shaders: &CompiledShaders) -> Entry { let vertex_interfaces = create_interfaces(&shaders.vertex); let fragment_interfaces = create_interfaces(&shaders.fragment); let fragment_layout = create_layouts(&shaders.fragment); - let frag_input = FragInput{ inputs: fragment_interfaces.inputs }; - let frag_output = FragOutput{ outputs: fragment_interfaces.outputs }; + let frag_input = FragInput { + inputs: fragment_interfaces.inputs, + }; + let frag_output = FragOutput { + outputs: fragment_interfaces.outputs, + }; let frag_layout = FragLayout { stages: ShaderStages { - fragment: true, - ..ShaderStages::none() + fragment: true, + ..ShaderStages::none() }, layout_data: fragment_layout, }; - let vert_input = VertInput{ inputs: vertex_interfaces.inputs }; - let vert_output = VertOutput{ outputs: vertex_interfaces.outputs }; + let vert_input = VertInput { + inputs: vertex_interfaces.inputs, + }; + let vert_output = VertOutput { + outputs: vertex_interfaces.outputs, + }; let vert_layout = VertLayout(ShaderStages { - vertex: true, - ..ShaderStages::none() - }); + vertex: true, + ..ShaderStages::none() + }); Entry { frag_input, frag_output, @@ -46,7 +57,6 @@ pub fn create_entry(shaders: &CompiledShaders) -> Entry { frag_layout, vert_layout, } - } fn create_interfaces(data: &[u32]) -> ShaderInterfaces { @@ -94,7 +104,8 @@ fn create_interfaces(data: &[u32]) -> ShaderInterfaces { fn create_layouts(data: &[u32]) -> LayoutData { sr::ShaderModule::load_u32_data(data) .map(|m| { - m.enumerate_descriptor_sets(None) + let (num_sets, num_bindings, descriptions) = m + .enumerate_descriptor_sets(None) .map(|sets| { let num_sets = sets.len(); let num_bindings = sets @@ -107,9 +118,11 @@ fn create_layouts(data: &[u32]) -> LayoutData { let descriptions = sets .iter() .map(|i| { - let desc = i.bindings.iter() + let desc = i + .bindings + .iter() .map(|b| { - let info = DescriptorDescInfo{ + let info = DescriptorDescInfo { descriptor_type: b.descriptor_type, image: b.image, }; @@ -125,18 +138,35 @@ fn create_layouts(data: &[u32]) -> LayoutData { }; (b.binding as usize, d) }) - .collect::>(); + .collect::>(); (i.set as usize, desc) }) .collect::>>(); - LayoutData { - num_sets, - num_bindings, - descriptions, - } + (num_sets, num_bindings, descriptions) }) - .expect("Failed to pass outputs") + .expect("Failed to pass descriptors"); + let (num_constants, pc_ranges) = m + .enumerate_push_constant_blocks(None) + .map(|constants| { + let num_constants = constants.len(); + let pc_ranges = constants + .iter() + .map(|pc| PipelineLayoutDescPcRange { + offset: pc.offset as usize, + size: pc.size as usize, + stages: ShaderStages::all(), + }) + .collect::>(); + (num_constants, pc_ranges) + }) + .expect("Failed to pass push constants"); + LayoutData { + num_sets, + num_bindings, + descriptions, + num_constants, + pc_ranges, + } }) .expect("failed to load module") } - diff --git a/tests/shaders/frag4.glsl b/tests/shaders/frag4.glsl new file mode 100644 index 0000000..c193bae --- /dev/null +++ b/tests/shaders/frag4.glsl @@ -0,0 +1,11 @@ +#version 450 + +layout(location = 0) out vec4 f_color; + +layout(push_constant) uniform PushConstantData { + float time; +} pc; + +void main() { + f_color = vec4(pc.time, 0.5, 1.0, 1.0); +} diff --git a/tests/shaders/vert4.glsl b/tests/shaders/vert4.glsl new file mode 100644 index 0000000..874d199 --- /dev/null +++ b/tests/shaders/vert4.glsl @@ -0,0 +1,10 @@ +#version 450 + +layout(location = 0) in vec2 position; + +void main() { + vec2 p = position; + p.x += 0.2; + gl_Position = vec4(p, 0.0, 1.0); +} + diff --git a/tests/tests.rs b/tests/tests.rs index c5f70b4..904858d 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -5,9 +5,9 @@ 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 vulkano::descriptor::pipeline_layout::PipelineLayoutDesc; fn setup() { color_backtrace::install(); @@ -32,9 +32,9 @@ fn difference(e: &str, t: &str) -> String { .join("\n") } -fn descriptor_layout(desc: &T) -> String +fn descriptor_layout(desc: &T) -> String where -T: PipelineLayoutDesc, + T: PipelineLayoutDesc, { let num_sets = desc.num_sets(); let mut r = format!("{:?}", num_sets); @@ -68,6 +68,15 @@ where shade_runner::parse(&shader) } +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(); @@ -89,6 +98,8 @@ fn test_shade1() { num_sets: 0, num_bindings: HashMap::new(), descriptions: HashMap::new(), + num_constants: 0, + pc_ranges: Vec::new(), }, }, vert_input: VertInput { @@ -107,14 +118,7 @@ fn test_shade1() { }), }; let entry = parse("vert1.glsl", "frag1.glsl"); - let entry = format!("{:?}", entry); - let target = format!("{:?}", target); - assert_eq!( - &entry, - &target, - "\n\nDifference: {}", - difference(&entry, &target) - ); + do_test(&entry, &target); } #[test] @@ -156,6 +160,8 @@ fn test_shade2() { num_sets: 0, num_bindings: HashMap::new(), descriptions: HashMap::new(), + num_constants: 0, + pc_ranges: Vec::new(), }, }, vert_input: VertInput { @@ -190,14 +196,7 @@ fn test_shade2() { }), }; let entry = parse("vert2.glsl", "frag2.glsl"); - let entry = format!("{:?}", entry); - let target = format!("{:?}", target); - assert_eq!( - &entry, - &target, - "\n\nDifference: {}", - difference(&entry, &target) - ); + do_test(&entry, &target); } #[test] @@ -245,6 +244,8 @@ fn test_shade3() { )] .into_iter() .collect(), + num_constants: 0, + pc_ranges: Vec::new(), }, }, vert_input: VertInput { @@ -267,21 +268,70 @@ fn test_shade3() { 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)); - + do_test( + &descriptor_layout(&entry.frag_layout), + &descriptor_layout(&target.frag_layout), + ); + do_test( + &descriptor_layout(&entry.vert_layout), + &descriptor_layout(&target.vert_layout), + ); } -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_shade4() { + setup(); + let target = Entry { + 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 { + stages: ShaderStages { + fragment: true, + ..ShaderStages::none() + }, + 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(ShaderStages { + vertex: true, + ..ShaderStages::none() + }), + }; + 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), ); }