IVGCVSW-6127 ConstTensorsAsInput: DepthwiseConvolution2d

!android-nn-driver:7418

 * Update Front-end and Tools.
 * Updated Serializer, Deserializer and unit tests to reflect this.
 * Updated TfLiteDelegate, TfLiteParser and OnnxParser.
 * Change NNDriver to new API.
 * Updated Ref.
 * Neon and Cl backend partially completed (Backend.cpp files).
 * Added dynamic or constant input EndToEnd tests.
 * Added ConstantTensorAsInputMemeberVariableRedirect Optimization.

Signed-off-by: Cathal Corbett <cathal.corbett@arm.com>
Change-Id: Ib18b6c10a093042e165e25237dc04a4c67ba82da
diff --git a/src/armnnSerializer/Serializer.cpp b/src/armnnSerializer/Serializer.cpp
index 3b9dfb0..99d1c2b 100644
--- a/src/armnnSerializer/Serializer.cpp
+++ b/src/armnnSerializer/Serializer.cpp
@@ -441,13 +441,10 @@
 
 void SerializerStrategy::SerializeDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
                                                               const armnn::DepthwiseConvolution2dDescriptor& descriptor,
-                                                              const std::vector<armnn::ConstTensor>& constants,
                                                               const char* name)
 {
     IgnoreUnused(name);
 
-    const armnn::ConstTensor& weights = constants[0];
-
     auto fbBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_DepthwiseConvolution2d);
     auto fbDescriptor = CreateDepthwiseConvolution2dDescriptor(m_flatBufferBuilder,
                                                                descriptor.m_PadLeft,
@@ -461,20 +458,9 @@
                                                                descriptor.m_BiasEnabled,
                                                                GetFlatBufferDataLayout(descriptor.m_DataLayout));
 
-    flatbuffers::Offset<serializer::ConstTensor> fbWeightsConstTensorInfo = CreateConstTensorInfo(weights);
-    flatbuffers::Offset<serializer::ConstTensor> fbBiasesConstTensorInfo;
-
-    if (constants.size() > 1)
-    {
-        const armnn::ConstTensor& biases = constants[1];
-        fbBiasesConstTensorInfo = CreateConstTensorInfo(biases);
-    }
-
     auto flatBufferLayer = CreateDepthwiseConvolution2dLayer(m_flatBufferBuilder,
                                                              fbBaseLayer,
-                                                             fbDescriptor,
-                                                             fbWeightsConstTensorInfo,
-                                                             fbBiasesConstTensorInfo);
+                                                             fbDescriptor);
 
     CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_DepthwiseConvolution2dLayer);
 }
@@ -2090,7 +2076,6 @@
                     static_cast<const armnn::DepthwiseConvolution2dDescriptor&>(descriptor);
             SerializeDepthwiseConvolution2dLayer(layer,
                                                  layerDescriptor,
-                                                 constants,
                                                  name);
             break;
         }
diff --git a/src/armnnSerializer/Serializer.hpp b/src/armnnSerializer/Serializer.hpp
index 98c1984..afde778 100644
--- a/src/armnnSerializer/Serializer.hpp
+++ b/src/armnnSerializer/Serializer.hpp
@@ -158,7 +158,6 @@
 
     void SerializeDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer,
                                               const armnn::DepthwiseConvolution2dDescriptor& descriptor,
-                                              const std::vector<armnn::ConstTensor>& constants,
                                               const char* name = nullptr);
 
     void SerializeDequantizeLayer(const armnn::IConnectableLayer* layer,
diff --git a/src/armnnSerializer/test/SerializerTestUtils.cpp b/src/armnnSerializer/test/SerializerTestUtils.cpp
index d0a8e2d..cf2cb15 100644
--- a/src/armnnSerializer/test/SerializerTestUtils.cpp
+++ b/src/armnnSerializer/test/SerializerTestUtils.cpp
@@ -54,8 +54,14 @@
         CHECK(
             GetDataTypeName(connectedInfo.GetDataType()) == GetDataTypeName(m_InputTensorInfos[i].GetDataType()));
 
-        CHECK(connectedInfo.GetQuantizationScale() == m_InputTensorInfos[i].GetQuantizationScale());
-        CHECK(connectedInfo.GetQuantizationOffset() == m_InputTensorInfos[i].GetQuantizationOffset());
+        // If weights and bias are connected to DepthwiseConvolution2d via Constant Layer we do not check.
+        // Constant Layer already disabled in SerializerTestUtils.hpp from entering function.
+        if (layer->GetType() == armnn::LayerType::DepthwiseConvolution2d &&
+            connectedOutput->GetOwningIConnectableLayer().GetType() != armnn::LayerType::Constant)
+        {
+            CHECK(connectedInfo.GetQuantizationScale() == m_InputTensorInfos[i].GetQuantizationScale());
+            CHECK(connectedInfo.GetQuantizationOffset() == m_InputTensorInfos[i].GetQuantizationOffset());
+        }
     }
 
     for (unsigned int i = 0; i < m_OutputTensorInfos.size(); i++)
diff --git a/src/armnnSerializer/test/SerializerTestUtils.hpp b/src/armnnSerializer/test/SerializerTestUtils.hpp
index ce4d2cc..ac15ced 100644
--- a/src/armnnSerializer/test/SerializerTestUtils.hpp
+++ b/src/armnnSerializer/test/SerializerTestUtils.hpp
@@ -128,6 +128,7 @@
         {
             case armnn::LayerType::Input: break;
             case armnn::LayerType::Output: break;
+            case armnn::LayerType::Constant: break;
             default:
             {
                 this->VerifyNameAndConnections(layer, name);
diff --git a/src/armnnSerializer/test/SerializerTests.cpp b/src/armnnSerializer/test/SerializerTests.cpp
index a765290..278715b 100644
--- a/src/armnnSerializer/test/SerializerTests.cpp
+++ b/src/armnnSerializer/test/SerializerTests.cpp
@@ -553,11 +553,8 @@
 
     armnn::INetworkPtr network = armnn::INetwork::Create();
     armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
-    armnn::IConnectableLayer* const depthwiseConvLayer =
-        network->AddDepthwiseConvolution2dLayer(descriptor,
-                                                weights,
-                                                armnn::Optional<armnn::ConstTensor>(biases),
-                                                layerName.c_str());
+    armnn::IConnectableLayer* const depthwiseConvLayer = network->AddDepthwiseConvolution2dLayer(descriptor,
+                                                                                                 layerName.c_str());
     armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
 
     inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
@@ -566,12 +563,20 @@
     inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
     depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
 
+    armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights);
+    weightsLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(1u));
+    weightsLayer->GetOutputSlot(0).SetTensorInfo(weights.GetInfo());
+
+     armnn::IConnectableLayer* const biasLayer = network->AddConstantLayer(biases);
+    biasLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(2u));
+    biasLayer->GetOutputSlot(0).SetTensorInfo(biases.GetInfo());
+
     armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
     CHECK(deserializedNetwork);
 
     const std::vector<armnn::ConstTensor>& constants {weights, biases};
     LayerVerifierBaseWithDescriptorAndConstants<armnn::DepthwiseConvolution2dDescriptor> verifier(
-            layerName, {inputInfo}, {outputInfo}, descriptor, constants);
+        layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor, constants);
     deserializedNetwork->ExecuteStrategy(verifier);
 }
 
@@ -610,11 +615,8 @@
 
     armnn::INetworkPtr network = armnn::INetwork::Create();
     armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
-    armnn::IConnectableLayer* const depthwiseConvLayer =
-        network->AddDepthwiseConvolution2dLayer(descriptor,
-                                                weights,
-                                                armnn::Optional<armnn::ConstTensor>(biases),
-                                                layerName.c_str());
+    armnn::IConnectableLayer* const depthwiseConvLayer = network->AddDepthwiseConvolution2dLayer(descriptor,
+                                                                                                 layerName.c_str());
     armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
 
     inputLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(0));
@@ -623,12 +625,75 @@
     inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
     depthwiseConvLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
 
+    armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights);
+    weightsLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(1u));
+    weightsLayer->GetOutputSlot(0).SetTensorInfo(weights.GetInfo());
+
+    armnn::IConnectableLayer* const biasLayer = network->AddConstantLayer(biases);
+    biasLayer->GetOutputSlot(0).Connect(depthwiseConvLayer->GetInputSlot(2u));
+    biasLayer->GetOutputSlot(0).SetTensorInfo(biases.GetInfo());
+
     armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
     CHECK(deserializedNetwork);
 
     const std::vector<armnn::ConstTensor>& constants {weights, biases};
     LayerVerifierBaseWithDescriptorAndConstants<armnn::DepthwiseConvolution2dDescriptor> verifier(
-            layerName, {inputInfo}, {outputInfo}, descriptor, constants);
+            layerName, {inputInfo, kernelInfo, biasInfo}, {outputInfo}, descriptor, constants);
+    deserializedNetwork->ExecuteStrategy(verifier);
+}
+
+TEST_CASE("SerializeDepthwiseConvolution2dWeightsAndBiasesAsConstantLayers")
+{
+    const std::string layerName("depthwiseConvolution2d");
+    const armnn::TensorInfo inputInfo ({ 1, 5, 5, 1 }, armnn::DataType::Float32);
+    const armnn::TensorInfo outputInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32);
+
+    const armnn::TensorInfo weightsInfo({ 1, 3, 3, 1 }, armnn::DataType::Float32, 0.0f, 0, true);
+    const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32, 0.0f, 0, true);
+
+    std::vector<float> weightsData = GenerateRandomData<float>(weightsInfo.GetNumElements());
+    armnn::ConstTensor weights(weightsInfo, weightsData);
+
+    std::vector<float> biasesData = GenerateRandomData<float>(biasesInfo.GetNumElements());
+    armnn::ConstTensor biases(biasesInfo, biasesData);
+
+    armnn::DepthwiseConvolution2dDescriptor descriptor;
+    descriptor.m_PadLeft     = 1;
+    descriptor.m_PadRight    = 1;
+    descriptor.m_PadTop      = 1;
+    descriptor.m_PadBottom   = 1;
+    descriptor.m_StrideX     = 2;
+    descriptor.m_StrideY     = 2;
+    descriptor.m_DilationX   = 2;
+    descriptor.m_DilationY   = 2;
+    descriptor.m_BiasEnabled = true;
+    descriptor.m_DataLayout  = armnn::DataLayout::NHWC;
+
+    armnn::INetworkPtr network = armnn::INetwork::Create();
+    armnn::IConnectableLayer* const inputLayer  = network->AddInputLayer(0);
+    armnn::IConnectableLayer* const weightsLayer = network->AddConstantLayer(weights, "Weights");
+    armnn::IConnectableLayer* const biasesLayer = network->AddConstantLayer(biases, "Biases");
+    armnn::IConnectableLayer* const convLayer   = network->AddDepthwiseConvolution2dLayer(descriptor,
+                                                                                          layerName.c_str());
+    armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
+
+    inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
+    weightsLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(1));
+    biasesLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(2));
+    convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+
+    inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
+    weightsLayer->GetOutputSlot(0).SetTensorInfo(weightsInfo);
+    biasesLayer->GetOutputSlot(0).SetTensorInfo(biasesInfo);
+    convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
+
+    armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
+    CHECK(deserializedNetwork);
+
+    const std::vector<armnn::ConstTensor>& constants {weights, biases};
+    LayerVerifierBaseWithDescriptorAndConstants<armnn::DepthwiseConvolution2dDescriptor> verifier(
+        layerName, {inputInfo, weightsInfo, biasesInfo}, {outputInfo}, descriptor, constants);
+
     deserializedNetwork->ExecuteStrategy(verifier);
 }