| 28 | |
| 29 | template<typename T, typename accType> |
| 30 | void convSep(Param out, const Param signal, const Param filter, |
| 31 | const int conv_dim, const bool expand) { |
| 32 | if (!(conv_dim == 0 || conv_dim == 1)) { |
| 33 | AF_ERROR( |
| 34 | "Separable convolution accepts only 0 or 1 as convolution " |
| 35 | "dimension", |
| 36 | AF_ERR_NOT_SUPPORTED); |
| 37 | } |
| 38 | constexpr int THREADS_X = 16; |
| 39 | constexpr int THREADS_Y = 16; |
| 40 | constexpr bool IsComplex = |
| 41 | std::is_same<T, cfloat>::value || std::is_same<T, cdouble>::value; |
| 42 | |
| 43 | const int fLen = filter.info.dims[0] * filter.info.dims[1]; |
| 44 | const size_t C0_SIZE = (THREADS_X + 2 * (fLen - 1)) * THREADS_Y; |
| 45 | const size_t C1_SIZE = (THREADS_Y + 2 * (fLen - 1)) * THREADS_X; |
| 46 | size_t locSize = (conv_dim == 0 ? C0_SIZE : C1_SIZE); |
| 47 | |
| 48 | std::array<TemplateArg, 5> tmpltArgs = { |
| 49 | TemplateTypename<T>(), TemplateTypename<accType>(), |
| 50 | TemplateArg(conv_dim), TemplateArg(expand), |
| 51 | TemplateArg(fLen), |
| 52 | }; |
| 53 | std::array<std::string, 11> compileOpts = { |
| 54 | DefineKeyValue(T, dtype_traits<T>::getName()), |
| 55 | DefineKeyValue(Ti, dtype_traits<T>::getName()), |
| 56 | DefineKeyValue(To, dtype_traits<accType>::getName()), |
| 57 | DefineKeyValue(accType, dtype_traits<accType>::getName()), |
| 58 | DefineKeyValue(CONV_DIM, conv_dim), |
| 59 | DefineKeyValue(EXPAND, (expand ? 1 : 0)), |
| 60 | DefineKeyValue(FLEN, fLen), |
| 61 | DefineKeyFromStr(binOpName<af_mul_t>()), |
| 62 | DefineKeyValue(IS_CPLX, (IsComplex ? 1 : 0)), |
| 63 | DefineKeyValue(LOCAL_MEM_SIZE, locSize), |
| 64 | getTypeBuildDefinition<T>()}; |
| 65 | |
| 66 | auto conv = |
| 67 | common::getKernel("convolve", {{ops_cl_src, convolve_separable_cl_src}}, |
| 68 | tmpltArgs, compileOpts); |
| 69 | |
| 70 | cl::NDRange local(THREADS_X, THREADS_Y); |
| 71 | |
| 72 | int blk_x = divup(out.info.dims[0], THREADS_X); |
| 73 | int blk_y = divup(out.info.dims[1], THREADS_Y); |
| 74 | |
| 75 | cl::NDRange global(blk_x * signal.info.dims[2] * THREADS_X, |
| 76 | blk_y * signal.info.dims[3] * THREADS_Y); |
| 77 | |
| 78 | cl::Buffer *mBuff = bufferAlloc(fLen * sizeof(accType)); |
| 79 | // FIX ME: if the filter array is strided, direct might cause issues |
| 80 | getQueue().enqueueCopyBuffer(*filter.data, *mBuff, 0, 0, |
| 81 | fLen * sizeof(accType)); |
| 82 | |
| 83 | conv(cl::EnqueueArgs(getQueue(), global, local), *out.data, out.info, |
| 84 | *signal.data, signal.info, *mBuff, blk_x, blk_y); |
| 85 | bufferFree(mBuff); |
| 86 | } |
| 87 |
nothing calls this directly
no test coverage detected