aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamas Nyiri <tamas.nyiri@arm.com>2021-11-05 14:55:33 +0000
committerTamas Nyiri <tamas.nyiri@arm.com>2021-11-17 11:32:55 +0000
commitd998a1cfbcc7b4ed9922532ffe19c51283fcae68 (patch)
tree53317946bb5845f4f253ebfd53b668c6698fcfee
parent7b885b3cce70154596b1994b013ea91527117c26 (diff)
downloadarmnn-d998a1cfbcc7b4ed9922532ffe19c51283fcae68.tar.gz
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>
-rw-r--r--CMakeLists.txt1
-rw-r--r--docs/05_02_deserializer_serializer.dox1
-rw-r--r--src/armnn/SerializeLayerParameters.cpp31
-rw-r--r--src/armnn/SerializeLayerParameters.hpp5
-rw-r--r--src/armnnDeserializer/Deserializer.cpp125
-rw-r--r--src/armnnDeserializer/Deserializer.hpp8
-rw-r--r--src/armnnDeserializer/test/DeserializePooling3d.cpp173
-rw-r--r--src/armnnSerializer/ArmnnSchema.fbs26
-rw-r--r--src/armnnSerializer/ArmnnSchema_generated.h293
-rw-r--r--src/armnnSerializer/Serializer.cpp40
-rw-r--r--src/armnnSerializer/Serializer.hpp4
-rw-r--r--src/armnnSerializer/test/SerializerTests.cpp43
12 files changed, 735 insertions, 15 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3653740c00..4ea40de109 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -821,6 +821,7 @@ if(BUILD_UNIT_TESTS)
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 5d4dc43a74..84324d89d5 100644
--- a/docs/05_02_deserializer_serializer.dox
+++ b/docs/05_02_deserializer_serializer.dox
@@ -57,6 +57,7 @@ The Arm NN SDK Serializer currently supports the following layers:
- Pad (Constant, Symmetric, Reflect)
- Permute
- Pooling2d
+- Pooling3d
- Prelu
- QLstm
- Quantize
diff --git a/src/armnn/SerializeLayerParameters.cpp b/src/armnn/SerializeLayerParameters.cpp
index c60d4faf79..d7f38034f5 100644
--- a/src/armnn/SerializeLayerParameters.cpp
+++ b/src/armnn/SerializeLayerParameters.cpp
@@ -121,7 +121,7 @@ void StringifyLayerParameters<Convolution3dDescriptor>::Serialize(ParameterStrin
{
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 @@ void StringifyLayerParameters<Pooling2dDescriptor>::Serialize(ParameterStringify
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 5c1e6f3759..d2c7d76d7d 100644
--- a/src/armnn/SerializeLayerParameters.hpp
+++ b/src/armnn/SerializeLayerParameters.hpp
@@ -124,6 +124,11 @@ template <> struct StringifyLayerParameters<Pooling2dDescriptor>
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 8b1e9b970c..a5114ecfca 100644
--- a/src/armnnDeserializer/Deserializer.cpp
+++ b/src/armnnDeserializer/Deserializer.cpp
@@ -249,6 +249,7 @@ m_ParserFunctions(Layer_MAX+1, &IDeserializer::DeserializerImpl::ParseUnsupporte
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 @@ LayerBaseRawPtr IDeserializer::DeserializerImpl::GetBaseLayer(const GraphPtr& gr
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 @@ void IDeserializer::DeserializerImpl::ParsePermute(GraphPtr graph, unsigned int
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 @@ armnn::Pooling2dDescriptor IDeserializer::DeserializerImpl::GetPoolingDescriptor
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 @@ void IDeserializer::DeserializerImpl::ParsePooling2d(GraphPtr graph, unsigned in
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 @@ void IDeserializer::DeserializerImpl::ParsePooling2d(GraphPtr graph, unsigned in
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 d2291c07a7..8de492ed5f 100644
--- a/src/armnnDeserializer/Deserializer.hpp
+++ b/src/armnnDeserializer/Deserializer.hpp
@@ -18,7 +18,8 @@ namespace armnnDeserializer
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 @@ public:
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 @@ private:
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 0000000000..62fdc5cd60
--- /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 362dd5c653..c8ffce48bc 100644
--- a/src/armnnSerializer/ArmnnSchema.fbs
+++ b/src/armnnSerializer/ArmnnSchema.fbs
@@ -180,6 +180,7 @@ enum LayerType : uint {
UnidirectionalSequenceLstm = 63,
ChannelShuffle = 64,
Convolution3d = 65,
+ Pooling3d = 66,
}
// Base layer table to be used as part of other layers
@@ -453,6 +454,11 @@ table Pooling2dLayer {
descriptor:Pooling2dDescriptor;
}
+table Pooling3dLayer {
+ base:LayerBase;
+ descriptor:Pooling3dDescriptor;
+}
+
enum PoolingAlgorithm : byte {
Max = 0,
Average = 1,
@@ -484,6 +490,25 @@ table Pooling2dDescriptor {
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 @@ union Layer {
UnidirectionalSequenceLstmLayer,
ChannelShuffleLayer,
Convolution3dLayer,
+ Pooling3dLayer,
}
table AnyLayer {
diff --git a/src/armnnSerializer/ArmnnSchema_generated.h b/src/armnnSerializer/ArmnnSchema_generated.h
index b66bac69db..76a6460c85 100644
--- a/src/armnnSerializer/ArmnnSchema_generated.h
+++ b/src/armnnSerializer/ArmnnSchema_generated.h
@@ -173,9 +173,15 @@ struct MultiplicationLayerBuilder;
struct Pooling2dLayer;
struct Pooling2dLayerBuilder;
+struct Pooling3dLayer;
+struct Pooling3dLayerBuilder;
+
struct Pooling2dDescriptor;
struct Pooling2dDescriptorBuilder;
+struct Pooling3dDescriptor;
+struct Pooling3dDescriptorBuilder;
+
struct QuantizeLayer;
struct QuantizeLayerBuilder;
@@ -770,11 +776,12 @@ enum LayerType {
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 @@ inline const LayerType (&EnumValuesLayerType())[66] {
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 @@ inline const char * const *EnumNamesLayerType() {
"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 @@ enum Layer {
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 @@ inline const Layer (&EnumValuesLayer())[67] {
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 @@ inline const char * const *EnumNamesLayer() {
"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 @@ template<> struct LayerTraits<armnnSerializer::Convolution3dLayer> {
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 @@ inline flatbuffers::Offset<Pooling2dLayer> CreatePooling2dLayer(
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 @@ inline flatbuffers::Offset<Pooling2dDescriptor> CreatePooling2dDescriptor(
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 @@ struct AnyLayer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
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 @@ template<> inline const armnnSerializer::Convolution3dLayer *AnyLayer::layer_as<
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 @@ inline bool VerifyLayer(flatbuffers::Verifier &verifier, const void *obj, Layer
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 a9f7b7d307..4249e08c71 100644
--- a/src/armnnSerializer/Serializer.cpp
+++ b/src/armnnSerializer/Serializer.cpp
@@ -1079,6 +1079,39 @@ void SerializerStrategy::SerializePooling2dLayer(const armnn::IConnectableLayer*
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 @@ void SerializerStrategy::ExecuteStrategy(const armnn::IConnectableLayer* layer,
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 1c0a9a619f..bb6455f842 100644
--- a/src/armnnSerializer/Serializer.hpp
+++ b/src/armnnSerializer/Serializer.hpp
@@ -248,6 +248,10 @@ private:
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 f4e25998d9..632a80a748 100644
--- a/src/armnnSerializer/test/SerializerTests.cpp
+++ b/src/armnnSerializer/test/SerializerTests.cpp
@@ -1834,6 +1834,49 @@ TEST_CASE("SerializePooling2d")
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");