| 152 | } |
| 153 | |
| 154 | static const Tensor* createHostPlanar(const Tensor* source) { |
| 155 | // check |
| 156 | auto bnType = MNN_FORWARD_CPU; |
| 157 | auto tensorBackend = TensorUtils::getDescribeOrigin(source)->getBackend(); |
| 158 | if (tensorBackend) { |
| 159 | bnType = tensorBackend->type(); |
| 160 | } |
| 161 | bool device = bnType != MNN_FORWARD_CPU; |
| 162 | bool chunky = TensorUtils::getDescribe(source)->dimensionFormat == MNN_DATA_FORMAT_NC4HW4; |
| 163 | |
| 164 | // no convert needed |
| 165 | if (!device && !chunky) { |
| 166 | return source; |
| 167 | } |
| 168 | |
| 169 | // convert |
| 170 | if (chunky) { |
| 171 | Tensor* result = source->createHostTensorFromDevice(source, false); |
| 172 | if (result->getDimensionType() == MNN::Tensor::TENSORFLOW) { |
| 173 | TensorUtils::getDescribe(result)->dimensionFormat = MNN_DATA_FORMAT_NHWC; |
| 174 | } else { |
| 175 | TensorUtils::getDescribe(result)->dimensionFormat = MNN_DATA_FORMAT_NCHW; |
| 176 | } |
| 177 | TensorUtils::setLinearLayout(result); |
| 178 | |
| 179 | if (device) { |
| 180 | void *host = ((Tensor *)source)->map(MNN::Tensor::MAP_TENSOR_READ, result->getDimensionType()); |
| 181 | if(host != nullptr) { |
| 182 | ::memcpy(result->buffer().host, host, result->size()); |
| 183 | } |
| 184 | ((Tensor *)source)->unmap(MNN::Tensor::MAP_TENSOR_READ, result->getDimensionType(), host); |
| 185 | } else { |
| 186 | Backend::Info info; |
| 187 | info.type = MNN_FORWARD_CPU; |
| 188 | std::shared_ptr<Runtime> runtime(MNNGetExtraRuntimeCreator(MNN_FORWARD_CPU)->onCreate(info)); |
| 189 | auto backend = runtime->onCreate(); |
| 190 | backend->onCopyBuffer(source, result); |
| 191 | delete backend; |
| 192 | } |
| 193 | return result; |
| 194 | } else { |
| 195 | return source->createHostTensorFromDevice(source, true); |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | template <typename T> |
| 200 | static void copyTensorToFloat(const Tensor* source, double* dest) { |
no test coverage detected