IVGCVSW-6510 Serialization + Deserialization implementation

Subtask of story: IVGCVSW-6164 Add a Pooling3d FrontEnd and Ref Implementation

* Add serialization support
* Add deserialization support
* Add corresponding unit tests

Change-Id: I7cce5421f0a9b7c47a03524e733f3315131ba125
Signed-off-by: Tamas Nyiri <tamas.nyiri@arm.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3653740..4ea40de 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -821,6 +821,7 @@
             src/armnnDeserializer/test/DeserializePad.cpp
             src/armnnDeserializer/test/DeserializePermute.cpp
             src/armnnDeserializer/test/DeserializePooling2d.cpp
+            src/armnnDeserializer/test/DeserializePooling3d.cpp
             src/armnnDeserializer/test/DeserializeRank.cpp
             src/armnnDeserializer/test/DeserializeReduceSum.cpp
             src/armnnDeserializer/test/DeserializeReshape.cpp
diff --git a/docs/05_02_deserializer_serializer.dox b/docs/05_02_deserializer_serializer.dox
index 5d4dc43..84324d8 100644
--- a/docs/05_02_deserializer_serializer.dox
+++ b/docs/05_02_deserializer_serializer.dox
@@ -57,6 +57,7 @@
 - Pad (Constant, Symmetric, Reflect)
 - Permute
 - Pooling2d
+- Pooling3d
 - Prelu
 - QLstm
 - Quantize
diff --git a/src/armnn/SerializeLayerParameters.cpp b/src/armnn/SerializeLayerParameters.cpp
index c60d4fa..d7f3803 100644
--- a/src/armnn/SerializeLayerParameters.cpp
+++ b/src/armnn/SerializeLayerParameters.cpp
@@ -121,7 +121,7 @@
     {
         std::stringstream ss;
         ss << "(" << desc.m_DilationX << "," << desc.m_DilationY << "," << desc.m_DilationZ << ")";
-        fn("Dilation(X,Y)", ss.str());
+        fn("Dilation(X,Y,Z)", ss.str());
     }
 
     fn("BiasEnabled",(desc.m_BiasEnabled ? "true" : "false"));
@@ -331,6 +331,35 @@
     fn("DataLayout", GetDataLayoutName(desc.m_DataLayout));
 }
 
+void StringifyLayerParameters<Pooling3dDescriptor>::Serialize(ParameterStringifyFunction& fn,
+                                                              const Pooling3dDescriptor& desc)
+{
+    fn("Type", GetPoolingAlgorithmAsCString(desc.m_PoolType));
+    {
+        std::stringstream ss;
+        ss << "(" << desc.m_PadTop    << "," << desc.m_PadLeft
+           << "," << desc.m_PadBottom << "," << desc.m_PadRight
+           << "," << desc.m_PadFront  << "," << desc.m_PadBack << ")";
+        fn("Padding(T,L,B,R,F,B)", ss.str());
+    }
+
+    {
+        std::stringstream ss;
+        ss << "(" << desc.m_PoolWidth    << "," << desc.m_PoolHeight << "," << desc.m_PoolDepth << ")";
+        fn("(Width,Height,Depth)", ss.str());
+    }
+
+    {
+        std::stringstream ss;
+        ss << "(" << desc.m_StrideX <<  "," << desc.m_StrideY << "," << desc.m_StrideZ << ")";
+        fn("Stride(X,Y,Z)", ss.str());
+    }
+
+    fn("OutputShapeRounding", GetOutputShapeRoundingAsCString(desc.m_OutputShapeRounding));
+    fn("PaddingMethod", GetPaddingMethodAsCString(desc.m_PaddingMethod));
+    fn("DataLayout", GetDataLayoutName(desc.m_DataLayout));
+}
+
 void StringifyLayerParameters<PermuteDescriptor>::Serialize(ParameterStringifyFunction& fn,
                                                             const PermuteDescriptor& desc)
 {
diff --git a/src/armnn/SerializeLayerParameters.hpp b/src/armnn/SerializeLayerParameters.hpp
index 5c1e6f3..d2c7d76 100644
--- a/src/armnn/SerializeLayerParameters.hpp
+++ b/src/armnn/SerializeLayerParameters.hpp
@@ -124,6 +124,11 @@
     static void Serialize(ParameterStringifyFunction& fn, const Pooling2dDescriptor& desc);
 };
 
+template <> struct StringifyLayerParameters<Pooling3dDescriptor>
+{
+    static void Serialize(ParameterStringifyFunction& fn, const Pooling3dDescriptor& desc);
+};
+
 template <> struct StringifyLayerParameters<PreCompiledDescriptor>
 {
     static void Serialize(ParameterStringifyFunction& fn, const PreCompiledDescriptor& desc);
diff --git a/src/armnnDeserializer/Deserializer.cpp b/src/armnnDeserializer/Deserializer.cpp
index 8b1e9b9..a5114ec 100644
--- a/src/armnnDeserializer/Deserializer.cpp
+++ b/src/armnnDeserializer/Deserializer.cpp
@@ -249,6 +249,7 @@
     m_ParserFunctions[Layer_PadLayer]                    = &DeserializerImpl::ParsePad;
     m_ParserFunctions[Layer_PermuteLayer]                = &DeserializerImpl::ParsePermute;
     m_ParserFunctions[Layer_Pooling2dLayer]              = &DeserializerImpl::ParsePooling2d;
+    m_ParserFunctions[Layer_Pooling3dLayer]              = &DeserializerImpl::ParsePooling3d;
     m_ParserFunctions[Layer_PreluLayer]                  = &DeserializerImpl::ParsePrelu;
     m_ParserFunctions[Layer_QLstmLayer]                  = &DeserializerImpl::ParseQLstm;
     m_ParserFunctions[Layer_QuantizeLayer]               = &DeserializerImpl::ParseQuantize;
@@ -365,6 +366,8 @@
             return graphPtr->layers()->Get(layerIndex)->layer_as_PermuteLayer()->base();
         case Layer::Layer_Pooling2dLayer:
             return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling2dLayer()->base();
+        case Layer::Layer_Pooling3dLayer:
+            return graphPtr->layers()->Get(layerIndex)->layer_as_Pooling3dLayer()->base();
         case Layer::Layer_PreluLayer:
             return graphPtr->layers()->Get(layerIndex)->layer_as_PreluLayer()->base();
         case Layer::Layer_QLstmLayer:
@@ -2130,7 +2133,7 @@
     RegisterOutputSlots(graph, layerIndex, layer);
 }
 
-armnn::Pooling2dDescriptor IDeserializer::DeserializerImpl::GetPoolingDescriptor(PoolingDescriptor pooling2dDesc,
+armnn::Pooling2dDescriptor IDeserializer::DeserializerImpl::GetPooling2dDescriptor(Pooling2dDescriptor pooling2dDesc,
                                                               unsigned int layerIndex)
 {
     IgnoreUnused(layerIndex);
@@ -2225,7 +2228,104 @@
     return desc;
 }
 
+armnn::Pooling3dDescriptor IDeserializer::DeserializerImpl::GetPooling3dDescriptor(Pooling3dDescriptor pooling3dDesc,
+                                                              unsigned int layerIndex)
+{
+    IgnoreUnused(layerIndex);
+    armnn::Pooling3dDescriptor desc;
 
+    switch (pooling3dDesc->poolType())
+    {
+        case PoolingAlgorithm_Average:
+        {
+            desc.m_PoolType = armnn::PoolingAlgorithm::Average;
+            break;
+        }
+        case PoolingAlgorithm_Max:
+        {
+            desc.m_PoolType = armnn::PoolingAlgorithm::Max;
+            break;
+        }
+        case PoolingAlgorithm_L2:
+        {
+            desc.m_PoolType = armnn::PoolingAlgorithm::L2;
+            break;
+        }
+        default:
+        {
+            ARMNN_ASSERT_MSG(false, "Unsupported pooling algorithm");
+        }
+    }
+
+    switch (pooling3dDesc->outputShapeRounding())
+    {
+        case OutputShapeRounding_Floor:
+        {
+            desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
+            break;
+        }
+        case OutputShapeRounding_Ceiling:
+        {
+            desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Ceiling;
+            break;
+        }
+        default:
+        {
+            ARMNN_ASSERT_MSG(false, "Unsupported output shape rounding");
+        }
+    }
+
+    switch (pooling3dDesc->paddingMethod())
+    {
+        case PaddingMethod_Exclude:
+        {
+            desc.m_PaddingMethod = armnn::PaddingMethod::Exclude;
+            break;
+        }
+        case PaddingMethod_IgnoreValue:
+        {
+            desc.m_PaddingMethod = armnn::PaddingMethod::IgnoreValue;
+            break;
+        }
+        default:
+        {
+            ARMNN_ASSERT_MSG(false, "Unsupported padding method");
+        }
+    }
+
+    switch (pooling3dDesc->dataLayout())
+    {
+        case DataLayout_NCDHW:
+        {
+            desc.m_DataLayout = armnn::DataLayout::NCDHW;
+            break;
+        }
+        case DataLayout_NDHWC:
+        {
+            desc.m_DataLayout = armnn::DataLayout::NDHWC;
+            break;
+        }
+        default:
+        {
+            ARMNN_ASSERT_MSG(false, "Unsupported data layout");
+        }
+    }
+
+    desc.m_PadRight   = pooling3dDesc->padRight();
+    desc.m_PadLeft    = pooling3dDesc->padLeft();
+    desc.m_PadBottom  = pooling3dDesc->padBottom();
+    desc.m_PadTop     = pooling3dDesc->padTop();
+    desc.m_PadFront   = pooling3dDesc->padFront();
+    desc.m_PadBack    = pooling3dDesc->padBack();
+    desc.m_StrideX    = pooling3dDesc->strideX();
+    desc.m_StrideY    = pooling3dDesc->strideY();
+    desc.m_StrideZ    = pooling3dDesc->strideZ();
+    desc.m_PoolWidth  = pooling3dDesc->poolWidth();
+    desc.m_PoolHeight = pooling3dDesc->poolHeight();
+    desc.m_PoolDepth  = pooling3dDesc->poolDepth();
+
+    return desc;
+}
 
 void IDeserializer::DeserializerImpl::ParsePooling2d(GraphPtr graph, unsigned int layerIndex)
 {
@@ -2239,7 +2339,7 @@
     CHECK_VALID_SIZE(outputs.size(), 1);
     auto outputInfo = ToTensorInfo(outputs[0]);
 
-    auto pooling2dDescriptor = GetPoolingDescriptor(pooling2dDes, layerIndex);
+    auto pooling2dDescriptor = GetPooling2dDescriptor(pooling2dDes, layerIndex);
     auto layerName = GetLayerName(graph, layerIndex);
     IConnectableLayer* layer = m_Network->AddPooling2dLayer(pooling2dDescriptor, layerName.c_str());
     layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
@@ -2248,6 +2348,27 @@
     RegisterOutputSlots(graph, layerIndex, layer);
 }
 
+void IDeserializer::DeserializerImpl::ParsePooling3d(GraphPtr graph, unsigned int layerIndex)
+{
+    CHECK_LAYERS(graph, 0, layerIndex);
+
+    auto pooling3dDes = graph->layers()->Get(layerIndex)->layer_as_Pooling3dLayer()->descriptor();
+    auto inputs = GetInputs(graph, layerIndex);
+    CHECK_VALID_SIZE(inputs.size(), 1);
+
+    auto outputs = GetOutputs(graph, layerIndex);
+    CHECK_VALID_SIZE(outputs.size(), 1);
+    auto outputInfo = ToTensorInfo(outputs[0]);
+
+    auto pooling3dDescriptor = GetPooling3dDescriptor(pooling3dDes, layerIndex);
+    auto layerName = GetLayerName(graph, layerIndex);
+    IConnectableLayer* layer = m_Network->AddPooling3dLayer(pooling3dDescriptor, layerName.c_str());
+    layer->GetOutputSlot(0).SetTensorInfo(outputInfo);
+
+    RegisterInputSlots(graph, layerIndex, layer);
+    RegisterOutputSlots(graph, layerIndex, layer);
+}
+
 void IDeserializer::DeserializerImpl::ParseQuantize(GraphPtr graph, unsigned int layerIndex)
 {
     CHECK_LAYERS(graph, 0, layerIndex);
diff --git a/src/armnnDeserializer/Deserializer.hpp b/src/armnnDeserializer/Deserializer.hpp
index d2291c0..8de492e 100644
--- a/src/armnnDeserializer/Deserializer.hpp
+++ b/src/armnnDeserializer/Deserializer.hpp
@@ -18,7 +18,8 @@
 using ConstTensorRawPtr = const armnnSerializer::ConstTensor *;
 using GraphPtr = const armnnSerializer::SerializedGraph *;
 using TensorRawPtr = const armnnSerializer::TensorInfo *;
-using PoolingDescriptor = const armnnSerializer::Pooling2dDescriptor *;
+using Pooling2dDescriptor = const armnnSerializer::Pooling2dDescriptor *;
+using Pooling3dDescriptor = const armnnSerializer::Pooling3dDescriptor *;
 using NormalizationDescriptorPtr = const armnnSerializer::NormalizationDescriptor *;
 using LstmDescriptorPtr = const armnnSerializer::LstmDescriptor *;
 using LstmInputParamsPtr = const armnnSerializer::LstmInputParams *;
@@ -60,7 +61,9 @@
     static LayerBaseRawPtr GetBaseLayer(const GraphPtr& graphPtr, unsigned int layerIndex);
     static int32_t GetBindingLayerInfo(const GraphPtr& graphPtr, unsigned int layerIndex);
     static std::string GetLayerName(const GraphPtr& graph, unsigned int index);
-    static armnn::Pooling2dDescriptor GetPoolingDescriptor(PoolingDescriptor pooling2dDescriptor,
+    static armnn::Pooling2dDescriptor GetPooling2dDescriptor(Pooling2dDescriptor pooling2dDescriptor,
+                                                           unsigned int layerIndex);
+    static armnn::Pooling3dDescriptor GetPooling3dDescriptor(Pooling3dDescriptor pooling3dDescriptor,
                                                            unsigned int layerIndex);
     static armnn::NormalizationDescriptor GetNormalizationDescriptor(
         NormalizationDescriptorPtr normalizationDescriptor, unsigned int layerIndex);
@@ -121,6 +124,7 @@
     void ParsePad(GraphPtr graph, unsigned int layerIndex);
     void ParsePermute(GraphPtr graph, unsigned int layerIndex);
     void ParsePooling2d(GraphPtr graph, unsigned int layerIndex);
+    void ParsePooling3d(GraphPtr graph, unsigned int layerIndex);
     void ParsePrelu(GraphPtr graph, unsigned int layerIndex);
     void ParseQLstm(GraphPtr graph, unsigned int layerIndex);
     void ParseQuantize(GraphPtr graph, unsigned int layerIndex);
diff --git a/src/armnnDeserializer/test/DeserializePooling3d.cpp b/src/armnnDeserializer/test/DeserializePooling3d.cpp
new file mode 100644
index 0000000..62fdc5c
--- /dev/null
+++ b/src/armnnDeserializer/test/DeserializePooling3d.cpp
@@ -0,0 +1,173 @@
+//
+// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ParserFlatbuffersSerializeFixture.hpp"
+#include <armnnDeserializer/IDeserializer.hpp>
+
+#include <string>
+
+TEST_SUITE("Deserializer_Pooling3d")
+{
+struct Pooling3dFixture : public ParserFlatbuffersSerializeFixture
+{
+    explicit Pooling3dFixture(const std::string &inputShape,
+                              const std::string &outputShape,
+                              const std::string &dataType,
+                              const std::string &dataLayout,
+                              const std::string &poolingAlgorithm)
+    {
+        m_JsonString = R"(
+    {
+            inputIds: [0],
+            outputIds: [2],
+            layers: [
+            {
+                layer_type: "InputLayer",
+                layer: {
+                      base: {
+                            layerBindingId: 0,
+                            base: {
+                                index: 0,
+                                layerName: "InputLayer",
+                                layerType: "Input",
+                                inputSlots: [{
+                                    index: 0,
+                                    connection: {sourceLayerIndex:0, outputSlotIndex:0 },
+                                }],
+                                outputSlots: [ {
+                                    index: 0,
+                                    tensorInfo: {
+                                        dimensions: )" + inputShape + R"(,
+                                        dataType: )" + dataType + R"(
+                                        }}]
+                                }
+                }}},
+                {
+                layer_type: "Pooling3dLayer",
+                layer: {
+                      base: {
+                           index: 1,
+                           layerName: "Pooling3dLayer",
+                           layerType: "Pooling3d",
+                           inputSlots: [{
+                                  index: 0,
+                                  connection: {sourceLayerIndex:0, outputSlotIndex:0 },
+                           }],
+                           outputSlots: [ {
+                                  index: 0,
+                                  tensorInfo: {
+                                       dimensions: )" + outputShape + R"(,
+                                       dataType: )" + dataType + R"(
+
+                           }}]},
+                      descriptor: {
+                           poolType: )" + poolingAlgorithm + R"(,
+                           outputShapeRounding: "Floor",
+                           paddingMethod: Exclude,
+                           dataLayout: )" + dataLayout + R"(,
+                           padLeft: 0,
+                           padRight: 0,
+                           padTop: 0,
+                           padBottom: 0,
+                           padFront: 0,
+                           padBack: 0,
+                           poolWidth: 2,
+                           poolHeight: 2,
+                           poolDepth: 2,
+                           strideX: 2,
+                           strideY: 2,
+                           strideZ: 2
+                           }
+                }},
+                {
+                layer_type: "OutputLayer",
+                layer: {
+                    base:{
+                          layerBindingId: 0,
+                          base: {
+                                index: 2,
+                                layerName: "OutputLayer",
+                                layerType: "Output",
+                                inputSlots: [{
+                                    index: 0,
+                                    connection: {sourceLayerIndex:1, outputSlotIndex:0 },
+                                }],
+                                outputSlots: [ {
+                                    index: 0,
+                                    tensorInfo: {
+                                        dimensions: )" + outputShape + R"(,
+                                        dataType: )" + dataType + R"(
+                                    },
+                            }],
+                        }}},
+            }]
+     }
+ )";
+        SetupSingleInputSingleOutput("InputLayer", "OutputLayer");
+    }
+};
+
+struct SimpleAvgPooling3dFixture : Pooling3dFixture
+{
+    SimpleAvgPooling3dFixture() : Pooling3dFixture("[ 1, 2, 2, 2, 1 ]",
+                                                   "[ 1, 1, 1, 1, 1 ]",
+                                                   "Float32", "NDHWC", "Average") {}
+};
+
+struct SimpleAvgPooling3dFixture2 : Pooling3dFixture
+{
+    SimpleAvgPooling3dFixture2() : Pooling3dFixture("[ 1, 2, 2, 2, 1 ]",
+                                                    "[ 1, 1, 1, 1, 1 ]",
+                                                    "QuantisedAsymm8", "NDHWC", "Average") {}
+};
+
+struct SimpleMaxPooling3dFixture : Pooling3dFixture
+{
+    SimpleMaxPooling3dFixture() : Pooling3dFixture("[ 1, 1, 2, 2, 2 ]",
+                                                   "[ 1, 1, 1, 1, 1 ]",
+                                                   "Float32", "NCDHW", "Max") {}
+};
+
+struct SimpleMaxPooling3dFixture2 : Pooling3dFixture
+{
+    SimpleMaxPooling3dFixture2() : Pooling3dFixture("[ 1, 1, 2, 2, 2 ]",
+                                                    "[ 1, 1, 1, 1, 1 ]",
+                                                    "QuantisedAsymm8", "NCDHW", "Max") {}
+};
+
+struct SimpleL2Pooling3dFixture : Pooling3dFixture
+{
+    SimpleL2Pooling3dFixture() : Pooling3dFixture("[ 1, 2, 2, 2, 1 ]",
+                                                  "[ 1, 1, 1, 1, 1 ]",
+                                                  "Float32", "NDHWC", "L2") {}
+};
+
+TEST_CASE_FIXTURE(SimpleAvgPooling3dFixture, "Pooling3dFloat32Avg")
+{
+    RunTest<5, armnn::DataType::Float32>(0, { 2, 3, 5, 2, 3, 2, 3, 4 }, { 3 });
+}
+
+TEST_CASE_FIXTURE(SimpleAvgPooling3dFixture2, "Pooling3dQuantisedAsymm8Avg")
+{
+    RunTest<5, armnn::DataType::QAsymmU8>(0,{ 20, 40, 60, 80, 50, 60, 70, 30 },{ 50 });
+}
+
+TEST_CASE_FIXTURE(SimpleMaxPooling3dFixture, "Pooling3dFloat32Max")
+{
+    RunTest<5, armnn::DataType::Float32>(0, { 2, 5, 5, 2, 1, 3, 4, 0 }, { 5 });
+}
+
+TEST_CASE_FIXTURE(SimpleMaxPooling3dFixture2, "Pooling3dQuantisedAsymm8Max")
+{
+    RunTest<5, armnn::DataType::QAsymmU8>(0,{ 20, 40, 60, 80, 10, 40, 0, 70 },{ 80 });
+}
+
+TEST_CASE_FIXTURE(SimpleL2Pooling3dFixture, "Pooling3dFloat32L2")
+{
+    RunTest<5, armnn::DataType::Float32>(0, { 2, 3, 5, 2, 4, 1, 1, 3 }, { 2.93683503112f });
+}
+
+}
+
diff --git a/src/armnnSerializer/ArmnnSchema.fbs b/src/armnnSerializer/ArmnnSchema.fbs
index 362dd5c..c8ffce4 100644
--- a/src/armnnSerializer/ArmnnSchema.fbs
+++ b/src/armnnSerializer/ArmnnSchema.fbs
@@ -180,6 +180,7 @@
     UnidirectionalSequenceLstm = 63,
     ChannelShuffle = 64,
     Convolution3d = 65,
+    Pooling3d = 66,
 }
 
 // Base layer table to be used as part of other layers
@@ -453,6 +454,11 @@
     descriptor:Pooling2dDescriptor;
 }
 
+table Pooling3dLayer {
+    base:LayerBase;
+    descriptor:Pooling3dDescriptor;
+}
+
 enum PoolingAlgorithm : byte {
     Max = 0,
     Average = 1,
@@ -484,6 +490,25 @@
     dataLayout:DataLayout;
 }
 
+table Pooling3dDescriptor {
+    poolType:PoolingAlgorithm;
+    padLeft:uint;
+    padRight:uint;
+    padTop:uint;
+    padBottom:uint;
+    padFront:uint;
+    padBack:uint;
+    poolWidth:uint;
+    poolHeight:uint;
+    poolDepth:uint;
+    strideX:uint;
+    strideY:uint;
+    strideZ:uint;
+    outputShapeRounding:OutputShapeRounding;
+    paddingMethod:PaddingMethod;
+    dataLayout:DataLayout;
+}
+
 table QuantizeLayer {
     base:LayerBase;
 }
@@ -1046,6 +1071,7 @@
     UnidirectionalSequenceLstmLayer,
     ChannelShuffleLayer,
     Convolution3dLayer,
+    Pooling3dLayer,
 }
 
 table AnyLayer {
diff --git a/src/armnnSerializer/ArmnnSchema_generated.h b/src/armnnSerializer/ArmnnSchema_generated.h
index b66bac6..76a6460 100644
--- a/src/armnnSerializer/ArmnnSchema_generated.h
+++ b/src/armnnSerializer/ArmnnSchema_generated.h
@@ -173,9 +173,15 @@
 struct Pooling2dLayer;
 struct Pooling2dLayerBuilder;
 
+struct Pooling3dLayer;
+struct Pooling3dLayerBuilder;
+
 struct Pooling2dDescriptor;
 struct Pooling2dDescriptorBuilder;
 
+struct Pooling3dDescriptor;
+struct Pooling3dDescriptorBuilder;
+
 struct QuantizeLayer;
 struct QuantizeLayerBuilder;
 
@@ -770,11 +776,12 @@
   LayerType_UnidirectionalSequenceLstm = 63,
   LayerType_ChannelShuffle = 64,
   LayerType_Convolution3d = 65,
+  LayerType_Pooling3d = 66,
   LayerType_MIN = LayerType_Addition,
-  LayerType_MAX = LayerType_Convolution3d
+  LayerType_MAX = LayerType_Pooling3d
 };
 
-inline const LayerType (&EnumValuesLayerType())[66] {
+inline const LayerType (&EnumValuesLayerType())[67] {
   static const LayerType values[] = {
     LayerType_Addition,
     LayerType_Input,
@@ -841,13 +848,14 @@
     LayerType_Shape,
     LayerType_UnidirectionalSequenceLstm,
     LayerType_ChannelShuffle,
-    LayerType_Convolution3d
+    LayerType_Convolution3d,
+    LayerType_Pooling3d
   };
   return values;
 }
 
 inline const char * const *EnumNamesLayerType() {
-  static const char * const names[67] = {
+  static const char * const names[68] = {
     "Addition",
     "Input",
     "Multiplication",
@@ -914,13 +922,14 @@
     "UnidirectionalSequenceLstm",
     "ChannelShuffle",
     "Convolution3d",
+    "Pooling3d",
     nullptr
   };
   return names;
 }
 
 inline const char *EnumNameLayerType(LayerType e) {
-  if (flatbuffers::IsOutRange(e, LayerType_Addition, LayerType_Convolution3d)) return "";
+  if (flatbuffers::IsOutRange(e, LayerType_Addition, LayerType_Pooling3d)) return "";
   const size_t index = static_cast<size_t>(e);
   return EnumNamesLayerType()[index];
 }
@@ -1299,11 +1308,12 @@
   Layer_UnidirectionalSequenceLstmLayer = 64,
   Layer_ChannelShuffleLayer = 65,
   Layer_Convolution3dLayer = 66,
+  Layer_Pooling3dLayer = 67,
   Layer_MIN = Layer_NONE,
-  Layer_MAX = Layer_Convolution3dLayer
+  Layer_MAX = Layer_Pooling3dLayer
 };
 
-inline const Layer (&EnumValuesLayer())[67] {
+inline const Layer (&EnumValuesLayer())[68] {
   static const Layer values[] = {
     Layer_NONE,
     Layer_ActivationLayer,
@@ -1371,13 +1381,14 @@
     Layer_ShapeLayer,
     Layer_UnidirectionalSequenceLstmLayer,
     Layer_ChannelShuffleLayer,
-    Layer_Convolution3dLayer
+    Layer_Convolution3dLayer,
+    Layer_Pooling3dLayer
   };
   return values;
 }
 
 inline const char * const *EnumNamesLayer() {
-  static const char * const names[68] = {
+  static const char * const names[69] = {
     "NONE",
     "ActivationLayer",
     "AdditionLayer",
@@ -1445,13 +1456,14 @@
     "UnidirectionalSequenceLstmLayer",
     "ChannelShuffleLayer",
     "Convolution3dLayer",
+    "Pooling3dLayer",
     nullptr
   };
   return names;
 }
 
 inline const char *EnumNameLayer(Layer e) {
-  if (flatbuffers::IsOutRange(e, Layer_NONE, Layer_Convolution3dLayer)) return "";
+  if (flatbuffers::IsOutRange(e, Layer_NONE, Layer_Pooling3dLayer)) return "";
   const size_t index = static_cast<size_t>(e);
   return EnumNamesLayer()[index];
 }
@@ -1724,6 +1736,10 @@
   static const Layer enum_value = Layer_Convolution3dLayer;
 };
 
+template<> struct LayerTraits<armnnSerializer::Pooling3dLayer> {
+  static const Layer enum_value = Layer_Pooling3dLayer;
+};
+
 bool VerifyLayer(flatbuffers::Verifier &verifier, const void *obj, Layer type);
 bool VerifyLayerVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
 
@@ -4874,6 +4890,60 @@
   return builder_.Finish();
 }
 
+struct Pooling3dLayer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  typedef Pooling3dLayerBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+    VT_BASE = 4,
+    VT_DESCRIPTOR = 6
+  };
+  const armnnSerializer::LayerBase *base() const {
+    return GetPointer<const armnnSerializer::LayerBase *>(VT_BASE);
+  }
+  const armnnSerializer::Pooling3dDescriptor *descriptor() const {
+    return GetPointer<const armnnSerializer::Pooling3dDescriptor *>(VT_DESCRIPTOR);
+  }
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           VerifyOffset(verifier, VT_BASE) &&
+           verifier.VerifyTable(base()) &&
+           VerifyOffset(verifier, VT_DESCRIPTOR) &&
+           verifier.VerifyTable(descriptor()) &&
+           verifier.EndTable();
+  }
+};
+
+struct Pooling3dLayerBuilder {
+  typedef Pooling3dLayer Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  void add_base(flatbuffers::Offset<armnnSerializer::LayerBase> base) {
+    fbb_.AddOffset(Pooling3dLayer::VT_BASE, base);
+  }
+  void add_descriptor(flatbuffers::Offset<armnnSerializer::Pooling3dDescriptor> descriptor) {
+    fbb_.AddOffset(Pooling3dLayer::VT_DESCRIPTOR, descriptor);
+  }
+  explicit Pooling3dLayerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+        : fbb_(_fbb) {
+    start_ = fbb_.StartTable();
+  }
+  Pooling3dLayerBuilder &operator=(const Pooling3dLayerBuilder &);
+  flatbuffers::Offset<Pooling3dLayer> Finish() {
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<Pooling3dLayer>(end);
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<Pooling3dLayer> CreatePooling3dLayer(
+    flatbuffers::FlatBufferBuilder &_fbb,
+    flatbuffers::Offset<armnnSerializer::LayerBase> base = 0,
+    flatbuffers::Offset<armnnSerializer::Pooling3dDescriptor> descriptor = 0) {
+  Pooling3dLayerBuilder builder_(_fbb);
+  builder_.add_descriptor(descriptor);
+  builder_.add_base(base);
+  return builder_.Finish();
+}
+
 struct Pooling2dDescriptor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef Pooling2dDescriptorBuilder Builder;
   enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
@@ -5026,6 +5096,198 @@
   return builder_.Finish();
 }
 
+struct Pooling3dDescriptor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  typedef Pooling3dDescriptorBuilder Builder;
+  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+    VT_POOLTYPE = 4,
+    VT_PADLEFT = 6,
+    VT_PADRIGHT = 8,
+    VT_PADTOP = 10,
+    VT_PADBOTTOM = 12,
+    VT_PADFRONT = 14,
+    VT_PADBACK = 16,
+    VT_POOLWIDTH = 18,
+    VT_POOLHEIGHT = 20,
+    VT_POOLDEPTH = 22,
+    VT_STRIDEX = 24,
+    VT_STRIDEY = 26,
+    VT_STRIDEZ = 28,
+    VT_OUTPUTSHAPEROUNDING = 30,
+    VT_PADDINGMETHOD = 32,
+    VT_DATALAYOUT = 34
+  };
+  armnnSerializer::PoolingAlgorithm poolType() const {
+    return static_cast<armnnSerializer::PoolingAlgorithm>(GetField<int8_t>(VT_POOLTYPE, 0));
+  }
+  uint32_t padLeft() const {
+    return GetField<uint32_t>(VT_PADLEFT, 0);
+  }
+  uint32_t padRight() const {
+    return GetField<uint32_t>(VT_PADRIGHT, 0);
+  }
+  uint32_t padTop() const {
+    return GetField<uint32_t>(VT_PADTOP, 0);
+  }
+  uint32_t padBottom() const {
+    return GetField<uint32_t>(VT_PADBOTTOM, 0);
+  }
+  uint32_t padFront() const {
+    return GetField<uint32_t>(VT_PADFRONT, 0);
+  }
+  uint32_t padBack() const {
+    return GetField<uint32_t>(VT_PADBACK, 0);
+  }
+  uint32_t poolWidth() const {
+    return GetField<uint32_t>(VT_POOLWIDTH, 0);
+  }
+  uint32_t poolHeight() const {
+    return GetField<uint32_t>(VT_POOLHEIGHT, 0);
+  }
+  uint32_t poolDepth() const {
+    return GetField<uint32_t>(VT_POOLDEPTH, 0);
+  }
+  uint32_t strideX() const {
+    return GetField<uint32_t>(VT_STRIDEX, 0);
+  }
+  uint32_t strideY() const {
+    return GetField<uint32_t>(VT_STRIDEY, 0);
+  }
+  uint32_t strideZ() const {
+    return GetField<uint32_t>(VT_STRIDEZ, 0);
+  }
+  armnnSerializer::OutputShapeRounding outputShapeRounding() const {
+    return static_cast<armnnSerializer::OutputShapeRounding>(GetField<int8_t>(VT_OUTPUTSHAPEROUNDING, 0));
+  }
+  armnnSerializer::PaddingMethod paddingMethod() const {
+    return static_cast<armnnSerializer::PaddingMethod>(GetField<int8_t>(VT_PADDINGMETHOD, 0));
+  }
+  armnnSerializer::DataLayout dataLayout() const {
+    return static_cast<armnnSerializer::DataLayout>(GetField<int8_t>(VT_DATALAYOUT, 0));
+  }
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           VerifyField<int8_t>(verifier, VT_POOLTYPE) &&
+           VerifyField<uint32_t>(verifier, VT_PADLEFT) &&
+           VerifyField<uint32_t>(verifier, VT_PADRIGHT) &&
+           VerifyField<uint32_t>(verifier, VT_PADTOP) &&
+           VerifyField<uint32_t>(verifier, VT_PADBOTTOM) &&
+           VerifyField<uint32_t>(verifier, VT_PADFRONT) &&
+           VerifyField<uint32_t>(verifier, VT_PADBACK) &&
+           VerifyField<uint32_t>(verifier, VT_POOLWIDTH) &&
+           VerifyField<uint32_t>(verifier, VT_POOLHEIGHT) &&
+           VerifyField<uint32_t>(verifier, VT_POOLDEPTH) &&
+           VerifyField<uint32_t>(verifier, VT_STRIDEX) &&
+           VerifyField<uint32_t>(verifier, VT_STRIDEY) &&
+           VerifyField<uint32_t>(verifier, VT_STRIDEZ) &&
+           VerifyField<int8_t>(verifier, VT_OUTPUTSHAPEROUNDING) &&
+           VerifyField<int8_t>(verifier, VT_PADDINGMETHOD) &&
+           VerifyField<int8_t>(verifier, VT_DATALAYOUT) &&
+           verifier.EndTable();
+  }
+};
+
+struct Pooling3dDescriptorBuilder {
+  typedef Pooling3dDescriptor Table;
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  void add_poolType(armnnSerializer::PoolingAlgorithm poolType) {
+    fbb_.AddElement<int8_t>(Pooling3dDescriptor::VT_POOLTYPE, static_cast<int8_t>(poolType), 0);
+  }
+  void add_padLeft(uint32_t padLeft) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_PADLEFT, padLeft, 0);
+  }
+  void add_padRight(uint32_t padRight) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_PADRIGHT, padRight, 0);
+  }
+  void add_padTop(uint32_t padTop) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_PADTOP, padTop, 0);
+  }
+  void add_padBottom(uint32_t padBottom) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_PADBOTTOM, padBottom, 0);
+  }
+  void add_padFront(uint32_t padFront) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_PADFRONT, padFront, 0);
+  }
+  void add_padBack(uint32_t padBack) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_PADBACK, padBack, 0);
+  }
+  void add_poolWidth(uint32_t poolWidth) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_POOLWIDTH, poolWidth, 0);
+  }
+  void add_poolHeight(uint32_t poolHeight) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_POOLHEIGHT, poolHeight, 0);
+  }
+  void add_poolDepth(uint32_t poolDepth) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_POOLDEPTH, poolDepth, 0);
+  }
+  void add_strideX(uint32_t strideX) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_STRIDEX, strideX, 0);
+  }
+  void add_strideY(uint32_t strideY) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_STRIDEY, strideY, 0);
+  }
+  void add_strideZ(uint32_t strideZ) {
+    fbb_.AddElement<uint32_t>(Pooling3dDescriptor::VT_STRIDEZ, strideZ, 0);
+  }
+  void add_outputShapeRounding(armnnSerializer::OutputShapeRounding outputShapeRounding) {
+    fbb_.AddElement<int8_t>(Pooling3dDescriptor::VT_OUTPUTSHAPEROUNDING, static_cast<int8_t>(outputShapeRounding), 0);
+  }
+  void add_paddingMethod(armnnSerializer::PaddingMethod paddingMethod) {
+    fbb_.AddElement<int8_t>(Pooling3dDescriptor::VT_PADDINGMETHOD, static_cast<int8_t>(paddingMethod), 0);
+  }
+  void add_dataLayout(armnnSerializer::DataLayout dataLayout) {
+    fbb_.AddElement<int8_t>(Pooling3dDescriptor::VT_DATALAYOUT, static_cast<int8_t>(dataLayout), 0);
+  }
+  explicit Pooling3dDescriptorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+        : fbb_(_fbb) {
+    start_ = fbb_.StartTable();
+  }
+  Pooling3dDescriptorBuilder &operator=(const Pooling3dDescriptorBuilder &);
+  flatbuffers::Offset<Pooling3dDescriptor> Finish() {
+    const auto end = fbb_.EndTable(start_);
+    auto o = flatbuffers::Offset<Pooling3dDescriptor>(end);
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<Pooling3dDescriptor> CreatePooling3dDescriptor(
+    flatbuffers::FlatBufferBuilder &_fbb,
+    armnnSerializer::PoolingAlgorithm poolType = armnnSerializer::PoolingAlgorithm_Max,
+    uint32_t padLeft = 0,
+    uint32_t padRight = 0,
+    uint32_t padTop = 0,
+    uint32_t padBottom = 0,
+    uint32_t padFront = 0,
+    uint32_t padBack = 0,
+    uint32_t poolWidth = 0,
+    uint32_t poolHeight = 0,
+    uint32_t poolDepth = 0,
+    uint32_t strideX = 0,
+    uint32_t strideY = 0,
+    uint32_t strideZ = 0,
+    armnnSerializer::OutputShapeRounding outputShapeRounding = armnnSerializer::OutputShapeRounding_Floor,
+    armnnSerializer::PaddingMethod paddingMethod = armnnSerializer::PaddingMethod_IgnoreValue,
+    armnnSerializer::DataLayout dataLayout = armnnSerializer::DataLayout_NHWC) {
+  Pooling3dDescriptorBuilder builder_(_fbb);
+  builder_.add_strideZ(strideZ);
+  builder_.add_strideY(strideY);
+  builder_.add_strideX(strideX);
+  builder_.add_poolDepth(poolDepth);
+  builder_.add_poolHeight(poolHeight);
+  builder_.add_poolWidth(poolWidth);
+  builder_.add_padBack(padBack);
+  builder_.add_padFront(padFront);
+  builder_.add_padBottom(padBottom);
+  builder_.add_padTop(padTop);
+  builder_.add_padRight(padRight);
+  builder_.add_padLeft(padLeft);
+  builder_.add_dataLayout(dataLayout);
+  builder_.add_paddingMethod(paddingMethod);
+  builder_.add_outputShapeRounding(outputShapeRounding);
+  builder_.add_poolType(poolType);
+  return builder_.Finish();
+}
+
 struct QuantizeLayer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   typedef QuantizeLayerBuilder Builder;
   enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
@@ -10269,6 +10531,9 @@
   const armnnSerializer::Convolution3dLayer *layer_as_Convolution3dLayer() const {
     return layer_type() == armnnSerializer::Layer_Convolution3dLayer ? static_cast<const armnnSerializer::Convolution3dLayer *>(layer()) : nullptr;
   }
+  const armnnSerializer::Pooling3dLayer *layer_as_Pooling3dLayer() const {
+    return layer_type() == armnnSerializer::Layer_Pooling3dLayer ? static_cast<const armnnSerializer::Pooling3dLayer *>(layer()) : nullptr;
+  }
   bool Verify(flatbuffers::Verifier &verifier) const {
     return VerifyTableStart(verifier) &&
            VerifyField<uint8_t>(verifier, VT_LAYER_TYPE) &&
@@ -10542,6 +10807,10 @@
   return layer_as_Convolution3dLayer();
 }
 
+template<> inline const armnnSerializer::Pooling3dLayer *AnyLayer::layer_as<armnnSerializer::Pooling3dLayer>() const {
+  return layer_as_Pooling3dLayer();
+}
+
 struct AnyLayerBuilder {
   typedef AnyLayer Table;
   flatbuffers::FlatBufferBuilder &fbb_;
@@ -11036,6 +11305,10 @@
       auto ptr = reinterpret_cast<const armnnSerializer::Convolution3dLayer *>(obj);
       return verifier.VerifyTable(ptr);
     }
+    case Layer_Pooling3dLayer: {
+      auto ptr = reinterpret_cast<const armnnSerializer::Pooling3dLayer *>(obj);
+      return verifier.VerifyTable(ptr);
+    }
     default: return true;
   }
 }
diff --git a/src/armnnSerializer/Serializer.cpp b/src/armnnSerializer/Serializer.cpp
index a9f7b7d..4249e08 100644
--- a/src/armnnSerializer/Serializer.cpp
+++ b/src/armnnSerializer/Serializer.cpp
@@ -1079,6 +1079,39 @@
     CreateAnyLayer(fbPooling2dLayer.o, serializer::Layer::Layer_Pooling2dLayer);
 }
 
+void SerializerStrategy::SerializePooling3dLayer(const armnn::IConnectableLayer* layer,
+                                            const armnn::Pooling3dDescriptor& pooling3dDescriptor,
+                                            const char* name)
+{
+    IgnoreUnused(name);
+
+    auto fbPooling3dBaseLayer  = CreateLayerBase(layer, serializer::LayerType::LayerType_Pooling3d);
+    auto fbPooling3dDescriptor = serializer::CreatePooling3dDescriptor(
+        m_flatBufferBuilder,
+        GetFlatBufferPoolingAlgorithm(pooling3dDescriptor.m_PoolType),
+        pooling3dDescriptor.m_PadLeft,
+        pooling3dDescriptor.m_PadRight,
+        pooling3dDescriptor.m_PadTop,
+        pooling3dDescriptor.m_PadBottom,
+        pooling3dDescriptor.m_PadFront,
+        pooling3dDescriptor.m_PadBack,
+        pooling3dDescriptor.m_PoolWidth,
+        pooling3dDescriptor.m_PoolHeight,
+        pooling3dDescriptor.m_PoolDepth,
+        pooling3dDescriptor.m_StrideX,
+        pooling3dDescriptor.m_StrideY,
+        pooling3dDescriptor.m_StrideZ,
+        GetFlatBufferOutputShapeRounding(pooling3dDescriptor.m_OutputShapeRounding),
+        GetFlatBufferPaddingMethod(pooling3dDescriptor.m_PaddingMethod),
+        GetFlatBufferDataLayout(pooling3dDescriptor.m_DataLayout));
+
+    auto fbPooling3dLayer = serializer::CreatePooling3dLayer(m_flatBufferBuilder,
+                                                             fbPooling3dBaseLayer,
+                                                             fbPooling3dDescriptor);
+
+    CreateAnyLayer(fbPooling3dLayer.o, serializer::Layer::Layer_Pooling3dLayer);
+}
+
 void SerializerStrategy::SerializePreluLayer(const armnn::IConnectableLayer* layer,
                                         const char* name)
 {
@@ -2208,6 +2241,13 @@
             SerializePooling2dLayer(layer, layerDescriptor, name);
             break;
         }
+        case armnn::LayerType::Pooling3d :
+        {
+            const armnn::Pooling3dDescriptor& layerDescriptor =
+                    static_cast<const armnn::Pooling3dDescriptor&>(descriptor);
+            SerializePooling3dLayer(layer, layerDescriptor, name);
+            break;
+        }
         case armnn::LayerType::Prelu :
         {
             SerializePreluLayer(layer, name);
diff --git a/src/armnnSerializer/Serializer.hpp b/src/armnnSerializer/Serializer.hpp
index 1c0a9a6..bb6455f 100644
--- a/src/armnnSerializer/Serializer.hpp
+++ b/src/armnnSerializer/Serializer.hpp
@@ -248,6 +248,10 @@
                                  const armnn::Pooling2dDescriptor& pooling2dDescriptor,
                                  const char* name = nullptr);
 
+    void SerializePooling3dLayer(const armnn::IConnectableLayer* layer,
+                                 const armnn::Pooling3dDescriptor& pooling3dDescriptor,
+                                 const char* name = nullptr);
+
     void SerializePreluLayer(const armnn::IConnectableLayer* layer,
                              const char* name = nullptr);
 
diff --git a/src/armnnSerializer/test/SerializerTests.cpp b/src/armnnSerializer/test/SerializerTests.cpp
index f4e2599..632a80a 100644
--- a/src/armnnSerializer/test/SerializerTests.cpp
+++ b/src/armnnSerializer/test/SerializerTests.cpp
@@ -1834,6 +1834,49 @@
     deserializedNetwork->ExecuteStrategy(verifier);
 }
 
+TEST_CASE("SerializePooling3d")
+{
+    const std::string layerName("pooling3d");
+    const armnn::TensorInfo inputInfo({1, 1, 2, 2, 2}, armnn::DataType::Float32);
+    const armnn::TensorInfo outputInfo({1, 1, 1, 1, 1}, armnn::DataType::Float32);
+
+    armnn::Pooling3dDescriptor desc;
+    desc.m_DataLayout          = armnn::DataLayout::NDHWC;
+    desc.m_PadFront            = 0;
+    desc.m_PadBack             = 0;
+    desc.m_PadTop              = 0;
+    desc.m_PadBottom           = 0;
+    desc.m_PadLeft             = 0;
+    desc.m_PadRight            = 0;
+    desc.m_PoolType            = armnn::PoolingAlgorithm::Average;
+    desc.m_OutputShapeRounding = armnn::OutputShapeRounding::Floor;
+    desc.m_PaddingMethod       = armnn::PaddingMethod::Exclude;
+    desc.m_PoolHeight          = 2;
+    desc.m_PoolWidth           = 2;
+    desc.m_PoolDepth           = 2;
+    desc.m_StrideX             = 2;
+    desc.m_StrideY             = 2;
+    desc.m_StrideZ             = 2;
+
+    armnn::INetworkPtr network = armnn::INetwork::Create();
+    armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
+    armnn::IConnectableLayer* const pooling3dLayer = network->AddPooling3dLayer(desc, layerName.c_str());
+    armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
+
+    inputLayer->GetOutputSlot(0).Connect(pooling3dLayer->GetInputSlot(0));
+    pooling3dLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+
+    inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
+    pooling3dLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
+
+    armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
+    CHECK(deserializedNetwork);
+
+    LayerVerifierBaseWithDescriptor<armnn::Pooling3dDescriptor> verifier(
+            layerName, {inputInfo}, {outputInfo}, desc);
+    deserializedNetwork->ExecuteStrategy(verifier);
+}
+
 TEST_CASE("SerializeQuantize")
 {
     const std::string layerName("quantize");