Skip to main content

singe_npp/pipeline/image/
core.rs

1use singe_cuda::memory::DeviceMemory;
2
3use crate::{
4    context::StreamContext,
5    error::Result,
6    image::{
7        memory::Image,
8        view::{C1, ChannelLayout, ImageView},
9    },
10    pipeline::{ImageAllocator, Workspace, memory_context::validate_device_memory_stream_context},
11    types::Size,
12};
13
14/// Current storage behind a fluent image pipeline.
15#[derive(Debug)]
16#[non_exhaustive]
17pub enum ImageBacking<'a, T, L = C1> {
18    Borrowed(ImageView<'a, T, L>),
19    Owned(Image<T, L>),
20}
21
22/// Eager, stream-aware image processing pipeline.
23pub struct ImagePipeline<'a, T, L = C1> {
24    pub(super) stream_context: &'a StreamContext,
25    pub(super) workspace: &'a mut Workspace,
26    pub(super) backing: ImageBacking<'a, T, L>,
27}
28
29impl<'a, T, L> ImagePipeline<'a, T, L>
30where
31    T: Copy,
32    L: ChannelLayout,
33{
34    pub fn create(
35        stream_context: &'a StreamContext,
36        workspace: &'a mut Workspace,
37        size: Size,
38    ) -> Result<Self>
39    where
40        Workspace: ImageAllocator<T, L>,
41    {
42        let image = workspace.image::<T, L>(size)?;
43        Ok(Self::from_owned(stream_context, workspace, image))
44    }
45
46    pub fn from_view(
47        stream_context: &'a StreamContext,
48        workspace: &'a mut Workspace,
49        source: ImageView<'a, T, L>,
50    ) -> Self {
51        Self {
52            stream_context,
53            workspace,
54            backing: ImageBacking::Borrowed(source),
55        }
56    }
57
58    pub fn from_owned(
59        stream_context: &'a StreamContext,
60        workspace: &'a mut Workspace,
61        image: Image<T, L>,
62    ) -> Self {
63        Self {
64            stream_context,
65            workspace,
66            backing: ImageBacking::Owned(image),
67        }
68    }
69
70    pub fn from_memory(
71        stream_context: &'a StreamContext,
72        workspace: &'a mut Workspace,
73        memory: &'a DeviceMemory<T>,
74        size: Size,
75    ) -> Result<Self> {
76        validate_device_memory_stream_context(stream_context, memory)?;
77        Ok(Self::from_view(
78            stream_context,
79            workspace,
80            ImageView::from_memory(memory, size)?,
81        ))
82    }
83
84    pub fn from_memory_with_step(
85        stream_context: &'a StreamContext,
86        workspace: &'a mut Workspace,
87        memory: &'a DeviceMemory<T>,
88        size: Size,
89        step: i32,
90    ) -> Result<Self> {
91        validate_device_memory_stream_context(stream_context, memory)?;
92        Ok(Self::from_view(
93            stream_context,
94            workspace,
95            ImageView::from_memory_with_step(memory, size, step)?,
96        ))
97    }
98
99    pub const fn size(&self) -> Size {
100        match &self.backing {
101            ImageBacking::Borrowed(view) => view.size(),
102            ImageBacking::Owned(image) => image.size(),
103        }
104    }
105
106    pub const fn is_owned(&self) -> bool {
107        matches!(self.backing, ImageBacking::Owned(_))
108    }
109
110    pub(super) fn view(&self) -> Result<ImageView<'_, T, L>> {
111        match &self.backing {
112            ImageBacking::Borrowed(view) => Ok(*view),
113            ImageBacking::Owned(image) => image.view(),
114        }
115    }
116
117    pub fn into_backing(self) -> ImageBacking<'a, T, L> {
118        self.backing
119    }
120}