use std::cmp;
use std::ops::BitOr;
use format::Format;
use vk;
#[derive(Debug, Clone)]
pub struct DescriptorDesc {
pub ty: DescriptorDescTy,
pub array_count: u32,
pub stages: ShaderStages,
pub readonly: bool,
}
impl DescriptorDesc {
#[inline]
pub fn is_superset_of(&self, other: &DescriptorDesc) -> bool {
self.ty.is_superset_of(&other.ty) &&
self.array_count >= other.array_count && self.stages.is_superset_of(&other.stages) &&
(!self.readonly || other.readonly)
}
#[inline]
pub fn union(&self, other: &DescriptorDesc) -> Option<DescriptorDesc> {
if self.ty != other.ty { return None; }
Some(DescriptorDesc {
ty: self.ty.clone(),
array_count: cmp::max(self.array_count, other.array_count),
stages: self.stages | other.stages,
readonly: self.readonly && other.readonly,
})
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DescriptorDescTy {
Sampler, CombinedImageSampler(DescriptorImageDesc), Image(DescriptorImageDesc),
TexelBuffer {
storage: bool,
format: Option<Format>,
},
InputAttachment {
multisampled: bool,
array_layers: DescriptorImageDescArray,
},
Buffer(DescriptorBufferDesc),
}
impl DescriptorDescTy {
pub fn ty(&self) -> Option<DescriptorType> {
Some(match *self {
DescriptorDescTy::Sampler => DescriptorType::Sampler,
DescriptorDescTy::CombinedImageSampler(_) => DescriptorType::CombinedImageSampler,
DescriptorDescTy::Image(ref desc) => {
if desc.sampled { DescriptorType::SampledImage }
else { DescriptorType::StorageImage }
},
DescriptorDescTy::InputAttachment { .. } => DescriptorType::InputAttachment,
DescriptorDescTy::Buffer(ref desc) => {
let dynamic = match desc.dynamic { Some(d) => d, None => return None };
match (desc.storage, dynamic) {
(false, false) => DescriptorType::UniformBuffer,
(true, false) => DescriptorType::StorageBuffer,
(false, true) => DescriptorType::UniformBufferDynamic,
(true, true) => DescriptorType::StorageBufferDynamic,
}
},
DescriptorDescTy::TexelBuffer { storage, .. } => {
if storage { DescriptorType::StorageTexelBuffer }
else { DescriptorType::UniformTexelBuffer }
},
})
}
#[inline]
pub fn is_superset_of(&self, other: &DescriptorDescTy) -> bool {
match (self, other) {
(&DescriptorDescTy::Sampler, &DescriptorDescTy::Sampler) => true,
(&DescriptorDescTy::CombinedImageSampler(ref me),
&DescriptorDescTy::CombinedImageSampler(ref other)) => me.is_superset_of(other),
(&DescriptorDescTy::Image(ref me),
&DescriptorDescTy::Image(ref other)) => me.is_superset_of(other),
(&DescriptorDescTy::InputAttachment { multisampled: me_multisampled,
array_layers: me_array_layers },
&DescriptorDescTy::InputAttachment { multisampled: other_multisampled,
array_layers: other_array_layers }) =>
{
me_multisampled == other_multisampled && me_array_layers == other_array_layers
},
(&DescriptorDescTy::Buffer(ref me), &DescriptorDescTy::Buffer(ref other)) => {
if me.storage != other.storage {
return false;
}
match (me.dynamic, other.dynamic) {
(Some(_), None) => true,
(Some(m), Some(o)) => m == o,
(None, None) => true,
(None, Some(_)) => false,
}
},
(&DescriptorDescTy::TexelBuffer { storage: me_storage, format: me_format },
&DescriptorDescTy::TexelBuffer { storage: other_storage, format: other_format }) =>
{
if me_storage != other_storage {
return false;
}
match (me_format, other_format) {
(Some(_), None) => true,
(Some(m), Some(o)) => m == o,
(None, None) => true,
(None, Some(_)) => false,
}
},
_ => false
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DescriptorImageDesc {
pub sampled: bool,
pub dimensions: DescriptorImageDescDimensions,
pub format: Option<Format>,
pub multisampled: bool,
pub array_layers: DescriptorImageDescArray,
}
impl DescriptorImageDesc {
#[inline]
pub fn is_superset_of(&self, other: &DescriptorImageDesc) -> bool {
if self.dimensions != other.dimensions {
return false;
}
if self.multisampled != other.multisampled {
return false;
}
match (self.format, other.format) {
(Some(a), Some(b)) => if a != b { return false; },
(Some(_), None) => (),
(None, None) => (),
(None, Some(_)) => return false,
};
match (self.array_layers, other.array_layers) {
(DescriptorImageDescArray::NonArrayed, DescriptorImageDescArray::NonArrayed) => (),
(DescriptorImageDescArray::Arrayed { max_layers: my_max },
DescriptorImageDescArray::Arrayed { max_layers: other_max }) =>
{
match (my_max, other_max) {
(Some(m), Some(o)) => if m < o { return false; },
(Some(_), None) => (),
(None, Some(_)) => return false,
(None, None) => (), };
},
_ => return false
};
true
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum DescriptorImageDescArray {
NonArrayed,
Arrayed { max_layers: Option<u32> }
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum DescriptorImageDescDimensions {
OneDimensional,
TwoDimensional,
ThreeDimensional,
Cube,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DescriptorBufferDesc {
pub dynamic: Option<bool>,
pub storage: bool,
pub content: DescriptorBufferContentDesc,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DescriptorBufferContentDesc {
F32,
F64,
Struct {
},
Array {
len: Box<DescriptorBufferContentDesc>, num_array: usize
},
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
pub enum DescriptorType {
Sampler = vk::DESCRIPTOR_TYPE_SAMPLER,
CombinedImageSampler = vk::DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
SampledImage = vk::DESCRIPTOR_TYPE_SAMPLED_IMAGE,
StorageImage = vk::DESCRIPTOR_TYPE_STORAGE_IMAGE,
UniformTexelBuffer = vk::DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
StorageTexelBuffer = vk::DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
UniformBuffer = vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER,
StorageBuffer = vk::DESCRIPTOR_TYPE_STORAGE_BUFFER,
UniformBufferDynamic = vk::DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
StorageBufferDynamic = vk::DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
InputAttachment = vk::DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ShaderStages {
pub vertex: bool,
pub tessellation_control: bool,
pub tessellation_evaluation: bool,
pub geometry: bool,
pub fragment: bool,
pub compute: bool,
}
impl ShaderStages {
#[inline]
pub fn all() -> ShaderStages {
ShaderStages {
vertex: true,
tessellation_control: true,
tessellation_evaluation: true,
geometry: true,
fragment: true,
compute: true,
}
}
#[inline]
pub fn none() -> ShaderStages {
ShaderStages {
vertex: false,
tessellation_control: false,
tessellation_evaluation: false,
geometry: false,
fragment: false,
compute: false,
}
}
#[inline]
pub fn all_graphics() -> ShaderStages {
ShaderStages {
vertex: true,
tessellation_control: true,
tessellation_evaluation: true,
geometry: true,
fragment: true,
compute: false,
}
}
#[inline]
pub fn compute() -> ShaderStages {
ShaderStages {
vertex: false,
tessellation_control: false,
tessellation_evaluation: false,
geometry: false,
fragment: false,
compute: true,
}
}
#[inline]
pub fn is_superset_of(&self, other: &ShaderStages) -> bool {
(self.vertex || !other.vertex) &&
(self.tessellation_control || !other.tessellation_control) &&
(self.tessellation_evaluation || !other.tessellation_evaluation) &&
(self.geometry || !other.geometry) &&
(self.fragment || !other.fragment) &&
(self.compute || !other.compute)
}
#[inline]
pub fn intersects(&self, other: &ShaderStages) -> bool {
(self.vertex && other.vertex) ||
(self.tessellation_control && other.tessellation_control) ||
(self.tessellation_evaluation && other.tessellation_evaluation) ||
(self.geometry && other.geometry) ||
(self.fragment && other.fragment) ||
(self.compute && other.compute)
}
}
impl BitOr for ShaderStages {
type Output = ShaderStages;
#[inline]
fn bitor(self, other: ShaderStages) -> ShaderStages {
ShaderStages {
vertex: self.vertex || other.vertex,
tessellation_control: self.tessellation_control || other.tessellation_control,
tessellation_evaluation: self.tessellation_evaluation || other.tessellation_evaluation,
geometry: self.geometry || other.geometry,
fragment: self.fragment || other.fragment,
compute: self.compute || other.compute,
}
}
}
#[doc(hidden)]
impl Into<vk::ShaderStageFlags> for ShaderStages {
#[inline]
fn into(self) -> vk::ShaderStageFlags {
let mut result = 0;
if self.vertex { result |= vk::SHADER_STAGE_VERTEX_BIT; }
if self.tessellation_control { result |= vk::SHADER_STAGE_TESSELLATION_CONTROL_BIT; }
if self.tessellation_evaluation { result |= vk::SHADER_STAGE_TESSELLATION_EVALUATION_BIT; }
if self.geometry { result |= vk::SHADER_STAGE_GEOMETRY_BIT; }
if self.fragment { result |= vk::SHADER_STAGE_FRAGMENT_BIT; }
if self.compute { result |= vk::SHADER_STAGE_COMPUTE_BIT; }
result
}
}