1#![allow(non_snake_case)]
18
19use core::ops::{BitAnd, BitOr};
20
21use teeny_core::dtype::Num;
22use teeny_macros::kernel;
23use teeny_triton::triton::{
24 types::{AddOffsets, Comparison, Tensor},
25 *,
26};
27
28#[kernel]
32pub fn reflection_pad3d_forward<
33 T: Triton,
34 D: Num,
35 const PD1: i32,
36 const PD2: i32,
37 const PH1: i32,
38 const PH2: i32,
39 const PW1: i32,
40 const PW2: i32,
41 const BLOCK_OW: i32,
42>(
43 input_ptr: T::Pointer<D>,
44 output_ptr: T::Pointer<D>,
45 _B: i32,
46 C: i32,
47 Dv: i32,
48 H: i32,
49 W: i32,
50 OD: i32,
51 OH: i32,
52 OW: i32,
53) where
54 T::I32Tensor: Tensor<i32, 1>,
55 T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
56 T::BoolTensor: BitAnd<Output = T::BoolTensor>,
57 T::BoolTensor: BitOr<Output = T::BoolTensor>,
58 T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
59{
60 let pid = T::program_id(Axis::X);
61 let num_ow_tiles = T::cdiv(OW, BLOCK_OW);
62
63 let ow_tile = pid % num_ow_tiles;
64 let rest = pid / num_ow_tiles;
65 let oh = rest % OH;
66 let rest2 = rest / OH;
67 let od = rest2 % OD;
68 let bco = rest2 / OD;
69 let c = bco % C;
70 let b = bco / C;
71
72 let ow_start = ow_tile * BLOCK_OW;
73 let ow_range = T::arange(0, BLOCK_OW) + ow_start;
74 let ow_mask = ow_range.lt(OW);
75
76 let id_raw = od - PD1;
77 let id = if id_raw < 0 {
78 -id_raw
79 } else if id_raw >= Dv {
80 2 * (Dv - 1) - id_raw
81 } else {
82 id_raw
83 };
84
85 let ih_raw = oh - PH1;
86 let ih = if ih_raw < 0 {
87 -ih_raw
88 } else if ih_raw >= H {
89 2 * (H - 1) - ih_raw
90 } else {
91 ih_raw
92 };
93
94 let in_bc_base = ((b * C + c) * Dv + id) * H * W + ih * W;
95 let out_bc_base = (((b * C + c) * OD + od) * OH + oh) * OW;
96
97 let iw_raw = ow_range - PW1;
98 let left_cond = iw_raw.lt(0);
99 let right_cond = iw_raw.ge(W);
100 let in_bounds = iw_raw.ge(0) & iw_raw.lt(W);
101
102 let iw_left = iw_raw * (-1);
103 let iw_right = iw_raw * (-1) + (2 * (W - 1));
104
105 let zeros = T::zeros::<D>(&[BLOCK_OW]);
106 let val_center = T::load(
107 input_ptr.add_offsets(iw_raw + in_bc_base),
108 Some(ow_mask & in_bounds),
109 Some(zeros),
110 &[],
111 None,
112 None,
113 None,
114 false,
115 );
116 let val_left = T::load(
117 input_ptr.add_offsets(iw_left + in_bc_base),
118 Some(ow_mask & left_cond),
119 Some(zeros),
120 &[],
121 None,
122 None,
123 None,
124 false,
125 );
126 let val_right = T::load(
127 input_ptr.add_offsets(iw_right + in_bc_base),
128 Some(ow_mask & right_cond),
129 Some(zeros),
130 &[],
131 None,
132 None,
133 None,
134 false,
135 );
136
137 let result = T::where_(
138 left_cond,
139 val_left,
140 T::where_(right_cond, val_right, val_center),
141 );
142
143 let out_offsets = ow_range + out_bc_base;
144 T::store(
145 output_ptr.add_offsets(out_offsets),
146 result,
147 Some(ow_mask),
148 &[],
149 None,
150 None,
151 );
152}
153
154#[kernel]
156pub fn reflection_pad3d_backward<
157 T: Triton,
158 D: Num,
159 const PD1: i32,
160 const PD2: i32,
161 const PH1: i32,
162 const PH2: i32,
163 const PW1: i32,
164 const PW2: i32,
165 const BLOCK_OW: i32,
166>(
167 dy_ptr: T::Pointer<D>,
168 dx_ptr: T::Pointer<D>,
169 _B: i32,
170 C: i32,
171 Dv: i32,
172 H: i32,
173 W: i32,
174 OD: i32,
175 OH: i32,
176 OW: i32,
177) where
178 T::I32Tensor: Tensor<i32, 1>,
179 T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
180 T::BoolTensor: BitAnd<Output = T::BoolTensor>,
181 T::BoolTensor: BitOr<Output = T::BoolTensor>,
182 T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
183{
184 let pid = T::program_id(Axis::X);
185 let num_ow_tiles = T::cdiv(OW, BLOCK_OW);
186
187 let ow_tile = pid % num_ow_tiles;
188 let rest = pid / num_ow_tiles;
189 let oh = rest % OH;
190 let rest2 = rest / OH;
191 let od = rest2 % OD;
192 let bco = rest2 / OD;
193 let c = bco % C;
194 let b = bco / C;
195
196 let ow_start = ow_tile * BLOCK_OW;
197 let ow_range = T::arange(0, BLOCK_OW) + ow_start;
198 let ow_mask = ow_range.lt(OW);
199
200 let id_raw = od - PD1;
201 let id = if id_raw < 0 {
202 -id_raw
203 } else if id_raw >= Dv {
204 2 * (Dv - 1) - id_raw
205 } else {
206 id_raw
207 };
208
209 let ih_raw = oh - PH1;
210 let ih = if ih_raw < 0 {
211 -ih_raw
212 } else if ih_raw >= H {
213 2 * (H - 1) - ih_raw
214 } else {
215 ih_raw
216 };
217
218 let dy_bc_base = (((b * C + c) * OD + od) * OH + oh) * OW;
219 let dx_bc_base = ((b * C + c) * Dv + id) * H * W + ih * W;
220
221 let dy_offsets = ow_range + dy_bc_base;
222 let dy_tile = T::load(
223 dy_ptr.add_offsets(dy_offsets),
224 Some(ow_mask),
225 Some(T::zeros::<D>(&[BLOCK_OW])),
226 &[],
227 None,
228 None,
229 None,
230 false,
231 );
232
233 let iw_raw = ow_range - PW1;
234 let left_cond = iw_raw.lt(0);
235 let right_cond = iw_raw.ge(W);
236 let in_bounds = iw_raw.ge(0) & iw_raw.lt(W);
237
238 let iw_left = iw_raw * (-1);
239 let iw_right = iw_raw * (-1) + (2 * (W - 1));
240
241 T::atomic_add(
242 dx_ptr.add_offsets(iw_raw + dx_bc_base),
243 dy_tile,
244 Some(ow_mask & in_bounds),
245 None,
246 None,
247 );
248 T::atomic_add(
249 dx_ptr.add_offsets(iw_left + dx_bc_base),
250 dy_tile,
251 Some(ow_mask & left_cond),
252 None,
253 None,
254 );
255 T::atomic_add(
256 dx_ptr.add_offsets(iw_right + dx_bc_base),
257 dy_tile,
258 Some(ow_mask & right_cond),
259 None,
260 None,
261 );
262}
263
264pub struct ReflectionPad3dOp<'a, T: Num> {
265 pub forward: ReflectionPad3dForward<T>,
266 pub backward: ReflectionPad3dBackward<T>,
267 _marker: core::marker::PhantomData<&'a ()>,
268}