| 284 | |
| 285 | template <bool is_border_constant, typename ctype, typename mtype> |
| 286 | void WarpPerspectiveImpl::kern_resize(const KernParam<ctype, mtype>& kern_param) { |
| 287 | UNPACK_WARP_PERSPECTIVE_FWD_KERN_PARAM(kern_param); |
| 288 | MEGDNN_MARK_USED_VAR(N_SRC); |
| 289 | MEGDNN_MARK_USED_VAR(N_MAT); |
| 290 | MEGDNN_MARK_USED_VAR(midx_ptr); |
| 291 | MEGDNN_MARK_USED_VAR(bmode); |
| 292 | |
| 293 | rounding::RoundingConverter<ctype> output_converter; |
| 294 | auto bundle = get_bundle(OH, OW); |
| 295 | bundle.set(kern_param.workspace.raw_ptr); |
| 296 | int* tabsh0 = static_cast<int*>(bundle.get(0)); |
| 297 | int* tabsh1 = static_cast<int*>(bundle.get(1)); |
| 298 | int* tabsw0 = static_cast<int*>(bundle.get(2)); |
| 299 | int* tabsw1 = static_cast<int*>(bundle.get(3)); |
| 300 | float* tabrh = static_cast<float*>(bundle.get(4)); |
| 301 | float* tabrw = static_cast<float*>(bundle.get(5)); |
| 302 | float* cache0 = static_cast<float*>(bundle.get(6)); |
| 303 | float* cache1 = static_cast<float*>(bundle.get(7)); |
| 304 | |
| 305 | float bval = border_val; // filled in UNPACK_WARP_PERSPECTIVE_FWD_KERN_PARAM |
| 306 | |
| 307 | auto src = sptr; |
| 308 | auto mat = mptr; |
| 309 | auto dst = dptr; |
| 310 | |
| 311 | // | k_x 0 c_1 | |
| 312 | // mat = | 0 k_y c_2 | |
| 313 | // | 0 0 c_3 | |
| 314 | float kh = static_cast<float>(mat[4]) / mat[8]; // k_y / c_3 |
| 315 | float bh = static_cast<float>(mat[5]) / mat[8]; // c_2 / c_3 |
| 316 | float kw = static_cast<float>(mat[0]) / mat[8]; // k_x / c_3 |
| 317 | float bw = static_cast<float>(mat[2]) / mat[8]; // c_1 / c_3 |
| 318 | // build tab |
| 319 | for (size_t h = 0; h < OH; ++h) { |
| 320 | float f = static_cast<float>(h) * kh + bh; |
| 321 | tabsh0[h] = get_real_coord(std::floor(f) + 0, IH); |
| 322 | tabsh1[h] = get_real_coord(std::floor(f) + 1, IH); |
| 323 | tabrh[h] = f - std::floor(f); |
| 324 | } |
| 325 | for (size_t w = 0; w < OW; ++w) { |
| 326 | float f = static_cast<float>(w) * kw + bw; |
| 327 | tabsw0[w] = get_real_coord(std::floor(f) + 0, IW); |
| 328 | tabsw1[w] = get_real_coord(std::floor(f) + 1, IW); |
| 329 | tabrw[w] = f - std::floor(f); |
| 330 | } |
| 331 | // (1, 2) -> (0, 1) |
| 332 | auto calc_cache_backward = [&](size_t oh) { |
| 333 | std::swap(cache0, cache1); |
| 334 | // rebuild cache0 |
| 335 | size_t ih0 = tabsh0[oh]; |
| 336 | const ctype* psrc0 = src + ih0 * IW; |
| 337 | if (is_border_constant && ih0 >= IH) { |
| 338 | for (size_t ow = 0; ow < OW; ++ow) |
| 339 | cache0[ow] = bval; |
| 340 | } else { |
| 341 | for (size_t ow = 0; ow < OW; ++ow) { |
| 342 | size_t iw0 = tabsw0[ow], iw1 = tabsw1[ow]; |
| 343 | float v0 = (is_border_constant && iw0 >= IW) ? bval : psrc0[iw0]; |