aboutsummaryrefslogtreecommitdiff
path: root/src/pipeline/layout/sys.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/pipeline/layout/sys.rs')
-rw-r--r--src/pipeline/layout/sys.rs469
1 files changed, 0 insertions, 469 deletions
diff --git a/src/pipeline/layout/sys.rs b/src/pipeline/layout/sys.rs
deleted file mode 100644
index 7d6d33b..0000000
--- a/src/pipeline/layout/sys.rs
+++ /dev/null
@@ -1,469 +0,0 @@
-// Copyright (c) 2016 The vulkano developers
-// Licensed under the Apache License, Version 2.0
-// <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
-// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
-// at your option. All files in the project carrying such
-// notice may not be copied, modified, or distributed except
-// according to those terms.
-
-use super::limits_check;
-use crate::check_errors;
-use crate::descriptor_set::layout::DescriptorSetDesc;
-use crate::descriptor_set::layout::DescriptorSetDescSupersetError;
-use crate::descriptor_set::layout::DescriptorSetLayout;
-use crate::device::Device;
-use crate::device::DeviceOwned;
-use crate::pipeline::layout::PipelineLayoutLimitsError;
-use crate::pipeline::shader::ShaderStages;
-use crate::Error;
-use crate::OomError;
-use crate::VulkanObject;
-use smallvec::SmallVec;
-use std::cmp;
-use std::error;
-use std::fmt;
-use std::mem::MaybeUninit;
-use std::ptr;
-use std::sync::Arc;
-
-/// Wrapper around the `PipelineLayout` Vulkan object. Describes to the Vulkan implementation the
-/// descriptor sets and push constants available to your shaders.
-pub struct PipelineLayout {
- handle: ash::vk::PipelineLayout,
- device: Arc<Device>,
- descriptor_set_layouts: SmallVec<[Arc<DescriptorSetLayout>; 16]>,
- push_constant_ranges: SmallVec<[PipelineLayoutPcRange; 8]>,
-}
-
-impl PipelineLayout {
- /// Creates a new `PipelineLayout`.
- #[inline]
- pub fn new<D, P>(
- device: Arc<Device>,
- descriptor_set_layouts: D,
- push_constant_ranges: P,
- ) -> Result<PipelineLayout, PipelineLayoutCreationError>
- where
- D: IntoIterator<Item = Arc<DescriptorSetLayout>>,
- P: IntoIterator<Item = PipelineLayoutPcRange>,
- {
- let fns = device.fns();
- let descriptor_set_layouts: SmallVec<[Arc<DescriptorSetLayout>; 16]> =
- descriptor_set_layouts.into_iter().collect();
- let push_constant_ranges: SmallVec<[PipelineLayoutPcRange; 8]> =
- push_constant_ranges.into_iter().collect();
-
- // Check for overlapping stages
- for (a_id, a) in push_constant_ranges.iter().enumerate() {
- for b in push_constant_ranges.iter().skip(a_id + 1) {
- if a.stages.intersects(&b.stages) {
- return Err(PipelineLayoutCreationError::PushConstantsConflict {
- first_range: *a,
- second_range: *b,
- });
- }
- }
- }
-
- // Check against device limits
- limits_check::check_desc_against_limits(
- device.physical_device().properties(),
- &descriptor_set_layouts,
- &push_constant_ranges,
- )?;
-
- // Grab the list of `vkDescriptorSetLayout` objects from `layouts`.
- let layouts_ids = descriptor_set_layouts
- .iter()
- .map(|l| l.internal_object())
- .collect::<SmallVec<[_; 16]>>();
-
- // Builds a list of `vkPushConstantRange` that describe the push constants.
- let push_constants = {
- let mut out: SmallVec<[_; 8]> = SmallVec::new();
-
- for &PipelineLayoutPcRange {
- offset,
- size,
- stages,
- } in &push_constant_ranges
- {
- if stages == ShaderStages::none() || size == 0 || (size % 4) != 0 {
- return Err(PipelineLayoutCreationError::InvalidPushConstant);
- }
-
- out.push(ash::vk::PushConstantRange {
- stage_flags: stages.into(),
- offset: offset as u32,
- size: size as u32,
- });
- }
-
- out
- };
-
- // Each bit of `stageFlags` must only be present in a single push constants range.
- // We check that with a debug_assert because it's supposed to be enforced by the
- // `PipelineLayoutDesc`.
- debug_assert!({
- let mut stages = ash::vk::ShaderStageFlags::empty();
- let mut outcome = true;
- for pc in push_constants.iter() {
- if !(stages & pc.stage_flags).is_empty() {
- outcome = false;
- break;
- }
- stages &= pc.stage_flags;
- }
- outcome
- });
-
- // FIXME: it is not legal to pass eg. the TESSELLATION_SHADER bit when the device doesn't
- // have tess shaders enabled
-
- // Build the final object.
- let handle = unsafe {
- let infos = ash::vk::PipelineLayoutCreateInfo {
- flags: ash::vk::PipelineLayoutCreateFlags::empty(),
- set_layout_count: layouts_ids.len() as u32,
- p_set_layouts: layouts_ids.as_ptr(),
- push_constant_range_count: push_constants.len() as u32,
- p_push_constant_ranges: push_constants.as_ptr(),
- ..Default::default()
- };
-
- let mut output = MaybeUninit::uninit();
- check_errors(fns.v1_0.create_pipeline_layout(
- device.internal_object(),
- &infos,
- ptr::null(),
- output.as_mut_ptr(),
- ))?;
- output.assume_init()
- };
-
- Ok(PipelineLayout {
- handle,
- device: device.clone(),
- descriptor_set_layouts,
- push_constant_ranges,
- })
- }
-}
-
-impl PipelineLayout {
- /// Returns the descriptor set layouts this pipeline layout was created from.
- #[inline]
- pub fn descriptor_set_layouts(&self) -> &[Arc<DescriptorSetLayout>] {
- &self.descriptor_set_layouts
- }
-
- /// Returns a slice containing the push constant ranges this pipeline layout was created from.
- #[inline]
- pub fn push_constant_ranges(&self) -> &[PipelineLayoutPcRange] {
- &self.push_constant_ranges
- }
-
- /// Makes sure that `self` is a superset of the provided descriptor set layouts and push
- /// constant ranges. Returns an `Err` if this is not the case.
- pub fn ensure_superset_of(
- &self,
- descriptor_set_layout_descs: &[DescriptorSetDesc],
- push_constant_range: &Option<PipelineLayoutPcRange>,
- ) -> Result<(), PipelineLayoutSupersetError> {
- // Ewwwwwww
- let empty = DescriptorSetDesc::empty();
- let num_sets = cmp::max(
- self.descriptor_set_layouts.len(),
- descriptor_set_layout_descs.len(),
- );
-
- for set_num in 0..num_sets {
- let first = self
- .descriptor_set_layouts
- .get(set_num)
- .map(|set| set.desc())
- .unwrap_or_else(|| &empty);
- let second = descriptor_set_layout_descs
- .get(set_num)
- .unwrap_or_else(|| &empty);
-
- if let Err(error) = first.ensure_superset_of(second) {
- return Err(PipelineLayoutSupersetError::DescriptorSet {
- error,
- set_num: set_num as u32,
- });
- }
- }
-
- // FIXME: check push constants
- if let Some(range) = push_constant_range {
- for own_range in self.push_constant_ranges.as_ref().into_iter() {
- if range.stages.intersects(&own_range.stages) && // check if it shares any stages
- (range.offset < own_range.offset || // our range must start before and end after the given range
- own_range.offset + own_range.size < range.offset + range.size) {
- return Err(PipelineLayoutSupersetError::PushConstantRange {
- first_range: *own_range,
- second_range: *range,
- });
- }
- }
- }
-
- Ok(())
- }
-}
-
-unsafe impl DeviceOwned for PipelineLayout {
- #[inline]
- fn device(&self) -> &Arc<Device> {
- &self.device
- }
-}
-
-unsafe impl VulkanObject for PipelineLayout {
- type Object = ash::vk::PipelineLayout;
-
- fn internal_object(&self) -> Self::Object {
- self.handle
- }
-}
-
-impl fmt::Debug for PipelineLayout {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- fmt.debug_struct("PipelineLayout")
- .field("raw", &self.handle)
- .field("device", &self.device)
- .field("descriptor_set_layouts", &self.descriptor_set_layouts)
- .field("push_constant_ranges", &self.push_constant_ranges)
- .finish()
- }
-}
-
-impl Drop for PipelineLayout {
- #[inline]
- fn drop(&mut self) {
- unsafe {
- let fns = self.device.fns();
- fns.v1_0.destroy_pipeline_layout(
- self.device.internal_object(),
- self.handle,
- ptr::null(),
- );
- }
- }
-}
-
-/// Error that can happen when creating a pipeline layout.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum PipelineLayoutCreationError {
- /// Not enough memory.
- OomError(OomError),
- /// The pipeline layout description doesn't fulfill the limit requirements.
- LimitsError(PipelineLayoutLimitsError),
- /// One of the push constants range didn't obey the rules. The list of stages must not be
- /// empty, the size must not be 0, and the size must be a multiple or 4.
- InvalidPushConstant,
- /// Conflict between different push constants ranges.
- PushConstantsConflict {
- first_range: PipelineLayoutPcRange,
- second_range: PipelineLayoutPcRange,
- },
-}
-
-impl error::Error for PipelineLayoutCreationError {
- #[inline]
- fn source(&self) -> Option<&(dyn error::Error + 'static)> {
- match *self {
- PipelineLayoutCreationError::OomError(ref err) => Some(err),
- PipelineLayoutCreationError::LimitsError(ref err) => Some(err),
- _ => None,
- }
- }
-}
-
-impl fmt::Display for PipelineLayoutCreationError {
- #[inline]
- fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(
- fmt,
- "{}",
- match *self {
- PipelineLayoutCreationError::OomError(_) => "not enough memory available",
- PipelineLayoutCreationError::LimitsError(_) => {
- "the pipeline layout description doesn't fulfill the limit requirements"
- }
- PipelineLayoutCreationError::InvalidPushConstant => {
- "one of the push constants range didn't obey the rules"
- }
- PipelineLayoutCreationError::PushConstantsConflict { .. } => {
- "conflict between different push constants ranges"
- }
- }
- )
- }
-}
-
-impl From<OomError> for PipelineLayoutCreationError {
- #[inline]
- fn from(err: OomError) -> PipelineLayoutCreationError {
- PipelineLayoutCreationError::OomError(err)
- }
-}
-
-impl From<PipelineLayoutLimitsError> for PipelineLayoutCreationError {
- #[inline]
- fn from(err: PipelineLayoutLimitsError) -> PipelineLayoutCreationError {
- PipelineLayoutCreationError::LimitsError(err)
- }
-}
-
-impl From<Error> for PipelineLayoutCreationError {
- #[inline]
- fn from(err: Error) -> PipelineLayoutCreationError {
- match err {
- err @ Error::OutOfHostMemory => {
- PipelineLayoutCreationError::OomError(OomError::from(err))
- }
- err @ Error::OutOfDeviceMemory => {
- PipelineLayoutCreationError::OomError(OomError::from(err))
- }
- _ => panic!("unexpected error: {:?}", err),
- }
- }
-}
-
-/// Error when checking whether a pipeline layout is a superset of another one.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum PipelineLayoutSupersetError {
- DescriptorSet {
- error: DescriptorSetDescSupersetError,
- set_num: u32,
- },
- PushConstantRange {
- first_range: PipelineLayoutPcRange,
- second_range: PipelineLayoutPcRange,
- },
-}
-
-impl error::Error for PipelineLayoutSupersetError {
- #[inline]
- fn source(&self) -> Option<&(dyn error::Error + 'static)> {
- match *self {
- PipelineLayoutSupersetError::DescriptorSet { ref error, .. } => Some(error),
- ref error @ PipelineLayoutSupersetError::PushConstantRange { .. } => Some(error),
- }
- }
-}
-
-impl fmt::Display for PipelineLayoutSupersetError {
- #[inline]
- fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- match *self {
- PipelineLayoutSupersetError::DescriptorSet { .. } => {
- write!(
- fmt,
- "the descriptor set was not a superset of the other"
- )
- },
- PipelineLayoutSupersetError::PushConstantRange { first_range, second_range } => {
- writeln!(fmt, "our range did not completely encompass the other range")?;
- writeln!(fmt, " our stages: {:?}", first_range.stages)?;
- writeln!(
- fmt,
- " our range: {} - {}",
- first_range.offset,
- first_range.offset + first_range.size
- )?;
- writeln!(fmt, " other stages: {:?}", second_range.stages)?;
- write!(fmt,
- " other range: {} - {}",
- second_range.offset,
- second_range.offset + second_range.size
- )
- },
- }
- }
-}
-
-/// Description of a range of the push constants of a pipeline layout.
-// TODO: should contain the layout as well
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
-pub struct PipelineLayoutPcRange {
- /// Offset in bytes from the start of the push constants to this range.
- pub offset: usize,
- /// Size in bytes of the range.
- pub size: usize,
- /// The stages which can access this range. Note that the same shader stage can't access two
- /// different ranges.
- pub stages: ShaderStages,
-}
-
-/* TODO: restore
-#[cfg(test)]
-mod tests {
- use std::iter;
- use std::sync::Arc;
- use descriptor::descriptor::ShaderStages;
- use descriptor::descriptor_set::DescriptorSetLayout;
- use descriptor::pipeline_layout::sys::PipelineLayout;
- use descriptor::pipeline_layout::sys::PipelineLayoutCreationError;
-
- #[test]
- fn empty() {
- let (device, _) = gfx_dev_and_queue!();
- let _layout = PipelineLayout::new(&device, iter::empty(), iter::empty()).unwrap();
- }
-
- #[test]
- fn wrong_device_panic() {
- let (device1, _) = gfx_dev_and_queue!();
- let (device2, _) = gfx_dev_and_queue!();
-
- let set = match DescriptorSetLayout::raw(device1, iter::empty()) {
- Ok(s) => Arc::new(s),
- Err(_) => return
- };
-
- assert_should_panic!({
- let _ = PipelineLayout::new(&device2, Some(&set), iter::empty());
- });
- }
-
- #[test]
- fn invalid_push_constant_stages() {
- let (device, _) = gfx_dev_and_queue!();
-
- let push_constant = (0, 8, ShaderStages::none());
-
- match PipelineLayout::new(&device, iter::empty(), Some(push_constant)) {
- Err(PipelineLayoutCreationError::InvalidPushConstant) => (),
- _ => panic!()
- }
- }
-
- #[test]
- fn invalid_push_constant_size1() {
- let (device, _) = gfx_dev_and_queue!();
-
- let push_constant = (0, 0, ShaderStages::all_graphics());
-
- match PipelineLayout::new(&device, iter::empty(), Some(push_constant)) {
- Err(PipelineLayoutCreationError::InvalidPushConstant) => (),
- _ => panic!()
- }
- }
-
- #[test]
- fn invalid_push_constant_size2() {
- let (device, _) = gfx_dev_and_queue!();
-
- let push_constant = (0, 11, ShaderStages::all_graphics());
-
- match PipelineLayout::new(&device, iter::empty(), Some(push_constant)) {
- Err(PipelineLayoutCreationError::InvalidPushConstant) => (),
- _ => panic!()
- }
- }
-}*/