aboutsummaryrefslogtreecommitdiff
path: root/src/armnnSerializer
diff options
context:
space:
mode:
authorMatthew Sloyan <matthew.sloyan@arm.com>2021-09-08 13:05:51 +0100
committerMatthew Sloyan <matthew.sloyan@arm.com>2021-10-01 15:27:01 +0100
commitb63a31170aee1d28267d83a4bc67b57708fb6b05 (patch)
tree16cea0a872939be749b72f45ad125964439bc40e /src/armnnSerializer
parenteb852bb9e45b1db42a26001ece11ec7cc1f2bbfe (diff)
downloadarmnn-b63a31170aee1d28267d83a4bc67b57708fb6b05.tar.gz
IVGCVSW-6163 Add Conv3d FrontEnd and Ref Implementation
* Added front-end * Added Reference workload * Added Serializer & Deserializer support * Added unit tests * Added NDHWC DataLayout Signed-off-by: Matthew Sloyan <matthew.sloyan@arm.com> Change-Id: Iec4d39e7433b5334d52fa44cf8efc6bcd39319d8
Diffstat (limited to 'src/armnnSerializer')
-rw-r--r--src/armnnSerializer/ArmnnSchema.fbs29
-rw-r--r--src/armnnSerializer/ArmnnSchema_generated.h308
-rw-r--r--src/armnnSerializer/Serializer.cpp58
-rw-r--r--src/armnnSerializer/Serializer.hpp9
-rw-r--r--src/armnnSerializer/SerializerUtils.cpp2
-rw-r--r--src/armnnSerializer/test/SerializerTests.cpp55
6 files changed, 443 insertions, 18 deletions
diff --git a/src/armnnSerializer/ArmnnSchema.fbs b/src/armnnSerializer/ArmnnSchema.fbs
index 740090bcc8..77982888c8 100644
--- a/src/armnnSerializer/ArmnnSchema.fbs
+++ b/src/armnnSerializer/ArmnnSchema.fbs
@@ -45,7 +45,8 @@ enum DataType : byte {
enum DataLayout : byte {
NHWC = 0,
- NCHW = 1
+ NCHW = 1,
+ NDHWC = 2
}
enum ReduceOperation: byte {
@@ -177,6 +178,7 @@ enum LayerType : uint {
Shape = 62,
UnidirectionalSequenceLstm = 63,
ChannelShuffle = 64,
+ Convolution3d = 65,
}
// Base layer table to be used as part of other layers
@@ -282,6 +284,30 @@ table Convolution2dDescriptor {
dataLayout:DataLayout = NCHW;
}
+table Convolution3dLayer {
+ base:LayerBase;
+ descriptor:Convolution3dDescriptor;
+ weights:ConstTensor;
+ biases:ConstTensor;
+}
+
+table Convolution3dDescriptor {
+ padLeft:uint;
+ padRight:uint;
+ padTop:uint;
+ padBottom:uint;
+ padFront:uint;
+ padBack:uint;
+ strideX:uint;
+ strideY:uint;
+ strideZ:uint;
+ dilationX:uint = 1;
+ dilationY:uint = 1;
+ dilationZ:uint = 1;
+ biasEnabled:bool = false;
+ dataLayout:DataLayout = NDHWC;
+}
+
table DepthToSpaceLayer {
base:LayerBase;
descriptor:DepthToSpaceDescriptor;
@@ -1012,6 +1038,7 @@ union Layer {
ShapeLayer,
UnidirectionalSequenceLstmLayer,
ChannelShuffleLayer,
+ Convolution3dLayer,
}
table AnyLayer {
diff --git a/src/armnnSerializer/ArmnnSchema_generated.h b/src/armnnSerializer/ArmnnSchema_generated.h
index 653ea6a1e5..8234aa9c47 100644
--- a/src/armnnSerializer/ArmnnSchema_generated.h
+++ b/src/armnnSerializer/ArmnnSchema_generated.h
@@ -86,6 +86,12 @@ struct Convolution2dLayerBuilder;
struct Convolution2dDescriptor;
struct Convolution2dDescriptorBuilder;
+struct Convolution3dLayer;
+struct Convolution3dLayerBuilder;
+
+struct Convolution3dDescriptor;
+struct Convolution3dDescriptorBuilder;
+
struct DepthToSpaceLayer;
struct DepthToSpaceLayerBuilder;
@@ -533,29 +539,32 @@ inline const char *EnumNameDataType(DataType e) {
enum DataLayout {
DataLayout_NHWC = 0,
DataLayout_NCHW = 1,
+ DataLayout_NDHWC = 2,
DataLayout_MIN = DataLayout_NHWC,
- DataLayout_MAX = DataLayout_NCHW
+ DataLayout_MAX = DataLayout_NDHWC
};
-inline const DataLayout (&EnumValuesDataLayout())[2] {
+inline const DataLayout (&EnumValuesDataLayout())[3] {
static const DataLayout values[] = {
DataLayout_NHWC,
- DataLayout_NCHW
+ DataLayout_NCHW,
+ DataLayout_NDHWC
};
return values;
}
inline const char * const *EnumNamesDataLayout() {
- static const char * const names[3] = {
+ static const char * const names[4] = {
"NHWC",
"NCHW",
+ "NDHWC",
nullptr
};
return names;
}
inline const char *EnumNameDataLayout(DataLayout e) {
- if (flatbuffers::IsOutRange(e, DataLayout_NHWC, DataLayout_NCHW)) return "";
+ if (flatbuffers::IsOutRange(e, DataLayout_NHWC, DataLayout_NDHWC)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesDataLayout()[index];
}
@@ -757,11 +766,12 @@ enum LayerType {
LayerType_Shape = 62,
LayerType_UnidirectionalSequenceLstm = 63,
LayerType_ChannelShuffle = 64,
+ LayerType_Convolution3d = 65,
LayerType_MIN = LayerType_Addition,
- LayerType_MAX = LayerType_ChannelShuffle
+ LayerType_MAX = LayerType_Convolution3d
};
-inline const LayerType (&EnumValuesLayerType())[65] {
+inline const LayerType (&EnumValuesLayerType())[66] {
static const LayerType values[] = {
LayerType_Addition,
LayerType_Input,
@@ -827,13 +837,14 @@ inline const LayerType (&EnumValuesLayerType())[65] {
LayerType_Cast,
LayerType_Shape,
LayerType_UnidirectionalSequenceLstm,
- LayerType_ChannelShuffle
+ LayerType_ChannelShuffle,
+ LayerType_Convolution3d
};
return values;
}
inline const char * const *EnumNamesLayerType() {
- static const char * const names[66] = {
+ static const char * const names[67] = {
"Addition",
"Input",
"Multiplication",
@@ -899,13 +910,14 @@ inline const char * const *EnumNamesLayerType() {
"Shape",
"UnidirectionalSequenceLstm",
"ChannelShuffle",
+ "Convolution3d",
nullptr
};
return names;
}
inline const char *EnumNameLayerType(LayerType e) {
- if (flatbuffers::IsOutRange(e, LayerType_Addition, LayerType_ChannelShuffle)) return "";
+ if (flatbuffers::IsOutRange(e, LayerType_Addition, LayerType_Convolution3d)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesLayerType()[index];
}
@@ -1250,11 +1262,12 @@ enum Layer {
Layer_ShapeLayer = 63,
Layer_UnidirectionalSequenceLstmLayer = 64,
Layer_ChannelShuffleLayer = 65,
+ Layer_Convolution3dLayer = 66,
Layer_MIN = Layer_NONE,
- Layer_MAX = Layer_ChannelShuffleLayer
+ Layer_MAX = Layer_Convolution3dLayer
};
-inline const Layer (&EnumValuesLayer())[66] {
+inline const Layer (&EnumValuesLayer())[67] {
static const Layer values[] = {
Layer_NONE,
Layer_ActivationLayer,
@@ -1321,13 +1334,14 @@ inline const Layer (&EnumValuesLayer())[66] {
Layer_CastLayer,
Layer_ShapeLayer,
Layer_UnidirectionalSequenceLstmLayer,
- Layer_ChannelShuffleLayer
+ Layer_ChannelShuffleLayer,
+ Layer_Convolution3dLayer
};
return values;
}
inline const char * const *EnumNamesLayer() {
- static const char * const names[67] = {
+ static const char * const names[68] = {
"NONE",
"ActivationLayer",
"AdditionLayer",
@@ -1394,13 +1408,14 @@ inline const char * const *EnumNamesLayer() {
"ShapeLayer",
"UnidirectionalSequenceLstmLayer",
"ChannelShuffleLayer",
+ "Convolution3dLayer",
nullptr
};
return names;
}
inline const char *EnumNameLayer(Layer e) {
- if (flatbuffers::IsOutRange(e, Layer_NONE, Layer_ChannelShuffleLayer)) return "";
+ if (flatbuffers::IsOutRange(e, Layer_NONE, Layer_Convolution3dLayer)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesLayer()[index];
}
@@ -1669,6 +1684,10 @@ template<> struct LayerTraits<armnnSerializer::ChannelShuffleLayer> {
static const Layer enum_value = Layer_ChannelShuffleLayer;
};
+template<> struct LayerTraits<armnnSerializer::Convolution3dLayer> {
+ static const Layer enum_value = Layer_Convolution3dLayer;
+};
+
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);
@@ -3227,6 +3246,254 @@ inline flatbuffers::Offset<Convolution2dDescriptor> CreateConvolution2dDescripto
return builder_.Finish();
}
+struct Convolution3dLayer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef Convolution3dLayerBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_BASE = 4,
+ VT_DESCRIPTOR = 6,
+ VT_WEIGHTS = 8,
+ VT_BIASES = 10
+ };
+ const armnnSerializer::LayerBase *base() const {
+ return GetPointer<const armnnSerializer::LayerBase *>(VT_BASE);
+ }
+ const armnnSerializer::Convolution3dDescriptor *descriptor() const {
+ return GetPointer<const armnnSerializer::Convolution3dDescriptor *>(VT_DESCRIPTOR);
+ }
+ const armnnSerializer::ConstTensor *weights() const {
+ return GetPointer<const armnnSerializer::ConstTensor *>(VT_WEIGHTS);
+ }
+ const armnnSerializer::ConstTensor *biases() const {
+ return GetPointer<const armnnSerializer::ConstTensor *>(VT_BIASES);
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ VerifyOffset(verifier, VT_BASE) &&
+ verifier.VerifyTable(base()) &&
+ VerifyOffset(verifier, VT_DESCRIPTOR) &&
+ verifier.VerifyTable(descriptor()) &&
+ VerifyOffset(verifier, VT_WEIGHTS) &&
+ verifier.VerifyTable(weights()) &&
+ VerifyOffset(verifier, VT_BIASES) &&
+ verifier.VerifyTable(biases()) &&
+ verifier.EndTable();
+ }
+};
+
+struct Convolution3dLayerBuilder {
+ typedef Convolution3dLayer Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_base(flatbuffers::Offset<armnnSerializer::LayerBase> base) {
+ fbb_.AddOffset(Convolution3dLayer::VT_BASE, base);
+ }
+ void add_descriptor(flatbuffers::Offset<armnnSerializer::Convolution3dDescriptor> descriptor) {
+ fbb_.AddOffset(Convolution3dLayer::VT_DESCRIPTOR, descriptor);
+ }
+ void add_weights(flatbuffers::Offset<armnnSerializer::ConstTensor> weights) {
+ fbb_.AddOffset(Convolution3dLayer::VT_WEIGHTS, weights);
+ }
+ void add_biases(flatbuffers::Offset<armnnSerializer::ConstTensor> biases) {
+ fbb_.AddOffset(Convolution3dLayer::VT_BIASES, biases);
+ }
+ explicit Convolution3dLayerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ Convolution3dLayerBuilder &operator=(const Convolution3dLayerBuilder &);
+ flatbuffers::Offset<Convolution3dLayer> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Convolution3dLayer>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Convolution3dLayer> CreateConvolution3dLayer(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ flatbuffers::Offset<armnnSerializer::LayerBase> base = 0,
+ flatbuffers::Offset<armnnSerializer::Convolution3dDescriptor> descriptor = 0,
+ flatbuffers::Offset<armnnSerializer::ConstTensor> weights = 0,
+ flatbuffers::Offset<armnnSerializer::ConstTensor> biases = 0) {
+ Convolution3dLayerBuilder builder_(_fbb);
+ builder_.add_biases(biases);
+ builder_.add_weights(weights);
+ builder_.add_descriptor(descriptor);
+ builder_.add_base(base);
+ return builder_.Finish();
+}
+
+struct Convolution3dDescriptor FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+ typedef Convolution3dDescriptorBuilder Builder;
+ enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
+ VT_PADLEFT = 4,
+ VT_PADRIGHT = 6,
+ VT_PADTOP = 8,
+ VT_PADBOTTOM = 10,
+ VT_PADFRONT = 12,
+ VT_PADBACK = 14,
+ VT_STRIDEX = 16,
+ VT_STRIDEY = 18,
+ VT_STRIDEZ = 20,
+ VT_DILATIONX = 22,
+ VT_DILATIONY = 24,
+ VT_DILATIONZ = 26,
+ VT_BIASENABLED = 28,
+ VT_DATALAYOUT = 30
+ };
+ 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 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);
+ }
+ uint32_t dilationX() const {
+ return GetField<uint32_t>(VT_DILATIONX, 1);
+ }
+ uint32_t dilationY() const {
+ return GetField<uint32_t>(VT_DILATIONY, 1);
+ }
+ uint32_t dilationZ() const {
+ return GetField<uint32_t>(VT_DILATIONZ, 1);
+ }
+ bool biasEnabled() const {
+ return GetField<uint8_t>(VT_BIASENABLED, 0) != 0;
+ }
+ armnnSerializer::DataLayout dataLayout() const {
+ return static_cast<armnnSerializer::DataLayout>(GetField<int8_t>(VT_DATALAYOUT, 2));
+ }
+ bool Verify(flatbuffers::Verifier &verifier) const {
+ return VerifyTableStart(verifier) &&
+ 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_STRIDEX) &&
+ VerifyField<uint32_t>(verifier, VT_STRIDEY) &&
+ VerifyField<uint32_t>(verifier, VT_STRIDEZ) &&
+ VerifyField<uint32_t>(verifier, VT_DILATIONX) &&
+ VerifyField<uint32_t>(verifier, VT_DILATIONY) &&
+ VerifyField<uint32_t>(verifier, VT_DILATIONZ) &&
+ VerifyField<uint8_t>(verifier, VT_BIASENABLED) &&
+ VerifyField<int8_t>(verifier, VT_DATALAYOUT) &&
+ verifier.EndTable();
+ }
+};
+
+struct Convolution3dDescriptorBuilder {
+ typedef Convolution3dDescriptor Table;
+ flatbuffers::FlatBufferBuilder &fbb_;
+ flatbuffers::uoffset_t start_;
+ void add_padLeft(uint32_t padLeft) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_PADLEFT, padLeft, 0);
+ }
+ void add_padRight(uint32_t padRight) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_PADRIGHT, padRight, 0);
+ }
+ void add_padTop(uint32_t padTop) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_PADTOP, padTop, 0);
+ }
+ void add_padBottom(uint32_t padBottom) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_PADBOTTOM, padBottom, 0);
+ }
+ void add_padFront(uint32_t padFront) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_PADFRONT, padFront, 0);
+ }
+ void add_padBack(uint32_t padBack) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_PADBACK, padBack, 0);
+ }
+ void add_strideX(uint32_t strideX) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_STRIDEX, strideX, 0);
+ }
+ void add_strideY(uint32_t strideY) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_STRIDEY, strideY, 0);
+ }
+ void add_strideZ(uint32_t strideZ) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_STRIDEZ, strideZ, 0);
+ }
+ void add_dilationX(uint32_t dilationX) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_DILATIONX, dilationX, 1);
+ }
+ void add_dilationY(uint32_t dilationY) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_DILATIONY, dilationY, 1);
+ }
+ void add_dilationZ(uint32_t dilationZ) {
+ fbb_.AddElement<uint32_t>(Convolution3dDescriptor::VT_DILATIONZ, dilationZ, 1);
+ }
+ void add_biasEnabled(bool biasEnabled) {
+ fbb_.AddElement<uint8_t>(Convolution3dDescriptor::VT_BIASENABLED, static_cast<uint8_t>(biasEnabled), 0);
+ }
+ void add_dataLayout(armnnSerializer::DataLayout dataLayout) {
+ fbb_.AddElement<int8_t>(Convolution3dDescriptor::VT_DATALAYOUT, static_cast<int8_t>(dataLayout), 2);
+ }
+ explicit Convolution3dDescriptorBuilder(flatbuffers::FlatBufferBuilder &_fbb)
+ : fbb_(_fbb) {
+ start_ = fbb_.StartTable();
+ }
+ Convolution3dDescriptorBuilder &operator=(const Convolution3dDescriptorBuilder &);
+ flatbuffers::Offset<Convolution3dDescriptor> Finish() {
+ const auto end = fbb_.EndTable(start_);
+ auto o = flatbuffers::Offset<Convolution3dDescriptor>(end);
+ return o;
+ }
+};
+
+inline flatbuffers::Offset<Convolution3dDescriptor> CreateConvolution3dDescriptor(
+ flatbuffers::FlatBufferBuilder &_fbb,
+ 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 strideX = 0,
+ uint32_t strideY = 0,
+ uint32_t strideZ = 0,
+ uint32_t dilationX = 1,
+ uint32_t dilationY = 1,
+ uint32_t dilationZ = 1,
+ bool biasEnabled = false,
+ armnnSerializer::DataLayout dataLayout = armnnSerializer::DataLayout_NDHWC) {
+ Convolution3dDescriptorBuilder builder_(_fbb);
+ builder_.add_dilationZ(dilationZ);
+ builder_.add_dilationY(dilationY);
+ builder_.add_dilationX(dilationX);
+ builder_.add_strideZ(strideZ);
+ builder_.add_strideY(strideY);
+ builder_.add_strideX(strideX);
+ 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_biasEnabled(biasEnabled);
+ return builder_.Finish();
+}
+
struct DepthToSpaceLayer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef DepthToSpaceLayerBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
@@ -9963,6 +10230,9 @@ struct AnyLayer FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const armnnSerializer::ChannelShuffleLayer *layer_as_ChannelShuffleLayer() const {
return layer_type() == armnnSerializer::Layer_ChannelShuffleLayer ? static_cast<const armnnSerializer::ChannelShuffleLayer *>(layer()) : nullptr;
}
+ const armnnSerializer::Convolution3dLayer *layer_as_Convolution3dLayer() const {
+ return layer_type() == armnnSerializer::Layer_Convolution3dLayer ? static_cast<const armnnSerializer::Convolution3dLayer *>(layer()) : nullptr;
+ }
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint8_t>(verifier, VT_LAYER_TYPE) &&
@@ -10232,6 +10502,10 @@ template<> inline const armnnSerializer::ChannelShuffleLayer *AnyLayer::layer_as
return layer_as_ChannelShuffleLayer();
}
+template<> inline const armnnSerializer::Convolution3dLayer *AnyLayer::layer_as<armnnSerializer::Convolution3dLayer>() const {
+ return layer_as_Convolution3dLayer();
+}
+
struct AnyLayerBuilder {
typedef AnyLayer Table;
flatbuffers::FlatBufferBuilder &fbb_;
@@ -10722,6 +10996,10 @@ inline bool VerifyLayer(flatbuffers::Verifier &verifier, const void *obj, Layer
auto ptr = reinterpret_cast<const armnnSerializer::ChannelShuffleLayer *>(obj);
return verifier.VerifyTable(ptr);
}
+ case Layer_Convolution3dLayer: {
+ auto ptr = reinterpret_cast<const armnnSerializer::Convolution3dLayer *>(obj);
+ return verifier.VerifyTable(ptr);
+ }
default: return true;
}
}
diff --git a/src/armnnSerializer/Serializer.cpp b/src/armnnSerializer/Serializer.cpp
index 9a3a270de5..efaf9f81cd 100644
--- a/src/armnnSerializer/Serializer.cpp
+++ b/src/armnnSerializer/Serializer.cpp
@@ -397,6 +397,54 @@ void SerializerStrategy::SerializeConvolution2dLayer(const armnn::IConnectableLa
CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_Convolution2dLayer);
}
+// Build FlatBuffer for Convolution2dLayer
+void SerializerStrategy::SerializeConvolution3dLayer(const armnn::IConnectableLayer* layer,
+ const armnn::Convolution3dDescriptor& descriptor,
+ const std::vector<armnn::ConstTensor>& constants,
+ const char* name)
+{
+ IgnoreUnused(name);
+
+ const armnn::ConstTensor weights = constants[0];
+
+ // Create FlatBuffer BaseLayer
+ auto flatBufferBaseLayer = CreateLayerBase(layer, serializer::LayerType::LayerType_Convolution2d);
+
+ auto flatBufferDescriptor = CreateConvolution3dDescriptor(m_flatBufferBuilder,
+ descriptor.m_PadLeft,
+ descriptor.m_PadRight,
+ descriptor.m_PadTop,
+ descriptor.m_PadBottom,
+ descriptor.m_PadFront,
+ descriptor.m_PadBack,
+ descriptor.m_StrideX,
+ descriptor.m_StrideY,
+ descriptor.m_StrideZ,
+ descriptor.m_DilationX,
+ descriptor.m_DilationY,
+ descriptor.m_DilationZ,
+ descriptor.m_BiasEnabled,
+ GetFlatBufferDataLayout(descriptor.m_DataLayout));
+ auto flatBufferWeightsConstTensorInfo = CreateConstTensorInfo(weights);
+ flatbuffers::Offset<serializer::ConstTensor> flatBufferBiasesConstTensorInfo;
+
+ if (constants.size() > 1)
+ {
+ const armnn::ConstTensor biases = constants[1];
+ flatBufferBiasesConstTensorInfo = CreateConstTensorInfo(biases);
+ }
+
+ // Create the FlatBuffer Convolution2dLayer
+ auto flatBufferLayer = CreateConvolution3dLayer(m_flatBufferBuilder,
+ flatBufferBaseLayer,
+ flatBufferDescriptor,
+ flatBufferWeightsConstTensorInfo,
+ flatBufferBiasesConstTensorInfo);
+
+ // Add the AnyLayer to the FlatBufferLayers
+ CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_Convolution3dLayer);
+}
+
void SerializerStrategy::SerializeDepthToSpaceLayer(const armnn::IConnectableLayer* layer,
const armnn::DepthToSpaceDescriptor& descriptor,
const char* name)
@@ -2054,6 +2102,16 @@ void SerializerStrategy::ExecuteStrategy(const armnn::IConnectableLayer* layer,
name);
break;
}
+ case armnn::LayerType::Convolution3d :
+ {
+ const armnn::Convolution3dDescriptor& layerDescriptor =
+ static_cast<const armnn::Convolution3dDescriptor&>(descriptor);
+ SerializeConvolution3dLayer(layer,
+ layerDescriptor,
+ constants,
+ name);
+ break;
+ }
case armnn::LayerType::DepthToSpace :
{
const armnn::DepthToSpaceDescriptor& layerDescriptor =
diff --git a/src/armnnSerializer/Serializer.hpp b/src/armnnSerializer/Serializer.hpp
index 43fb0f46b1..1161095c33 100644
--- a/src/armnnSerializer/Serializer.hpp
+++ b/src/armnnSerializer/Serializer.hpp
@@ -144,12 +144,17 @@ private:
const char* name = nullptr);
void SerializeConstantLayer(const armnn::IConnectableLayer* layer,
- const std::vector<armnn::ConstTensor>& contants,
+ const std::vector<armnn::ConstTensor>& constants,
const char* name = nullptr);
void SerializeConvolution2dLayer(const armnn::IConnectableLayer* layer,
const armnn::Convolution2dDescriptor& descriptor,
- const std::vector<armnn::ConstTensor>& contants,
+ const std::vector<armnn::ConstTensor>& constants,
+ const char* name = nullptr);
+
+ void SerializeConvolution3dLayer(const armnn::IConnectableLayer* layer,
+ const armnn::Convolution3dDescriptor& descriptor,
+ const std::vector<armnn::ConstTensor>& constants,
const char* name = nullptr);
void SerializeDepthToSpaceLayer(const armnn::IConnectableLayer* layer,
diff --git a/src/armnnSerializer/SerializerUtils.cpp b/src/armnnSerializer/SerializerUtils.cpp
index 85ce01d132..fca6db8449 100644
--- a/src/armnnSerializer/SerializerUtils.cpp
+++ b/src/armnnSerializer/SerializerUtils.cpp
@@ -97,6 +97,8 @@ armnnSerializer::DataLayout GetFlatBufferDataLayout(armnn::DataLayout dataLayout
{
case armnn::DataLayout::NHWC:
return armnnSerializer::DataLayout::DataLayout_NHWC;
+ case armnn::DataLayout::NDHWC:
+ return armnnSerializer::DataLayout::DataLayout_NDHWC;
case armnn::DataLayout::NCHW:
default:
return armnnSerializer::DataLayout::DataLayout_NCHW;
diff --git a/src/armnnSerializer/test/SerializerTests.cpp b/src/armnnSerializer/test/SerializerTests.cpp
index cd7fd5ca5b..2f8fd73717 100644
--- a/src/armnnSerializer/test/SerializerTests.cpp
+++ b/src/armnnSerializer/test/SerializerTests.cpp
@@ -439,6 +439,61 @@ TEST_CASE("SerializeConvolution2dWithPerAxisParams")
deserializedNetwork->ExecuteStrategy(verifier);
}
+TEST_CASE("SerializeConvolution3d")
+{
+ const std::string layerName("convolution3d");
+ const armnn::TensorInfo inputInfo ({ 1, 5, 5, 5, 1 }, armnn::DataType::Float32);
+ const armnn::TensorInfo outputInfo({ 1, 2, 2, 2, 1 }, armnn::DataType::Float32);
+
+ const armnn::TensorInfo weightsInfo({ 3, 3, 3, 1, 1 }, armnn::DataType::Float32);
+ const armnn::TensorInfo biasesInfo ({ 1 }, armnn::DataType::Float32);
+
+ 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::Convolution3dDescriptor descriptor;
+ descriptor.m_PadLeft = 0;
+ descriptor.m_PadRight = 0;
+ descriptor.m_PadTop = 0;
+ descriptor.m_PadBottom = 0;
+ descriptor.m_PadFront = 0;
+ descriptor.m_PadBack = 0;
+ descriptor.m_DilationX = 1;
+ descriptor.m_DilationY = 1;
+ descriptor.m_DilationZ = 1;
+ descriptor.m_StrideX = 2;
+ descriptor.m_StrideY = 2;
+ descriptor.m_StrideZ = 2;
+ descriptor.m_BiasEnabled = true;
+ descriptor.m_DataLayout = armnn::DataLayout::NDHWC;
+
+ armnn::INetworkPtr network = armnn::INetwork::Create();
+ armnn::IConnectableLayer* const inputLayer = network->AddInputLayer(0);
+ armnn::IConnectableLayer* const convLayer =
+ network->AddConvolution3dLayer(descriptor,
+ weights,
+ armnn::Optional<armnn::ConstTensor>(biases),
+ layerName.c_str());
+ armnn::IConnectableLayer* const outputLayer = network->AddOutputLayer(0);
+
+ inputLayer->GetOutputSlot(0).Connect(convLayer->GetInputSlot(0));
+ convLayer->GetOutputSlot(0).Connect(outputLayer->GetInputSlot(0));
+
+ inputLayer->GetOutputSlot(0).SetTensorInfo(inputInfo);
+ convLayer->GetOutputSlot(0).SetTensorInfo(outputInfo);
+
+ armnn::INetworkPtr deserializedNetwork = DeserializeNetwork(SerializeNetwork(*network));
+ CHECK(deserializedNetwork);
+
+ const std::vector<armnn::ConstTensor>& constants {weights, biases};
+ LayerVerifierBaseWithDescriptorAndConstants<armnn::Convolution3dDescriptor> verifier(
+ layerName, {inputInfo}, {outputInfo}, descriptor, constants);
+ deserializedNetwork->ExecuteStrategy(verifier);
+}
+
TEST_CASE("SerializeDepthToSpace")
{
const std::string layerName("depthToSpace");