| 32 | } |
| 33 | |
| 34 | ErrorCode MultiInputDWConvExecution::onEncode(const std::vector<Tensor *> &inputs, const std::vector<Tensor *> &outputs) { |
| 35 | mUnits.clear(); |
| 36 | mUnits.resize(3); |
| 37 | |
| 38 | auto originLayout = TensorUtils::getDescribe(inputs[1])->dimensionFormat; |
| 39 | auto openclBackend = static_cast<OpenCLBackend *>(backend()); |
| 40 | auto runtime = openclBackend->getOpenCLRuntime(); |
| 41 | |
| 42 | auto inputShape = tensorShapeFormat(inputs[0]); |
| 43 | auto outputShape = tensorShapeFormat(outputs[0]); |
| 44 | const int batch = outputShape.at(0); |
| 45 | const int outputChannel = outputShape.at(3), inputChannel = inputShape.at(3); |
| 46 | const int inputHeight = inputShape.at(1), inputWidth = inputShape.at(2); |
| 47 | const int height = outputShape.at(1), width = outputShape.at(2); |
| 48 | const int kernelY = inputs[1]->length(2), kernelX = inputs[1]->length(3); |
| 49 | int kernelShape[2] = {kernelY, kernelX}; |
| 50 | |
| 51 | if (mPadMode == PadMode_SAME) { |
| 52 | int padNeededHeight = (height - 1) * mStrides[0] + (kernelY - 1) * mDilations[0] + 1 - inputHeight; |
| 53 | int padNeededWidth = (width - 1) * mStrides[1] + (kernelX - 1) * mDilations[1] + 1 - inputWidth; |
| 54 | mPaddings[0] = padNeededHeight; |
| 55 | mPaddings[1] = padNeededWidth; |
| 56 | } |
| 57 | |
| 58 | const int weightSize = inputs[1]->elementSize(); |
| 59 | auto bufferPool = openclBackend->getBufferPool(); |
| 60 | auto bufferPtr = bufferPool->alloc(weightSize * sizeof(float), false); |
| 61 | if (bufferPtr == nullptr) { |
| 62 | return OUT_OF_MEMORY; |
| 63 | } |
| 64 | |
| 65 | mFilter.reset(Tensor::createDevice<float>({1, UP_DIV(outputChannel, 4), 1, 4 * kernelY * kernelX})); |
| 66 | bool succ = openclBackend->onAcquireBuffer(mFilter.get(), Backend::DYNAMIC); |
| 67 | bufferPool->recycle(bufferPtr, false); |
| 68 | if (!succ) { |
| 69 | return OUT_OF_MEMORY; |
| 70 | } |
| 71 | openclBackend->onReleaseBuffer(mFilter.get(), Backend::DYNAMIC); |
| 72 | |
| 73 | // transform kernel from image2d (NHCW) to original form (maybe NCHW or NHWC) |
| 74 | { |
| 75 | std::string kernelName = ""; |
| 76 | if (originLayout == MNN_DATA_FORMAT_NCHW) { |
| 77 | kernelName = "image_to_nchw_buffer"; |
| 78 | } else if (originLayout == MNN_DATA_FORMAT_NHWC) { |
| 79 | kernelName = "image_to_nhwc_buffer"; |
| 80 | } |
| 81 | auto shape = tensorShapeFormat(inputs[1]); |
| 82 | std::vector<uint32_t> gws = {static_cast<uint32_t>(shape[2] * UP_DIV(shape[3], 4)), static_cast<uint32_t>(shape[0] * shape[1])}; |
| 83 | |
| 84 | auto kernelW = runtime->buildKernel("buffer_to_image", kernelName, {}, openclBackend->getPrecision(), inputs[1], inputs[1]); |
| 85 | auto kernel = kernelW->get(); |
| 86 | cl_int ret = CL_SUCCESS; |
| 87 | ret |= kernel.setArg(0, gws[0]); |
| 88 | ret |= kernel.setArg(1, gws[1]); |
| 89 | ret |= kernel.setArg(2, *bufferPtr); |
| 90 | ret |= kernel.setArg(3, shape[1]); |
| 91 | ret |= kernel.setArg(4, shape[2]); |
nothing calls this directly
no test coverage detected