use smallvec::SmallVec;
use std::fmt;
use std::mem;
use std::ptr;
use std::sync::Arc;
use OomError;
use VulkanObject;
use check_errors;
use vk;
use descriptor::descriptor::DescriptorDesc;
use descriptor::descriptor_set::DescriptorsCount;
use device::Device;
use device::DeviceOwned;
pub struct UnsafeDescriptorSetLayout {
layout: vk::DescriptorSetLayout,
device: Arc<Device>,
descriptors_count: DescriptorsCount,
}
impl UnsafeDescriptorSetLayout {
pub fn new<I>(device: Arc<Device>, descriptors: I)
-> Result<UnsafeDescriptorSetLayout, OomError>
where I: IntoIterator<Item = Option<DescriptorDesc>>
{
let mut descriptors_count = DescriptorsCount::zero();
let bindings = descriptors
.into_iter()
.enumerate()
.filter_map(|(binding, desc)| {
let desc = match desc {
Some(d) => d,
None => return None,
};
let ty = desc.ty.ty().unwrap(); descriptors_count.add_one(ty);
Some(vk::DescriptorSetLayoutBinding {
binding: binding as u32,
descriptorType: ty as u32,
descriptorCount: desc.array_count,
stageFlags: desc.stages.into_vulkan_bits(),
pImmutableSamplers: ptr::null(), })
})
.collect::<SmallVec<[_; 32]>>();
let layout = unsafe {
let infos = vk::DescriptorSetLayoutCreateInfo {
sType: vk::STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
pNext: ptr::null(),
flags: 0, bindingCount: bindings.len() as u32,
pBindings: bindings.as_ptr(),
};
let mut output = mem::uninitialized();
let vk = device.pointers();
check_errors(vk.CreateDescriptorSetLayout(device.internal_object(),
&infos,
ptr::null(),
&mut output))?;
output
};
Ok(UnsafeDescriptorSetLayout {
layout: layout,
device: device,
descriptors_count: descriptors_count,
})
}
#[inline]
pub fn descriptors_count(&self) -> &DescriptorsCount {
&self.descriptors_count
}
}
unsafe impl DeviceOwned for UnsafeDescriptorSetLayout {
#[inline]
fn device(&self) -> &Arc<Device> {
&self.device
}
}
impl fmt::Debug for UnsafeDescriptorSetLayout {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fmt.debug_struct("UnsafeDescriptorSetLayout")
.field("raw", &self.layout)
.field("device", &self.device)
.finish()
}
}
unsafe impl VulkanObject for UnsafeDescriptorSetLayout {
type Object = vk::DescriptorSetLayout;
#[inline]
fn internal_object(&self) -> vk::DescriptorSetLayout {
self.layout
}
}
impl Drop for UnsafeDescriptorSetLayout {
#[inline]
fn drop(&mut self) {
unsafe {
let vk = self.device.pointers();
vk.DestroyDescriptorSetLayout(self.device.internal_object(), self.layout, ptr::null());
}
}
}
#[cfg(test)]
mod tests {
use descriptor::descriptor::DescriptorBufferDesc;
use descriptor::descriptor::DescriptorDesc;
use descriptor::descriptor::DescriptorDescTy;
use descriptor::descriptor::ShaderStages;
use descriptor::descriptor_set::DescriptorsCount;
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use std::iter;
#[test]
fn empty() {
let (device, _) = gfx_dev_and_queue!();
let _layout = UnsafeDescriptorSetLayout::new(device, iter::empty());
}
#[test]
fn basic_create() {
let (device, _) = gfx_dev_and_queue!();
let layout = DescriptorDesc {
ty: DescriptorDescTy::Buffer(DescriptorBufferDesc {
dynamic: Some(false),
storage: false,
}),
array_count: 1,
stages: ShaderStages::all_graphics(),
readonly: true,
};
let sl = UnsafeDescriptorSetLayout::new(device.clone(), iter::once(Some(layout))).unwrap();
assert_eq!(sl.descriptors_count(),
&DescriptorsCount {
uniform_buffer: 1,
..DescriptorsCount::zero()
});
}
}