// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // // Copyright (C) 2018, Intel Corporation, all rights reserved. // Third party copyrights are property of their respective owners. #include "precomp.hpp" #include #include "op_vkcom.hpp" namespace cv { namespace dnn { #ifdef HAVE_VULKAN void copyToTensor(vkcom::Tensor &dst, const Mat &src) { CV_Assert(src.isContinuous() && src.type() == CV_32F); std::vector mat_shape = shape(src); dst.reshape((const char*)src.data, mat_shape); } void copyToMat(Mat &dst, vkcom::Tensor &src) { CV_Assert(dst.type() == CV_32F); std::vector shape = src.getShape(); void *data = src.map(); Mat tmp(shape, CV_32F, data); tmp.copyTo(dst); src.unMap(); } vkcom::Tensor VkComTensor(const Ptr& ptr) { CV_Assert(!ptr.empty()); return ptr.dynamicCast()->getTensor(); } void setDirty(std::vector >& ptrs) { for (const Ptr& ptr : ptrs) { ptr.dynamicCast()->setDeviceDirty(); } } std::vector VkComTensors(const std::vector >& ptrs) { std::vector vec; vec.reserve(ptrs.size()); for (const Ptr& ptr : ptrs) { vec.push_back(VkComTensor(ptr)); } return vec; } VkComBackendNode::VkComBackendNode(const std::vector >& inputsWrapper, const std::shared_ptr& op, const std::vector >& blobsWrapper) : BackendNode(DNN_BACKEND_VKCOM) { operation = op; inputsWrapper_ = inputsWrapper; ins = VkComTensors(inputsWrapper_); if (!blobsWrapper.empty()) { blobs = VkComTensors(blobsWrapper); } } bool VkComBackendNode::forward(std::vector& outs) { for (int i = 0, n = inputsWrapper_.size(); i < n; ++i) { inputsWrapper_[i].dynamicCast()->copyToDevice(); } return operation->forward(ins, blobs, outs); } VkComBackendWrapper::VkComBackendWrapper(Mat& m) : BackendWrapper(DNN_BACKEND_VKCOM, DNN_TARGET_VULKAN) { copyToTensor(tensor, m); host = &m; hostDirty = false; deviceDirty = false; } VkComBackendWrapper::VkComBackendWrapper(const Ptr& baseBuffer, Mat& m) : BackendWrapper(DNN_BACKEND_VKCOM, DNN_TARGET_VULKAN) { Ptr base = baseBuffer.dynamicCast(); CV_Assert(!base.empty()); host = &m; tensor = base->tensor; CV_Assert(tensor.count() >= m.total()); tensor.reshape(0, shape(m)); hostDirty = false; deviceDirty = false; } void VkComBackendWrapper::copyToHost() { if (deviceDirty) copyToMat(*host, tensor); } void VkComBackendWrapper::setHostDirty() { hostDirty = true; }; void VkComBackendWrapper::setDeviceDirty() { deviceDirty = true; }; void VkComBackendWrapper::copyToDevice() { if (hostDirty) { copyToTensor(tensor, *host); hostDirty = false; } } vkcom::Tensor VkComBackendWrapper::getTensor() { return tensor; } #endif void forwardVkCom(std::vector > &outputs, const Ptr& node) { #ifdef HAVE_VULKAN CV_Assert(!node.empty()); Ptr node_ = node.dynamicCast(); std::vector outs = VkComTensors(outputs); node_->forward(outs); setDirty(outputs); #endif } bool haveVulkan() { #ifdef HAVE_VULKAN return vkcom::isAvailable(); #else return false; #endif // HAVE_VULKAN } } // namespace dnn } // namespace cv