open_cl_low_level/
work.rs1use crate::{Dims, Error, Output};
3
4#[derive(Debug, Fail, Clone, Eq, PartialEq)]
5pub enum WorkError {
6 #[fail(display = "Work does not allow a zero value for any of its specified dimenions")]
7 DimLengthCannotBeZero,
8
9 #[fail(display = "Work dimensions must be 1, 2, or 3.")]
10 InvalidDimsCount,
11
12 #[fail(display = "Work size dimensions cannot have any zero values")]
13 InvalidWorkSize,
14}
15
16const INVALID_WORK_SIZE: Error = Error::WorkError(WorkError::InvalidWorkSize);
17
18#[derive(Debug, PartialEq, Eq, Clone)]
20pub struct NonZeroVolume3DArray([usize; 3]);
21
22impl NonZeroVolume3DArray {
23 fn as_ptr(&self) -> *const usize {
24 self.0.as_ptr()
25 }
26}
27
28impl NonZeroVolume3DArray {
29 fn from_dims(d: &Dims) -> Output<NonZeroVolume3DArray> {
30 let work_size: [usize; 3] = match d {
31 Dims::One(x) => [*x, 1, 1],
32 Dims::Two(x, y) => [*x, *y, 1],
33 Dims::Three(x, y, z) => [*x, *y, *z],
34 };
35 match work_size {
36 [0, _, _] | [_, 0, _] | [_, _, 0] => Err(INVALID_WORK_SIZE),
37 w => Ok(NonZeroVolume3DArray(w)),
38 }
39 }
40}
41
42#[derive(Debug, PartialEq, Eq, Clone)]
43pub struct GlobalWorkSize(NonZeroVolume3DArray);
44
45impl GlobalWorkSize {
46 pub fn from_dims(dims: &Dims) -> Output<GlobalWorkSize> {
47 let arr = NonZeroVolume3DArray::from_dims(dims)?;
48 Ok(GlobalWorkSize(arr))
49 }
50
51 pub fn as_ptr(&self) -> *const usize {
52 self.0.as_ptr()
53 }
54}
55
56#[derive(Debug, PartialEq, Eq, Clone)]
57pub enum LocalWorkSize {
58 WorkSize(NonZeroVolume3DArray),
59 Null,
60}
61
62impl LocalWorkSize {
63 pub fn from_dims(dims: &Dims) -> Output<LocalWorkSize> {
64 let arr = NonZeroVolume3DArray::from_dims(dims)?;
65 Ok(LocalWorkSize::WorkSize(arr))
66 }
67
68 pub fn as_ptr(&self) -> *const usize {
69 match self {
70 LocalWorkSize::WorkSize(arr) => arr.as_ptr(),
71 LocalWorkSize::Null => std::ptr::null::<usize>(),
72 }
73 }
74}
75
76#[derive(Debug, PartialEq, Eq, Clone)]
77pub enum GlobalWorkOffset {
78 Offset([usize; 3]),
79 Null,
80}
81
82impl GlobalWorkOffset {
83 pub fn from_dims(d: &Dims) -> GlobalWorkOffset {
84 let work_offset: [usize; 3] = match d {
85 Dims::One(x) => [*x, 0, 0],
86 Dims::Two(x, y) => [*x, *y, 0],
87 Dims::Three(x, y, z) => [*x, *y, *z],
88 };
89 GlobalWorkOffset::Offset(work_offset)
90 }
91
92 pub fn as_ptr(&self) -> *const usize {
93 match self {
94 GlobalWorkOffset::Offset(arr) => arr.as_ptr(),
95 GlobalWorkOffset::Null => std::ptr::null::<usize>(),
96 }
97 }
98}
99
100#[derive(Debug, Clone, Eq, PartialEq)]
108pub struct Work {
109 pub global_size: Dims,
110 pub global_offset: Option<Dims>,
111 pub local_size: Option<Dims>,
112}
113
114impl Work {
115 pub fn new<D: Into<Dims>>(global_size: D) -> Work {
116 Work {
117 global_size: global_size.into(),
118 global_offset: None,
119 local_size: None,
120 }
121 }
122
123 pub fn with_global_offset<D: Into<Dims>>(mut self, offset: D) -> Work {
124 self.global_offset = Some(offset.into());
125 self
126 }
127
128 pub fn with_local_size<D: Into<Dims>>(mut self, local_size: D) -> Work {
129 self.local_size = Some(local_size.into());
130 self
131 }
132
133 pub fn work_dims(&self) -> u32 {
134 self.global_size.n_dimensions() as u32
135 }
136
137 pub fn global_work_size(&self) -> Output<GlobalWorkSize> {
144 GlobalWorkSize::from_dims(&self.global_size)
145 }
146
147 pub fn global_work_offset(&self) -> GlobalWorkOffset {
153 match &self.global_offset {
154 Some(dims) => GlobalWorkOffset::from_dims(dims),
155 None => GlobalWorkOffset::Null,
156 }
157 }
158
159 pub fn local_work_size(&self) -> Output<LocalWorkSize> {
160 match &self.local_size {
161 Some(dims) => LocalWorkSize::from_dims(dims),
162 None => Ok(LocalWorkSize::Null),
163 }
164 }
165
166 pub fn n_items(&self) -> usize {
167 self.global_size.n_items()
168 }
169}