descriptor layout

master
Tom Gowan 6 years ago
parent 0755b4f807
commit f3346e48bb

@ -57,8 +57,16 @@ unsafe impl PipelineLayoutDesc for FragLayout {
fn num_bindings_in_set(&self, set: usize) -> Option<usize> { fn num_bindings_in_set(&self, set: usize) -> Option<usize> {
self.layout_data.num_bindings.get(&set).map(|&i| i) self.layout_data.num_bindings.get(&set).map(|&i| i)
} }
fn descriptor(&self, _set: usize, _binding: usize) -> Option<DescriptorDesc> { fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
None 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 { fn num_push_constants_ranges(&self) -> usize {
0 0

@ -1,8 +1,8 @@
use crate::sr; use crate::sr;
use crate::srvk::SpirvTy; use crate::srvk::{SpirvTy,DescriptorDescInfo};
use std::borrow::Cow; use std::borrow::Cow;
use crate::vk::pipeline::shader::ShaderInterfaceDefEntry; use crate::vk::pipeline::shader::ShaderInterfaceDefEntry;
use crate::vk::descriptor::descriptor::ShaderStages; use crate::vk::descriptor::descriptor::*;
use std::collections::HashMap; use std::collections::HashMap;
use crate::CompiledShaders; use crate::CompiledShaders;
use crate::layouts::*; use crate::layouts::*;
@ -16,11 +16,13 @@ pub struct ShaderInterfaces {
pub struct LayoutData { pub struct LayoutData {
pub num_sets: usize, pub num_sets: usize,
pub num_bindings: HashMap<usize, usize>, pub num_bindings: HashMap<usize, usize>,
pub descriptions: HashMap<usize, HashMap<usize, DescriptorDesc>>,
} }
pub fn create_entry(shaders: &CompiledShaders) -> Entry { pub fn create_entry(shaders: &CompiledShaders) -> Entry {
let vertex_interfaces = create_interfaces(&shaders.vertex); let vertex_interfaces = create_interfaces(&shaders.vertex);
let fragment_interfaces = create_interfaces(&shaders.fragment); let fragment_interfaces = create_interfaces(&shaders.fragment);
let fragment_layout = create_layouts(&shaders.fragment);
let frag_input = FragInput{ inputs: fragment_interfaces.inputs }; let frag_input = FragInput{ inputs: fragment_interfaces.inputs };
let frag_output = FragOutput{ outputs: fragment_interfaces.outputs }; let frag_output = FragOutput{ outputs: fragment_interfaces.outputs };
let frag_layout = FragLayout { let frag_layout = FragLayout {
@ -28,7 +30,7 @@ pub fn create_entry(shaders: &CompiledShaders) -> Entry {
fragment: true, fragment: true,
..ShaderStages::none() ..ShaderStages::none()
}, },
layout_data: Default::default(), layout_data: fragment_layout,
}; };
let vert_input = VertInput{ inputs: vertex_interfaces.inputs }; let vert_input = VertInput{ inputs: vertex_interfaces.inputs };
let vert_output = VertOutput{ outputs: vertex_interfaces.outputs }; let vert_output = VertOutput{ outputs: vertex_interfaces.outputs };
@ -88,3 +90,53 @@ fn create_interfaces(data: &[u32]) -> ShaderInterfaces {
}) })
.expect("failed to load module") .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::<HashMap<usize, usize>>();
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::<DescriptorDescTy>::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::<HashMap<usize, DescriptorDesc>>();
(i.set as usize, desc)
})
.collect::<HashMap<usize, HashMap<usize, DescriptorDesc>>>();
LayoutData {
num_sets,
num_bindings,
descriptions,
}
})
.expect("Failed to pass outputs")
})
.expect("failed to load module")
}

@ -1,7 +1,6 @@
use crate::sr; use crate::sr;
use crate::vk; use crate::vk;
use vk::descriptor::descriptor::*; use vk::descriptor::descriptor::*;
use vk::pipeline::shader::ShaderInterfaceDefEntry;
use vk::format::Format; use vk::format::Format;
pub struct SpirvTy<T> { pub struct SpirvTy<T> {
@ -9,8 +8,8 @@ pub struct SpirvTy<T> {
} }
pub struct DescriptorDescInfo { pub struct DescriptorDescInfo {
descriptor_type: sr::types::ReflectDescriptorType, pub descriptor_type: sr::types::ReflectDescriptorType,
image: sr::types::ReflectImageTraits, pub image: sr::types::ReflectImageTraits,
} }
impl<T> SpirvTy<T> { impl<T> SpirvTy<T> {
@ -56,7 +55,9 @@ impl From<sr::types::ReflectImageTraits> for SpirvTy<DescriptorImageDesc> {
let t = DescriptorImageDesc { let t = DescriptorImageDesc {
sampled: d.sampled != 0, sampled: d.sampled != 0,
dimensions: SpirvTy::from(d.dim).inner(), 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, multisampled: d.ms != 0,
array_layers: conv_array_layers(d.arrayed, d.depth), array_layers: conv_array_layers(d.arrayed, d.depth),
}; };
@ -66,13 +67,67 @@ impl From<sr::types::ReflectImageTraits> for SpirvTy<DescriptorImageDesc> {
impl From<sr::types::variable::ReflectDimension> for SpirvTy<DescriptorImageDescDimensions> { impl From<sr::types::variable::ReflectDimension> for SpirvTy<DescriptorImageDescDimensions> {
fn from(d: sr::types::variable::ReflectDimension) -> Self { 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<sr::types::image::ReflectImageFormat> for SpirvTy<Format> { impl From<sr::types::image::ReflectImageFormat> for SpirvTy<Format> {
fn from(d: sr::types::image::ReflectImageFormat) -> Self { 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 }
} }
} }

@ -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));
}

@ -0,0 +1,8 @@
#version 450
layout(location = 0) in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}

@ -4,9 +4,10 @@ use shade_runner::*;
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashMap; use std::collections::HashMap;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use vulkano::descriptor::descriptor::ShaderStages; use vulkano::descriptor::descriptor::*;
use vulkano::format::*; use vulkano::format::*;
use vulkano::pipeline::shader::ShaderInterfaceDefEntry; use vulkano::pipeline::shader::ShaderInterfaceDefEntry;
use vulkano::descriptor::pipeline_layout::PipelineLayoutDesc;
fn setup() { fn setup() {
color_backtrace::install(); color_backtrace::install();
@ -31,6 +32,27 @@ fn difference(e: &str, t: &str) -> String {
.join("\n") .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 fn parse<T>(vertex: T, fragment: T) -> shade_runner::Entry
where where
T: AsRef<Path>, T: AsRef<Path>,
@ -66,6 +88,7 @@ fn test_shade1() {
layout_data: LayoutData { layout_data: LayoutData {
num_sets: 0, num_sets: 0,
num_bindings: HashMap::new(), num_bindings: HashMap::new(),
descriptions: HashMap::new(),
}, },
}, },
vert_input: VertInput { vert_input: VertInput {
@ -101,20 +124,20 @@ fn test_shade2() {
frag_input: FragInput { frag_input: FragInput {
inputs: vec![ inputs: vec![
ShaderInterfaceDefEntry { ShaderInterfaceDefEntry {
location: 0..1, location: 0..1,
format: Format::R32G32B32A32Sfloat, format: Format::R32G32B32A32Sfloat,
name: Some(Cow::Borrowed("cool")), name: Some(Cow::Borrowed("cool")),
}, },
ShaderInterfaceDefEntry { ShaderInterfaceDefEntry {
location: 1..2, location: 1..2,
format: Format::R32G32Sfloat, format: Format::R32G32Sfloat,
name: Some(Cow::Borrowed("yep")), name: Some(Cow::Borrowed("yep")),
}, },
ShaderInterfaceDefEntry { ShaderInterfaceDefEntry {
location: 2..3, location: 2..3,
format: Format::R32Sfloat, format: Format::R32Sfloat,
name: Some(Cow::Borrowed("monkey")), name: Some(Cow::Borrowed("monkey")),
}, },
], ],
}, },
frag_output: FragOutput { frag_output: FragOutput {
@ -132,6 +155,7 @@ fn test_shade2() {
layout_data: LayoutData { layout_data: LayoutData {
num_sets: 0, num_sets: 0,
num_bindings: HashMap::new(), num_bindings: HashMap::new(),
descriptions: HashMap::new(),
}, },
}, },
vert_input: VertInput { vert_input: VertInput {
@ -144,20 +168,20 @@ fn test_shade2() {
vert_output: VertOutput { vert_output: VertOutput {
outputs: vec![ outputs: vec![
ShaderInterfaceDefEntry { ShaderInterfaceDefEntry {
location: 0..1, location: 0..1,
format: Format::R32G32B32A32Sfloat, format: Format::R32G32B32A32Sfloat,
name: Some(Cow::Borrowed("cool")), name: Some(Cow::Borrowed("cool")),
}, },
ShaderInterfaceDefEntry { ShaderInterfaceDefEntry {
location: 1..2, location: 1..2,
format: Format::R32G32Sfloat, format: Format::R32G32Sfloat,
name: Some(Cow::Borrowed("yep")), name: Some(Cow::Borrowed("yep")),
}, },
ShaderInterfaceDefEntry { ShaderInterfaceDefEntry {
location: 2..3, location: 2..3,
format: Format::R32Sfloat, format: Format::R32Sfloat,
name: Some(Cow::Borrowed("monkey")), name: Some(Cow::Borrowed("monkey")),
}, },
], ],
}, },
vert_layout: VertLayout(ShaderStages { 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<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)
);
}

Loading…
Cancel
Save