IVGCVSW-4931 Update NN Driver to support dynamic tensors

 * Change NN Driver m_Network to now have ShapeInferenceMethod::InferAndValidate
 * Implement dynamic tensor support for:
    - ArgMinMax layer
    - Pooling2d layer
    - Activation layer
 * Skip dynamic tensor tests for any HAL other than 1.3

Change-Id: Icf66c968e49cdd4822b8c79c5f18b3f9e97dc53f
Signed-off-by: Finn Williams <Finn.Williams@Arm.com>
Signed-off-by: Teresa Charlin <teresa.charlinreyes@arm.com>
diff --git a/Utils.cpp b/Utils.cpp
index 8a2812a..db1b6e6 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -80,7 +80,8 @@
 
 armnn::TensorInfo GetTensorInfoForOperand(const V1_0::Operand& operand)
 {
-    armnn::DataType type;
+    using namespace armnn;
+    DataType type;
 
     switch (operand.type)
     {
@@ -97,7 +98,30 @@
             throw UnsupportedOperand<V1_0::OperandType>(operand.type);
     }
 
-    armnn::TensorInfo ret(operand.dimensions.size(), operand.dimensions.data(), type);
+    TensorInfo ret;
+    if (operand.dimensions.size() == 0)
+    {
+        TensorShape tensorShape(Dimensionality::NotSpecified);
+        ret = TensorInfo(tensorShape, type);
+    }
+    else
+    {
+        bool dimensionsSpecificity[5] = { true, true, true, true, true };
+        int count = 0;
+        std::for_each(operand.dimensions.data(),
+                      operand.dimensions.data() +  operand.dimensions.size(),
+                      [&](const unsigned int val)
+                      {
+                          if (val == 0)
+                          {
+                              dimensionsSpecificity[count] = false;
+                          }
+                          count++;
+                      });
+
+        TensorShape tensorShape(operand.dimensions.size(), operand.dimensions.data(), dimensionsSpecificity);
+        ret = TensorInfo(tensorShape, type);
+    }
 
     ret.SetQuantizationScale(operand.scale);
     ret.SetQuantizationOffset(operand.zeroPoint);
@@ -143,7 +167,31 @@
             throw UnsupportedOperand<V1_2::OperandType>(operand.type);
     }
 
-    TensorInfo ret(operand.dimensions.size(), operand.dimensions.data(), type);
+    TensorInfo ret;
+    if (operand.dimensions.size() == 0)
+    {
+        TensorShape tensorShape(Dimensionality::NotSpecified);
+        ret = TensorInfo(tensorShape, type);
+    }
+    else
+    {
+        bool dimensionsSpecificity[5] = { true, true, true, true, true };
+        int count = 0;
+        std::for_each(operand.dimensions.data(),
+                      operand.dimensions.data() +  operand.dimensions.size(),
+                      [&](const unsigned int val)
+                      {
+                          if (val == 0)
+                          {
+                              dimensionsSpecificity[count] = false;
+                          }
+                          count++;
+                      });
+
+        TensorShape tensorShape(operand.dimensions.size(), operand.dimensions.data(), dimensionsSpecificity);
+        ret = TensorInfo(tensorShape, type);
+    }
+
     if (perChannel)
     {
         // ExtraParams is expected to be of type channelQuant
@@ -219,7 +267,29 @@
     }
     else
     {
-        ret = TensorInfo(operand.dimensions.size(), operand.dimensions.data(), type);
+        if (operand.dimensions.size() == 0)
+        {
+            TensorShape tensorShape(Dimensionality::NotSpecified);
+            ret = TensorInfo(tensorShape, type);
+        }
+        else
+        {
+            bool dimensionsSpecificity[5] = { true, true, true, true, true };
+            int count = 0;
+            std::for_each(operand.dimensions.data(),
+                          operand.dimensions.data() +  operand.dimensions.size(),
+                          [&](const unsigned int val)
+                          {
+                              if (val == 0)
+                              {
+                                  dimensionsSpecificity[count] = false;
+                              }
+                              count++;
+                          });
+
+            TensorShape tensorShape(operand.dimensions.size(), operand.dimensions.data(), dimensionsSpecificity);
+            ret = TensorInfo(tensorShape, type);
+        }
     }
 
     if (perChannel)
@@ -501,10 +571,22 @@
     return fileName;
 }
 
-bool IsDynamicTensor(const armnn::TensorInfo& outputInfo)
+bool IsDynamicTensor(const armnn::TensorInfo& tensorInfo)
 {
-    // Dynamic tensors have at least one 0-sized dimension
-    return outputInfo.GetNumElements() == 0u;
+    if (tensorInfo.GetShape().GetDimensionality() == armnn::Dimensionality::NotSpecified)
+    {
+        return true;
+    }
+    return !tensorInfo.GetShape().AreAllDimensionsSpecified();
+}
+
+bool AreDynamicTensorsSupported()
+{
+#if defined(ARMNN_ANDROID_NN_V1_3)
+    return true;
+#else
+    return false;
+#endif
 }
 
 std::string GetFileTimestamp()
@@ -568,7 +650,4 @@
 #endif
     }
 }
-
-
-
 } // namespace armnn_driver