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