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_pad2d_forward<
33 T: Triton,
34 D: Num,
35 const PT: i32,
36 const PB: i32,
37 const PL: i32,
38 const PR: i32,
39 const BLOCK_OW: i32,
40>(
41 input_ptr: T::Pointer<D>,
42 output_ptr: T::Pointer<D>,
43 _B: i32,
44 C: i32,
45 H: i32,
46 W: i32,
47 OH: i32,
48 OW: i32,
49) where
50 T::I32Tensor: Tensor<i32, 1>,
51 T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
52 T::BoolTensor: BitAnd<Output = T::BoolTensor>,
53 T::BoolTensor: BitOr<Output = T::BoolTensor>,
54 T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
55{
56 let pid = T::program_id(Axis::X);
57 let num_ow_tiles = T::cdiv(OW, BLOCK_OW);
58
59 let ow_tile = pid % num_ow_tiles;
60 let rest = pid / num_ow_tiles;
61 let oh = rest % OH;
62 let bc = rest / OH;
63 let c = bc % C;
64 let b = bc / C;
65
66 let ow_start = ow_tile * BLOCK_OW;
67 let ow_range = T::arange(0, BLOCK_OW) + ow_start;
68 let ow_mask = ow_range.lt(OW);
69
70 let ih_raw = oh - PT;
72 let ih = if ih_raw < 0 {
73 -ih_raw
74 } else if ih_raw >= H {
75 2 * (H - 1) - ih_raw
76 } else {
77 ih_raw
78 };
79
80 let in_bc_base = (b * C + c) * H * W + ih * W;
81 let out_bc_base = ((b * C + c) * OH + oh) * OW;
82
83 let iw_raw = ow_range - PL;
84 let left_cond = iw_raw.lt(0);
85 let right_cond = iw_raw.ge(W);
86 let in_bounds = iw_raw.ge(0) & iw_raw.lt(W);
87
88 let iw_left = iw_raw * (-1);
89 let iw_right = iw_raw * (-1) + (2 * (W - 1));
90
91 let zeros = T::zeros::<D>(&[BLOCK_OW]);
92 let val_center = T::load(
93 input_ptr.add_offsets(iw_raw + in_bc_base),
94 Some(ow_mask & in_bounds),
95 Some(zeros),
96 &[],
97 None,
98 None,
99 None,
100 false,
101 );
102 let val_left = T::load(
103 input_ptr.add_offsets(iw_left + in_bc_base),
104 Some(ow_mask & left_cond),
105 Some(zeros),
106 &[],
107 None,
108 None,
109 None,
110 false,
111 );
112 let val_right = T::load(
113 input_ptr.add_offsets(iw_right + in_bc_base),
114 Some(ow_mask & right_cond),
115 Some(zeros),
116 &[],
117 None,
118 None,
119 None,
120 false,
121 );
122
123 let result = T::where_(
124 left_cond,
125 val_left,
126 T::where_(right_cond, val_right, val_center),
127 );
128
129 let out_offsets = ow_range + out_bc_base;
130 T::store(
131 output_ptr.add_offsets(out_offsets),
132 result,
133 Some(ow_mask),
134 &[],
135 None,
136 None,
137 );
138}
139
140#[kernel]
142pub fn reflection_pad2d_backward<
143 T: Triton,
144 D: Num,
145 const PT: i32,
146 const PB: i32,
147 const PL: i32,
148 const PR: i32,
149 const BLOCK_OW: i32,
150>(
151 dy_ptr: T::Pointer<D>,
152 dx_ptr: T::Pointer<D>,
153 _B: i32,
154 C: i32,
155 H: i32,
156 W: i32,
157 OH: i32,
158 OW: i32,
159) where
160 T::I32Tensor: Tensor<i32, 1>,
161 T::I32Tensor: Comparison<i32, BoolTensor = T::BoolTensor>,
162 T::BoolTensor: BitAnd<Output = T::BoolTensor>,
163 T::BoolTensor: BitOr<Output = T::BoolTensor>,
164 T::Pointer<D>: AddOffsets<i32, 1, T::I32Tensor, Output = T::Tensor<T::Pointer<D>>>,
165{
166 let pid = T::program_id(Axis::X);
167 let num_ow_tiles = T::cdiv(OW, BLOCK_OW);
168
169 let ow_tile = pid % num_ow_tiles;
170 let rest = pid / num_ow_tiles;
171 let oh = rest % OH;
172 let bc = rest / OH;
173 let c = bc % C;
174 let b = bc / C;
175
176 let ow_start = ow_tile * BLOCK_OW;
177 let ow_range = T::arange(0, BLOCK_OW) + ow_start;
178 let ow_mask = ow_range.lt(OW);
179
180 let ih_raw = oh - PT;
181 let ih = if ih_raw < 0 {
182 -ih_raw
183 } else if ih_raw >= H {
184 2 * (H - 1) - ih_raw
185 } else {
186 ih_raw
187 };
188
189 let dy_bc_base = ((b * C + c) * OH + oh) * OW;
190 let dx_bc_base = (b * C + c) * H * W + ih * W;
191
192 let dy_offsets = ow_range + dy_bc_base;
193 let dy_tile = T::load(
194 dy_ptr.add_offsets(dy_offsets),
195 Some(ow_mask),
196 Some(T::zeros::<D>(&[BLOCK_OW])),
197 &[],
198 None,
199 None,
200 None,
201 false,
202 );
203
204 let iw_raw = ow_range - PL;
205 let left_cond = iw_raw.lt(0);
206 let right_cond = iw_raw.ge(W);
207 let in_bounds = iw_raw.ge(0) & iw_raw.lt(W);
208
209 let iw_left = iw_raw * (-1);
210 let iw_right = iw_raw * (-1) + (2 * (W - 1));
211
212 T::atomic_add(
213 dx_ptr.add_offsets(iw_raw + dx_bc_base),
214 dy_tile,
215 Some(ow_mask & in_bounds),
216 None,
217 None,
218 );
219 T::atomic_add(
220 dx_ptr.add_offsets(iw_left + dx_bc_base),
221 dy_tile,
222 Some(ow_mask & left_cond),
223 None,
224 None,
225 );
226 T::atomic_add(
227 dx_ptr.add_offsets(iw_right + dx_bc_base),
228 dy_tile,
229 Some(ow_mask & right_cond),
230 None,
231 None,
232 );
233}
234
235pub struct ReflectionPad2dOp<'a, T: Num> {
236 pub forward: ReflectionPad2dForward<T>,
237 pub backward: ReflectionPad2dBackward<T>,
238 _marker: core::marker::PhantomData<&'a ()>,
239}