use format::Format;
use image::Dimensions;
use sync::AccessFlagBits;
use sync::PipelineStages;
use std::cmp;
use std::ops::BitOr;
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,
})
}
pub fn pipeline_stages_and_access(&self) -> (PipelineStages, AccessFlagBits) {
let stages: PipelineStages = self.stages.into();
let access = match self.ty {
DescriptorDescTy::Sampler => panic!(),
DescriptorDescTy::CombinedImageSampler(_) | DescriptorDescTy::Image(_) => {
AccessFlagBits {
shader_read: true,
shader_write: !self.readonly,
.. AccessFlagBits::none()
}
},
DescriptorDescTy::TexelBuffer { .. } => {
AccessFlagBits {
shader_read: true,
shader_write: !self.readonly,
.. AccessFlagBits::none()
}
},
DescriptorDescTy::InputAttachment { .. } => {
AccessFlagBits {
input_attachment_read: true,
.. AccessFlagBits::none()
}
},
DescriptorDescTy::Buffer(ref buf) => {
if buf.storage {
AccessFlagBits {
shader_read: true,
shader_write: !self.readonly,
.. AccessFlagBits::none()
}
} else {
AccessFlagBits {
uniform_read: true,
.. AccessFlagBits::none()
}
}
},
};
(stages, access)
}
}
#[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,
}
impl DescriptorImageDescDimensions {
#[inline]
pub fn from_dimensions(dims: Dimensions) -> DescriptorImageDescDimensions {
match dims {
Dimensions::Dim1d { .. } => DescriptorImageDescDimensions::OneDimensional,
Dimensions::Dim1dArray { .. } => DescriptorImageDescDimensions::OneDimensional,
Dimensions::Dim2d { .. } => DescriptorImageDescDimensions::TwoDimensional,
Dimensions::Dim2dArray { .. } => DescriptorImageDescDimensions::TwoDimensional,
Dimensions::Dim3d { .. } => DescriptorImageDescDimensions::ThreeDimensional,
Dimensions::Cubemap { .. } => DescriptorImageDescDimensions::Cube,
Dimensions::CubemapArray { .. } => DescriptorImageDescDimensions::Cube,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DescriptorBufferDesc {
pub dynamic: Option<bool>,
pub storage: bool,
}
#[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)
}
#[inline]
pub(crate) fn into_vulkan_bits(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
}
}
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,
}
}
}
impl From<ShaderStages> for PipelineStages {
#[inline]
fn from(stages: ShaderStages) -> PipelineStages {
PipelineStages {
vertex_shader: stages.vertex,
tessellation_control_shader: stages.tessellation_control,
tessellation_evaluation_shader: stages.tessellation_evaluation,
geometry_shader: stages.geometry,
fragment_shader: stages.fragment,
compute_shader: stages.compute,
.. PipelineStages::none()
}
}
}