IVGCVSW-3617 Add CL TensorHandleFactory

* Adds ClTensorHandleFactory
* Includes some refactoring of NeonTensorHandleFactory

Signed-off-by: Jan Eilers <jan.eilers@arm.com>
Change-Id: I9f0874b1945050267c5ece970e6d9b200ed8a865
diff --git a/src/backends/cl/CMakeLists.txt b/src/backends/cl/CMakeLists.txt
index 4d08ded..36db107 100644
--- a/src/backends/cl/CMakeLists.txt
+++ b/src/backends/cl/CMakeLists.txt
@@ -15,6 +15,8 @@
         ClLayerSupport.cpp
         ClLayerSupport.hpp
         ClTensorHandle.hpp
+        ClTensorHandleFactory.cpp
+        ClTensorHandleFactory.hpp
         ClWorkloadFactory.cpp
         ClWorkloadFactory.hpp
         OpenClTimer.cpp
diff --git a/src/backends/cl/ClBackend.cpp b/src/backends/cl/ClBackend.cpp
index 332ae1e..123d063 100644
--- a/src/backends/cl/ClBackend.cpp
+++ b/src/backends/cl/ClBackend.cpp
@@ -8,6 +8,7 @@
 #include "ClWorkloadFactory.hpp"
 #include "ClBackendContext.hpp"
 #include "ClLayerSupport.hpp"
+#include "ClTensorHandleFactory.hpp"
 
 #include <aclCommon/BaseMemoryManager.hpp>
 
@@ -57,6 +58,30 @@
         boost::polymorphic_pointer_downcast<ClMemoryManager>(memoryManager));
 }
 
+IBackendInternal::IWorkloadFactoryPtr ClBackend::CreateWorkloadFactory(
+    TensorHandleFactoryRegistry& registry) const
+{
+    auto memoryManager = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
+
+    registry.RegisterMemoryManager(memoryManager);
+
+    return std::make_unique<ClWorkloadFactory>(
+            boost::polymorphic_pointer_downcast<ClMemoryManager>(memoryManager));
+}
+
+std::vector<ITensorHandleFactory::FactoryId> ClBackend::GetHandleFactoryPreferences() const
+{
+    return std::vector<ITensorHandleFactory::FactoryId> {ClTensorHandleFactory::GetIdStatic()};
+}
+
+void ClBackend::RegisterTensorHandleFactories(TensorHandleFactoryRegistry& registry)
+{
+    auto mgr = std::make_shared<ClMemoryManager>(std::make_unique<arm_compute::CLBufferAllocator>());
+
+    registry.RegisterMemoryManager(mgr);
+    registry.RegisterFactory(std::make_unique<ClTensorHandleFactory>(mgr));
+}
+
 IBackendInternal::IBackendContextPtr
 ClBackend::CreateBackendContext(const IRuntime::CreationOptions& options) const
 {
diff --git a/src/backends/cl/ClBackend.hpp b/src/backends/cl/ClBackend.hpp
index 12e8d8e..f033a0c 100644
--- a/src/backends/cl/ClBackend.hpp
+++ b/src/backends/cl/ClBackend.hpp
@@ -23,6 +23,13 @@
     IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
         const IBackendInternal::IMemoryManagerSharedPtr& memoryManager = nullptr) const override;
 
+    IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
+        TensorHandleFactoryRegistry& registry) const override;
+
+    std::vector<ITensorHandleFactory::FactoryId> GetHandleFactoryPreferences() const override;
+
+    void RegisterTensorHandleFactories(TensorHandleFactoryRegistry& registry) override;
+
     IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override;
 
     IBackendInternal::Optimizations GetOptimizations() const override;
diff --git a/src/backends/cl/ClTensorHandleFactory.cpp b/src/backends/cl/ClTensorHandleFactory.cpp
new file mode 100644
index 0000000..47e36b3
--- /dev/null
+++ b/src/backends/cl/ClTensorHandleFactory.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+
+#include "ClTensorHandleFactory.hpp"
+#include "ClTensorHandle.hpp"
+
+#include <arm_compute/runtime/CL/CLTensor.h>
+#include <arm_compute/core/Coordinates.h>
+#include <arm_compute/runtime/CL/CLSubTensor.h>
+
+#include <boost/polymorphic_cast.hpp>
+
+
+namespace armnn
+{
+
+using FactoryId = ITensorHandleFactory::FactoryId;
+
+std::unique_ptr<ITensorHandle> ClTensorHandleFactory::CreateSubTensorHandle(ITensorHandle& parent,
+                                                                            const TensorShape& subTensorShape,
+                                                                            const unsigned int* subTensorOrigin) const
+{
+    arm_compute::Coordinates coords;
+    arm_compute::TensorShape shape = armcomputetensorutils::BuildArmComputeTensorShape(subTensorShape);
+
+    coords.set_num_dimensions(subTensorShape.GetNumDimensions());
+    for (unsigned int i = 0; i < subTensorShape.GetNumDimensions(); ++i)
+    {
+        // Arm compute indexes tensor coords in reverse order.
+        unsigned int revertedIndex = subTensorShape.GetNumDimensions() - i - 1;
+        coords.set(i, boost::numeric_cast<int>(subTensorOrigin[revertedIndex]));
+    }
+
+    const arm_compute::TensorShape parentShape = armcomputetensorutils::BuildArmComputeTensorShape(
+            parent.GetShape());
+    if (!::arm_compute::error_on_invalid_subtensor(__func__, __FILE__, __LINE__, parentShape, coords, shape))
+    {
+        return nullptr;
+    }
+
+    return std::make_unique<ClSubTensorHandle>(
+            boost::polymorphic_downcast<IClTensorHandle *>(&parent), shape, coords);
+}
+
+std::unique_ptr<ITensorHandle> ClTensorHandleFactory::CreateTensorHandle(const TensorInfo& tensorInfo) const
+{
+    std::unique_ptr<ClTensorHandle> tensorHandle = std::make_unique<ClTensorHandle>(tensorInfo);
+    tensorHandle->SetMemoryGroup(m_MemoryManager->GetInterLayerMemoryGroup());
+
+    return tensorHandle;
+}
+
+std::unique_ptr<ITensorHandle> ClTensorHandleFactory::CreateTensorHandle(const TensorInfo& tensorInfo,
+                                                                         DataLayout dataLayout) const
+{
+    std::unique_ptr<ClTensorHandle> tensorHandle = std::make_unique<ClTensorHandle>(tensorInfo, dataLayout);
+    tensorHandle->SetMemoryGroup(m_MemoryManager->GetInterLayerMemoryGroup());
+
+    return tensorHandle;
+}
+
+const FactoryId& ClTensorHandleFactory::GetIdStatic()
+{
+    static const FactoryId s_Id(ClTensorHandleFactoryId());
+    return s_Id;
+}
+
+const FactoryId ClTensorHandleFactory::GetId() const
+{
+    return GetIdStatic();
+}
+
+bool ClTensorHandleFactory::SupportsSubTensors() const
+{
+    return true;
+}
+
+MemorySourceFlags ClTensorHandleFactory::GetExportFlags() const
+{
+    return m_ExportFlags;
+}
+
+MemorySourceFlags ClTensorHandleFactory::GetImportFlags() const
+{
+    return m_ImportFlags;
+}
+
+} // namespace armnn
\ No newline at end of file
diff --git a/src/backends/cl/ClTensorHandleFactory.hpp b/src/backends/cl/ClTensorHandleFactory.hpp
new file mode 100644
index 0000000..9ae1edc
--- /dev/null
+++ b/src/backends/cl/ClTensorHandleFactory.hpp
@@ -0,0 +1,52 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <backendsCommon/ITensorHandleFactory.hpp>
+#include <aclCommon/BaseMemoryManager.hpp>
+#include <backendsCommon/IMemoryManager.hpp>
+#include <armnn/MemorySources.hpp>
+
+namespace armnn
+{
+
+constexpr const char* ClTensorHandleFactoryId() { return "Arm/Cl/TensorHandleFactory"; }
+
+class ClTensorHandleFactory : public ITensorHandleFactory {
+public:
+    static const FactoryId m_Id;
+
+    ClTensorHandleFactory(std::shared_ptr<ClMemoryManager> mgr)
+                          : m_MemoryManager(mgr),
+                            m_ImportFlags(static_cast<MemorySourceFlags>(MemorySource::Undefined)),
+                            m_ExportFlags(static_cast<MemorySourceFlags>(MemorySource::Undefined))
+        {}
+
+    std::unique_ptr<ITensorHandle> CreateSubTensorHandle(ITensorHandle& parent,
+                                                         const TensorShape& subTensorShape,
+                                                         const unsigned int* subTensorOrigin) const override;
+
+    std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo) const override;
+
+    std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo,
+                                                      DataLayout dataLayout) const override;
+
+    static const FactoryId& GetIdStatic();
+
+    const FactoryId GetId() const override;
+
+    bool SupportsSubTensors() const override;
+
+    MemorySourceFlags GetExportFlags() const override;
+
+    MemorySourceFlags GetImportFlags() const override;
+
+private:
+    mutable std::shared_ptr<ClMemoryManager> m_MemoryManager;
+    MemorySourceFlags m_ImportFlags;
+    MemorySourceFlags m_ExportFlags;
+};
+
+} // namespace armnn
\ No newline at end of file
diff --git a/src/backends/cl/backend.mk b/src/backends/cl/backend.mk
index 8c34e62..98da871 100644
--- a/src/backends/cl/backend.mk
+++ b/src/backends/cl/backend.mk
@@ -18,6 +18,7 @@
         ClBackendContext.cpp \
         ClContextControl.cpp \
         ClLayerSupport.cpp \
+        ClTensorHandleFactory.cpp \
         ClWorkloadFactory.cpp \
         OpenClTimer.cpp \
         workloads/ClActivationWorkload.cpp \
diff --git a/src/backends/neon/NeonBackend.cpp b/src/backends/neon/NeonBackend.cpp
index f86509c..5df231b 100644
--- a/src/backends/neon/NeonBackend.cpp
+++ b/src/backends/neon/NeonBackend.cpp
@@ -97,7 +97,7 @@
 
 std::vector<ITensorHandleFactory::FactoryId> NeonBackend::GetHandleFactoryPreferences() const
 {
-    return std::vector<ITensorHandleFactory::FactoryId>() = {"Arm/Neon/TensorHandleFactory"};
+    return std::vector<ITensorHandleFactory::FactoryId>() = {NeonTensorHandleFactory::GetIdStatic()};
 }
 
 void NeonBackend::RegisterTensorHandleFactories(class TensorHandleFactoryRegistry& registry)
@@ -106,7 +106,7 @@
                                                              BaseMemoryManager::MemoryAffinity::Offset);
 
     registry.RegisterMemoryManager(memoryManager);
-    registry.RegisterFactory(std::make_unique<NeonTensorHandleFactory>(memoryManager, "Arm/Neon/TensorHandleFactory"));
+    registry.RegisterFactory(std::make_unique<NeonTensorHandleFactory>(memoryManager));
 }
 
 } // namespace armnn
diff --git a/src/backends/neon/NeonTensorHandleFactory.cpp b/src/backends/neon/NeonTensorHandleFactory.cpp
index ef34234..aff594c 100644
--- a/src/backends/neon/NeonTensorHandleFactory.cpp
+++ b/src/backends/neon/NeonTensorHandleFactory.cpp
@@ -11,18 +11,18 @@
 namespace armnn
 {
 
-using FactoryId = std::string;
+using FactoryId = ITensorHandleFactory::FactoryId;
 
 std::unique_ptr<ITensorHandle> NeonTensorHandleFactory::CreateSubTensorHandle(ITensorHandle& parent,
-                                                                              TensorShape const& subTensorShape,
-                                                                              unsigned int const* subTensorOrigin)
+                                                                              const TensorShape& subTensorShape,
+                                                                              const unsigned int* subTensorOrigin)
                                                                               const
 {
     const arm_compute::TensorShape shape = armcomputetensorutils::BuildArmComputeTensorShape(subTensorShape);
 
     arm_compute::Coordinates coords;
     coords.set_num_dimensions(subTensorShape.GetNumDimensions());
-    for (unsigned int i = 0; i < subTensorShape.GetNumDimensions(); i++)
+    for (unsigned int i = 0; i < subTensorShape.GetNumDimensions(); ++i)
     {
         // Arm compute indexes tensor coords in reverse order.
         unsigned int revertedIndex = subTensorShape.GetNumDimensions() - i - 1;
@@ -56,9 +56,15 @@
     return tensorHandle;
 }
 
+const FactoryId& NeonTensorHandleFactory::GetIdStatic()
+{
+    static const FactoryId s_Id(NeonTensorHandleFactoryId());
+    return s_Id;
+}
+
 const FactoryId NeonTensorHandleFactory::GetId() const
 {
-    return m_Id;
+    return GetIdStatic();
 }
 
 bool NeonTensorHandleFactory::SupportsSubTensors() const
diff --git a/src/backends/neon/NeonTensorHandleFactory.hpp b/src/backends/neon/NeonTensorHandleFactory.hpp
index a2e46e2..c401e0e 100644
--- a/src/backends/neon/NeonTensorHandleFactory.hpp
+++ b/src/backends/neon/NeonTensorHandleFactory.hpp
@@ -11,23 +11,28 @@
 namespace armnn
 {
 
+constexpr const char* NeonTensorHandleFactoryId() { return "Arm/Neon/TensorHandleFactory"; }
+
 class NeonTensorHandleFactory : public ITensorHandleFactory
 {
 public:
-    NeonTensorHandleFactory(std::weak_ptr<NeonMemoryManager> mgr, ITensorHandleFactory::FactoryId id)
-        : m_Id(id)
-        , m_MemoryManager(mgr)
+    NeonTensorHandleFactory(std::weak_ptr<NeonMemoryManager> mgr)
+                            : m_MemoryManager(mgr),
+                              m_ImportFlags(static_cast<MemorySourceFlags>(MemorySource::Undefined)),
+                              m_ExportFlags(static_cast<MemorySourceFlags>(MemorySource::Undefined))
     {}
 
     std::unique_ptr<ITensorHandle> CreateSubTensorHandle(ITensorHandle& parent,
-                                                         TensorShape const& subTensorShape,
-                                                         unsigned int const* subTensorOrigin) const override;
+                                                         const TensorShape& subTensorShape,
+                                                         const unsigned int* subTensorOrigin) const override;
 
     std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo) const override;
 
     std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo,
                                                       DataLayout dataLayout) const override;
 
+    static const FactoryId& GetIdStatic();
+
     const FactoryId GetId() const override;
 
     bool SupportsSubTensors() const override;
@@ -37,10 +42,9 @@
     MemorySourceFlags GetImportFlags() const override;
 
 private:
-    FactoryId m_Id = "Arm/Neon/TensorHandleFactory";
+    mutable std::shared_ptr<NeonMemoryManager> m_MemoryManager;
     MemorySourceFlags m_ImportFlags;
     MemorySourceFlags m_ExportFlags;
-    mutable std::shared_ptr<NeonMemoryManager> m_MemoryManager;
 };
 
 } // namespace armnn