From f3346e48bb3e8065fa8c0b4f21d61f1ee4a2c9af Mon Sep 17 00:00:00 2001 From: Tom Gowan Date: Fri, 26 Apr 2019 15:24:58 +1000 Subject: [PATCH] descriptor layout --- src/layouts.rs | 12 ++- src/reflection.rs | 58 +++++++++++++- src/srvk.rs | 67 ++++++++++++++-- tests/shaders/frag3.glsl | 9 +++ tests/shaders/vert3.glsl | 8 ++ tests/tests.rs | 161 ++++++++++++++++++++++++++++++++------- 6 files changed, 278 insertions(+), 37 deletions(-) create mode 100644 tests/shaders/frag3.glsl create mode 100644 tests/shaders/vert3.glsl diff --git a/src/layouts.rs b/src/layouts.rs index a48f90d..e049937 100644 --- a/src/layouts.rs +++ b/src/layouts.rs @@ -57,8 +57,16 @@ unsafe impl PipelineLayoutDesc for FragLayout { fn num_bindings_in_set(&self, set: usize) -> Option { self.layout_data.num_bindings.get(&set).map(|&i| i) } - fn descriptor(&self, _set: usize, _binding: usize) -> Option { - None + fn descriptor(&self, set: usize, binding: usize) -> Option { + self.layout_data.descriptions.get(&set) + .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 diff --git a/src/reflection.rs b/src/reflection.rs index 3de6284..a19407b 100644 --- a/src/reflection.rs +++ b/src/reflection.rs @@ -1,8 +1,8 @@ use crate::sr; -use crate::srvk::SpirvTy; +use crate::srvk::{SpirvTy,DescriptorDescInfo}; use std::borrow::Cow; use crate::vk::pipeline::shader::ShaderInterfaceDefEntry; -use crate::vk::descriptor::descriptor::ShaderStages; +use crate::vk::descriptor::descriptor::*; use std::collections::HashMap; use crate::CompiledShaders; use crate::layouts::*; @@ -16,11 +16,13 @@ pub struct ShaderInterfaces { pub struct LayoutData { pub num_sets: usize, pub num_bindings: HashMap, + pub descriptions: HashMap>, } 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_layout = FragLayout { @@ -28,7 +30,7 @@ pub fn create_entry(shaders: &CompiledShaders) -> Entry { fragment: true, ..ShaderStages::none() }, - layout_data: Default::default(), + layout_data: fragment_layout, }; let vert_input = VertInput{ inputs: vertex_interfaces.inputs }; let vert_output = VertOutput{ outputs: vertex_interfaces.outputs }; @@ -88,3 +90,53 @@ fn create_interfaces(data: &[u32]) -> ShaderInterfaces { }) .expect("failed to load module") } + +fn create_layouts(data: &[u32]) -> LayoutData { + sr::ShaderModule::load_u32_data(data) + .map(|m| { + m.enumerate_descriptor_sets(None) + .map(|sets| { + let num_sets = sets.len(); + let num_bindings = sets + .iter() + .map(|i| { + dbg!(&i); + (i.set as usize, i.bindings.len()) + }) + .collect::>(); + let descriptions = sets + .iter() + .map(|i| { + let desc = i.bindings.iter() + .map(|b| { + let info = DescriptorDescInfo{ + descriptor_type: b.descriptor_type, + image: b.image, + }; + let ty = SpirvTy::::from(info).inner(); + let stages = ShaderStages::none(); + let d = DescriptorDesc { + ty, + array_count: b.count, + stages, + // TODO this is what vulkan_shaders does but I don't think + // it's correct + readonly: true, + }; + (b.binding as usize, d) + }) + .collect::>(); + (i.set as usize, desc) + }) + .collect::>>(); + LayoutData { + num_sets, + num_bindings, + descriptions, + } + }) + .expect("Failed to pass outputs") + }) + .expect("failed to load module") +} + diff --git a/src/srvk.rs b/src/srvk.rs index ef4ea89..a1d1d52 100644 --- a/src/srvk.rs +++ b/src/srvk.rs @@ -1,7 +1,6 @@ use crate::sr; use crate::vk; use vk::descriptor::descriptor::*; -use vk::pipeline::shader::ShaderInterfaceDefEntry; use vk::format::Format; pub struct SpirvTy { @@ -9,8 +8,8 @@ pub struct SpirvTy { } pub struct DescriptorDescInfo { - descriptor_type: sr::types::ReflectDescriptorType, - image: sr::types::ReflectImageTraits, + pub descriptor_type: sr::types::ReflectDescriptorType, + pub image: sr::types::ReflectImageTraits, } impl SpirvTy { @@ -56,7 +55,9 @@ impl From for SpirvTy { let t = DescriptorImageDesc { sampled: d.sampled != 0, dimensions: SpirvTy::from(d.dim).inner(), - format: Some(SpirvTy::from(d.image_format).inner()), + // TODO figure out how to do format correctly + //format: Some(SpirvTy::from(d.image_format).inner()), + format: None, multisampled: d.ms != 0, array_layers: conv_array_layers(d.arrayed, d.depth), }; @@ -66,13 +67,67 @@ impl From for SpirvTy { impl From for SpirvTy { fn from(d: sr::types::variable::ReflectDimension) -> Self { - unimplemented!() + use sr::types::variable::ReflectDimension::*; + use DescriptorImageDescDimensions::*; + let inner = match d { + Type1d => OneDimensional, + Type2d => TwoDimensional, + Type3d => ThreeDimensional, + sr::types::variable::ReflectDimension::Cube => DescriptorImageDescDimensions::Cube, + _ => unimplemented!(), + }; + SpirvTy{ inner } } } +// I think this is wrong and currently is unused impl From for SpirvTy { fn from(d: sr::types::image::ReflectImageFormat) -> Self { - unimplemented!() + use sr::types::image::ReflectImageFormat::*; + use Format::*; + let inner = match d { + Undefined => unimplemented!(), + RGBA32_FLOAT => R32G32B32A32Sfloat, + RGBA16_FLOAT => R16G16B16A16Sfloat, + R32_FLOAT => R32Sfloat, + RGBA8 => unimplemented!(), + RGBA8_SNORM => R8G8B8A8Snorm, + RG32_FLOAT => R32G32Sfloat, + RG16_FLOAT => R16G16Sfloat, + R11G11B10_FLOAT => unimplemented!(), + R16_FLOAT => R16Sfloat, + RGBA16 => unimplemented!(), + RGB10A2 => unimplemented!(), + RG16 => unimplemented!(), + RG8 => unimplemented!(), + R16 => unimplemented!(), + R8 => unimplemented!(), + RGBA16_SNORM => R16G16B16A16Snorm, + RG16_SNORM => R16G16Snorm, + RG8_SNORM => R8G8Snorm, + R16_SNORM => R16Snorm, + R8_SNORM => R8Snorm, + RGBA32_INT => R32G32B32A32Sint, + RGBA16_INT => R16G16B16A16Sint, + RGBA8_INT => R8G8B8A8Sint, + R32_INT => R32Sint, + RG32_INT => R32G32Sint, + RG16_INT => R16G16Sint, + RG8_INT => R8G8Sint, + R16_INT => R16Sint, + R8_INT => R8Sint, + RGBA32_UINT => R32G32B32A32Uint, + RGBA16_UINT => R16G16B16A16Uint, + RGBA8_UINT => R8G8B8A8Uint, + R32_UINT => R32Uint, + RGB10A2_UINT => A2R10G10B10UintPack32, + RG32_UINT => R32G32Uint, + RG16_UINT => R16G16Uint, + RG8_UINT => R8G8Uint, + R16_UINT =>R16Uint, + R8_UINT =>R8Uint, + }; + SpirvTy{ inner } } } diff --git a/tests/shaders/frag3.glsl b/tests/shaders/frag3.glsl new file mode 100644 index 0000000..98eb844 --- /dev/null +++ b/tests/shaders/frag3.glsl @@ -0,0 +1,9 @@ +#version 450 + +layout(location = 0) out vec4 f_color; + +layout(set = 0, binding = 0) uniform sampler2D tex; + +void main() { + f_color = texture(tex, vec2(0.0, 0.5)); +} diff --git a/tests/shaders/vert3.glsl b/tests/shaders/vert3.glsl new file mode 100644 index 0000000..9848119 --- /dev/null +++ b/tests/shaders/vert3.glsl @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) in vec2 position; + +void main() { + gl_Position = vec4(position, 0.0, 1.0); +} + diff --git a/tests/tests.rs b/tests/tests.rs index 4b96f38..c5f70b4 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -4,9 +4,10 @@ use shade_runner::*; use std::borrow::Cow; use std::collections::HashMap; use std::path::{Path, PathBuf}; -use vulkano::descriptor::descriptor::ShaderStages; +use vulkano::descriptor::descriptor::*; use vulkano::format::*; use vulkano::pipeline::shader::ShaderInterfaceDefEntry; +use vulkano::descriptor::pipeline_layout::PipelineLayoutDesc; fn setup() { color_backtrace::install(); @@ -31,6 +32,27 @@ fn difference(e: &str, t: &str) -> String { .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, @@ -66,6 +88,7 @@ fn test_shade1() { layout_data: LayoutData { num_sets: 0, num_bindings: HashMap::new(), + descriptions: HashMap::new(), }, }, vert_input: VertInput { @@ -98,23 +121,23 @@ fn test_shade1() { fn test_shade2() { setup(); let target = Entry { - frag_input: FragInput { + frag_input: FragInput { inputs: vec![ ShaderInterfaceDefEntry { - location: 0..1, - format: Format::R32G32B32A32Sfloat, - name: Some(Cow::Borrowed("cool")), - }, + location: 0..1, + format: Format::R32G32B32A32Sfloat, + name: Some(Cow::Borrowed("cool")), + }, ShaderInterfaceDefEntry { - location: 1..2, - format: Format::R32G32Sfloat, - name: Some(Cow::Borrowed("yep")), - }, + location: 1..2, + format: Format::R32G32Sfloat, + name: Some(Cow::Borrowed("yep")), + }, ShaderInterfaceDefEntry { - location: 2..3, - format: Format::R32Sfloat, - name: Some(Cow::Borrowed("monkey")), - }, + location: 2..3, + format: Format::R32Sfloat, + name: Some(Cow::Borrowed("monkey")), + }, ], }, frag_output: FragOutput { @@ -132,6 +155,7 @@ fn test_shade2() { layout_data: LayoutData { num_sets: 0, num_bindings: HashMap::new(), + descriptions: HashMap::new(), }, }, vert_input: VertInput { @@ -144,20 +168,20 @@ fn test_shade2() { vert_output: VertOutput { outputs: vec![ ShaderInterfaceDefEntry { - location: 0..1, - format: Format::R32G32B32A32Sfloat, - name: Some(Cow::Borrowed("cool")), - }, + location: 0..1, + format: Format::R32G32B32A32Sfloat, + name: Some(Cow::Borrowed("cool")), + }, ShaderInterfaceDefEntry { - location: 1..2, - format: Format::R32G32Sfloat, - name: Some(Cow::Borrowed("yep")), - }, + location: 1..2, + format: Format::R32G32Sfloat, + name: Some(Cow::Borrowed("yep")), + }, ShaderInterfaceDefEntry { - location: 2..3, - format: Format::R32Sfloat, - name: Some(Cow::Borrowed("monkey")), - }, + location: 2..3, + format: Format::R32Sfloat, + name: Some(Cow::Borrowed("monkey")), + }, ], }, vert_layout: VertLayout(ShaderStages { @@ -176,3 +200,88 @@ fn test_shade2() { ); } +#[test] +fn test_shade3() { + 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: 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(), + }, + }, + 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("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)); + +} + +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) + ); +}