| 28 | |
| 29 | template<typename T> |
| 30 | void morph(Param<T> out, CParam<T> in, CParam<T> mask, bool isDilation) { |
| 31 | const int windLen = mask.dims[0]; |
| 32 | const int SeLength = (windLen <= 10 ? windLen : 0); |
| 33 | |
| 34 | auto morph = common::getKernel( |
| 35 | "arrayfire::cuda::morph", {{morph_cuh_src}}, |
| 36 | TemplateArgs(TemplateTypename<T>(), TemplateArg(isDilation), |
| 37 | TemplateArg(SeLength)), |
| 38 | {{DefineValue(MAX_MORPH_FILTER_LEN)}}); |
| 39 | |
| 40 | morph.copyToReadOnly(morph.getDevPtr("cFilter"), |
| 41 | reinterpret_cast<CUdeviceptr>(mask.ptr), |
| 42 | mask.dims[0] * mask.dims[1] * sizeof(T)); |
| 43 | |
| 44 | dim3 threads(kernel::THREADS_X, kernel::THREADS_Y); |
| 45 | |
| 46 | int blk_x = divup(in.dims[0], THREADS_X); |
| 47 | int blk_y = divup(in.dims[1], THREADS_Y); |
| 48 | // launch batch * blk_x blocks along x dimension |
| 49 | dim3 blocks(blk_x * in.dims[2], blk_y * in.dims[3]); |
| 50 | |
| 51 | // calculate shared memory size |
| 52 | int padding = (windLen % 2 == 0 ? (windLen - 1) : (2 * (windLen / 2))); |
| 53 | int shrdLen = |
| 54 | kernel::THREADS_X + padding + 1; // +1 for to avoid bank conflicts |
| 55 | int shrdSize = shrdLen * (kernel::THREADS_Y + padding) * sizeof(T); |
| 56 | |
| 57 | EnqueueArgs qArgs(blocks, threads, getActiveStream(), shrdSize); |
| 58 | morph(qArgs, out, in, blk_x, blk_y, windLen); |
| 59 | POST_LAUNCH_CHECK(); |
| 60 | } |
| 61 | |
| 62 | template<typename T> |
| 63 | void morph3d(Param<T> out, CParam<T> in, CParam<T> mask, bool isDilation) { |
nothing calls this directly
no test coverage detected