From dd6247f52dcb33bd03391b7ee573d7082e18cca7 Mon Sep 17 00:00:00 2001 From: Aron Virginas-Tar Date: Thu, 19 Sep 2019 14:31:17 +0100 Subject: IVGCVSW-3883 Add frontend for DepthToSpace layer Signed-off-by: Aron Virginas-Tar Change-Id: I18d957af6e988ffb6b9ee46ac836d1f38600e10b --- Android.mk | 1 + CMakeLists.txt | 2 + include/armnn/Descriptors.hpp | 12 +++- include/armnn/DescriptorsFwd.hpp | 2 + include/armnn/ILayerSupport.hpp | 5 ++ include/armnn/ILayerVisitor.hpp | 8 +++ include/armnn/INetwork.hpp | 7 ++ include/armnn/LayerVisitorBase.hpp | 4 ++ src/armnn/InternalTypes.cpp | 1 + src/armnn/InternalTypes.hpp | 1 + src/armnn/LayersFwd.hpp | 2 + src/armnn/Network.cpp | 6 ++ src/armnn/Network.hpp | 3 + src/armnn/layers/DepthToSpaceLayer.cpp | 84 ++++++++++++++++++++++ src/armnn/layers/DepthToSpaceLayer.hpp | 50 +++++++++++++ src/armnn/test/TestNameOnlyLayerVisitor.cpp | 1 + src/armnn/test/TestNameOnlyLayerVisitor.hpp | 1 + src/armnnSerializer/Serializer.cpp | 7 ++ src/armnnSerializer/Serializer.hpp | 4 ++ src/backends/backendsCommon/LayerSupportBase.cpp | 8 +++ src/backends/backendsCommon/LayerSupportBase.hpp | 5 ++ src/backends/backendsCommon/WorkloadData.cpp | 51 +++++++++++++ src/backends/backendsCommon/WorkloadData.hpp | 5 ++ src/backends/backendsCommon/WorkloadFactory.cpp | 19 +++++ src/backends/backendsCommon/WorkloadFactory.hpp | 3 + .../test/IsLayerSupportedTestImpl.hpp | 2 + 26 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 src/armnn/layers/DepthToSpaceLayer.cpp create mode 100644 src/armnn/layers/DepthToSpaceLayer.hpp diff --git a/Android.mk b/Android.mk index 89956ddad1..3e665a039f 100644 --- a/Android.mk +++ b/Android.mk @@ -124,6 +124,7 @@ LOCAL_SRC_FILES := \ src/armnn/layers/ConvertFp16ToFp32Layer.cpp \ src/armnn/layers/ConvertFp32ToFp16Layer.cpp \ src/armnn/layers/DebugLayer.cpp \ + src/armnn/layers/DepthToSpaceLayer.cpp \ src/armnn/layers/DepthwiseConvolution2dLayer.cpp \ src/armnn/layers/DequantizeLayer.cpp \ src/armnn/layers/DetectionPostProcessLayer.cpp \ diff --git a/CMakeLists.txt b/CMakeLists.txt index a5c63e45cd..6556c102bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -256,6 +256,8 @@ list(APPEND armnn_sources src/armnn/layers/ConvertFp32ToFp16Layer.cpp src/armnn/layers/DebugLayer.hpp src/armnn/layers/DebugLayer.cpp + src/armnn/layers/DepthToSpaceLayer.hpp + src/armnn/layers/DepthToSpaceLayer.cpp src/armnn/layers/DepthwiseConvolution2dLayer.hpp src/armnn/layers/DepthwiseConvolution2dLayer.cpp src/armnn/layers/DequantizeLayer.hpp diff --git a/include/armnn/Descriptors.hpp b/include/armnn/Descriptors.hpp index 686536f53e..c973089df6 100644 --- a/include/armnn/Descriptors.hpp +++ b/include/armnn/Descriptors.hpp @@ -589,16 +589,24 @@ struct SpaceToBatchNdDescriptor struct SpaceToDepthDescriptor { SpaceToDepthDescriptor() - : m_BlockSize(1u) - , m_DataLayout(DataLayout::NHWC) + : SpaceToDepthDescriptor(1u, DataLayout::NHWC) + {} + + SpaceToDepthDescriptor(unsigned int blockSize, DataLayout dataLayout) + : m_BlockSize(blockSize) + , m_DataLayout(dataLayout) {} /// Scalar specifying the input block size. It must be >= 1 unsigned int m_BlockSize; + /// The data layout to be used (NCHW, NHWC). DataLayout m_DataLayout; }; +/// A DepthToSpaceDescriptor for the DepthToSpaceLayer +using DepthToSpaceDescriptor = SpaceToDepthDescriptor; + /// An LstmDescriptor for the LstmLayer. struct LstmDescriptor { diff --git a/include/armnn/DescriptorsFwd.hpp b/include/armnn/DescriptorsFwd.hpp index bddb0cad59..e9624f18ce 100644 --- a/include/armnn/DescriptorsFwd.hpp +++ b/include/armnn/DescriptorsFwd.hpp @@ -37,6 +37,8 @@ struct StridedSliceDescriptor; struct TransposeConvolution2dDescriptor; struct ViewsDescriptor; +using DepthToSpaceDescriptor = SpaceToDepthDescriptor; + // MergerDescriptor is deprecated use ConcatDescriptor instead using MergerDescriptor = OriginsDescriptor; using ConcatDescriptor = OriginsDescriptor; diff --git a/include/armnn/ILayerSupport.hpp b/include/armnn/ILayerSupport.hpp index cab2df19af..e18b86acfd 100644 --- a/include/armnn/ILayerSupport.hpp +++ b/include/armnn/ILayerSupport.hpp @@ -88,6 +88,11 @@ public: const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const = 0; + virtual bool IsDepthToSpaceSupported(const TensorInfo& input, + const TensorInfo& output, + const DepthToSpaceDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const = 0; + virtual bool IsDepthwiseConvolutionSupported( const TensorInfo& input, const TensorInfo& output, diff --git a/include/armnn/ILayerVisitor.hpp b/include/armnn/ILayerVisitor.hpp index 6c0977303c..486a13f847 100644 --- a/include/armnn/ILayerVisitor.hpp +++ b/include/armnn/ILayerVisitor.hpp @@ -115,6 +115,14 @@ public: const Optional& biases, const char* name = nullptr) = 0; + /// Function a depth to space layer should call back to when its Accept(ILayerVisitor&) function is invoked. + /// @param layer - pointer to the layer which is calling back to this visit function. + /// @param depthToSpaceDescriptor - Parameters for the depth to space operation. + /// @param name - Optional name for the layer. + virtual void VisitDepthToSpaceLayer(const IConnectableLayer* layer, + const DepthToSpaceDescriptor& depthToSpaceDescriptor, + const char* name = nullptr) = 0; + /// Function that a 2D depthwise convolution layer with biases should call back to when its /// Accept(ILayerVisitor&) function is invoked. /// @param layer - pointer to the layer which is calling back to this visit function. diff --git a/include/armnn/INetwork.hpp b/include/armnn/INetwork.hpp index 09026ad9e6..0e0b99a718 100644 --- a/include/armnn/INetwork.hpp +++ b/include/armnn/INetwork.hpp @@ -141,6 +141,13 @@ public: const ConstTensor& biases, const char* name = nullptr) = 0; + /// Adds a depth to space layer to the network. + /// @param depthToSpaceDescriptor - Parameters for the depth to space operation. + /// @param name - Optional name for the layer. + /// @return - Interface for configuring the layer. + virtual IConnectableLayer* AddDepthToSpaceLayer(const DepthToSpaceDescriptor& depthToSpaceDescriptor, + const char* name = nullptr) = 0; + /// Adds a 2D depthwise convolution layer to the network. /// @param convolution2dDescriptor - Description of the 2D depthwise convolution layer. /// @param weights - Tensor for the weights. Expected format: [channelMultiplier, inputChannels, height, width]. diff --git a/include/armnn/LayerVisitorBase.hpp b/include/armnn/LayerVisitorBase.hpp index d626c712ba..65d23039b7 100644 --- a/include/armnn/LayerVisitorBase.hpp +++ b/include/armnn/LayerVisitorBase.hpp @@ -69,6 +69,10 @@ public: const Optional&, const char*) override { DefaultPolicy::Apply(__func__); } + void VisitDepthToSpaceLayer(const IConnectableLayer*, + const DepthToSpaceDescriptor&, + const char*) override { DefaultPolicy::Apply(__func__); } + void VisitDepthwiseConvolution2dLayer(const IConnectableLayer*, const DepthwiseConvolution2dDescriptor&, const ConstTensor&, diff --git a/src/armnn/InternalTypes.cpp b/src/armnn/InternalTypes.cpp index 600d80023f..e6f7367ab5 100644 --- a/src/armnn/InternalTypes.cpp +++ b/src/armnn/InternalTypes.cpp @@ -26,6 +26,7 @@ char const* GetLayerTypeAsCString(LayerType type) case LayerType::ConvertFp32ToFp16: return "ConvertFp32ToFp16"; case LayerType::Convolution2d: return "Convolution2d"; case LayerType::Debug: return "Debug"; + case LayerType::DepthToSpace: return "DepthToSpace"; case LayerType::DepthwiseConvolution2d: return "DepthwiseConvolution2d"; case LayerType::Dequantize: return "Dequantize"; case LayerType::DetectionPostProcess: return "DetectionPostProcess"; diff --git a/src/armnn/InternalTypes.hpp b/src/armnn/InternalTypes.hpp index 1e05fff769..fbca9bcbcb 100644 --- a/src/armnn/InternalTypes.hpp +++ b/src/armnn/InternalTypes.hpp @@ -26,6 +26,7 @@ enum class LayerType ConvertFp32ToFp16, Convolution2d, Debug, + DepthToSpace, DepthwiseConvolution2d, Dequantize, DetectionPostProcess, diff --git a/src/armnn/LayersFwd.hpp b/src/armnn/LayersFwd.hpp index a98c104f85..3599eacf7d 100644 --- a/src/armnn/LayersFwd.hpp +++ b/src/armnn/LayersFwd.hpp @@ -18,6 +18,7 @@ #include "layers/ConvertFp32ToFp16Layer.hpp" #include "layers/Convolution2dLayer.hpp" #include "layers/DebugLayer.hpp" +#include "layers/DepthToSpaceLayer.hpp" #include "layers/DepthwiseConvolution2dLayer.hpp" #include "layers/DequantizeLayer.hpp" #include "layers/DetectionPostProcessLayer.hpp" @@ -100,6 +101,7 @@ DECLARE_LAYER(ConvertFp16ToFp32) DECLARE_LAYER(ConvertFp32ToFp16) DECLARE_LAYER(Convolution2d) DECLARE_LAYER(Debug) +DECLARE_LAYER(DepthToSpace) DECLARE_LAYER(DepthwiseConvolution2d) DECLARE_LAYER(Dequantize) DECLARE_LAYER(DetectionPostProcess) diff --git a/src/armnn/Network.cpp b/src/armnn/Network.cpp index c055407b3a..a668274c4d 100644 --- a/src/armnn/Network.cpp +++ b/src/armnn/Network.cpp @@ -1060,6 +1060,12 @@ IConnectableLayer* Network::AddDepthwiseConvolution2dLayerImpl( return layer; } +IConnectableLayer* Network::AddDepthToSpaceLayer(const DepthToSpaceDescriptor& depthToSpaceDescriptor, + const char* name) +{ + return m_Graph->AddLayer(depthToSpaceDescriptor, name); +} + IConnectableLayer* Network::AddDepthwiseConvolution2dLayer( const DepthwiseConvolution2dDescriptor& convolution2dDescriptor, const ConstTensor& weights, diff --git a/src/armnn/Network.hpp b/src/armnn/Network.hpp index 274cc1ab7c..4a8bfbc9f2 100644 --- a/src/armnn/Network.hpp +++ b/src/armnn/Network.hpp @@ -61,6 +61,9 @@ public: const ConstTensor& biases, const char* name = nullptr) override; + IConnectableLayer* AddDepthToSpaceLayer(const DepthToSpaceDescriptor& depthToSpaceDescriptor, + const char* name = nullptr) override; + IConnectableLayer* AddDepthwiseConvolution2dLayer( const DepthwiseConvolution2dDescriptor& convolution2dDescriptor, const ConstTensor& weights, diff --git a/src/armnn/layers/DepthToSpaceLayer.cpp b/src/armnn/layers/DepthToSpaceLayer.cpp new file mode 100644 index 0000000000..e964c32865 --- /dev/null +++ b/src/armnn/layers/DepthToSpaceLayer.cpp @@ -0,0 +1,84 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "DepthToSpaceLayer.hpp" + +#include "LayerCloneBase.hpp" + +#include + +#include +#include + +#include + +#include + +namespace armnn +{ + +DepthToSpaceLayer::DepthToSpaceLayer(const DepthToSpaceDescriptor& param, const char* name) + : LayerWithParameters(1, 1, LayerType::DepthToSpace, param, name) +{} + +std::unique_ptr DepthToSpaceLayer::CreateWorkload(const Graph& graph, + const IWorkloadFactory& factory) const +{ + DepthToSpaceQueueDescriptor descriptor; + descriptor.m_Parameters.m_BlockSize = m_Param.m_BlockSize; + descriptor.m_Parameters.m_DataLayout = m_Param.m_DataLayout; + + return factory.CreateDepthToSpace(descriptor, PrepInfoAndDesc(descriptor, graph)); +} + +DepthToSpaceLayer* DepthToSpaceLayer::Clone(Graph& graph) const +{ + return CloneBase(graph, m_Param, GetName()); +} + +std::vector DepthToSpaceLayer::InferOutputShapes(const std::vector& inputShapes) const +{ + throw UnimplementedException("DepthToSpaceLayer::InferOutputShapes is not implemented"); + + BOOST_ASSERT(inputShapes.size() == 1); + + TensorShape inputShape = inputShapes[0]; + TensorShape outputShape(inputShape); + + armnnUtils::DataLayoutIndexed dimensionIndices(m_Param.m_DataLayout); + + unsigned int hIndex = dimensionIndices.GetHeightIndex(); + unsigned int wIndex = dimensionIndices.GetWidthIndex(); + unsigned int cIndex = dimensionIndices.GetChannelsIndex(); + + outputShape[hIndex] = inputShape[hIndex] * m_Param.m_BlockSize; + outputShape[wIndex] = inputShape[wIndex] * m_Param.m_BlockSize; + + outputShape[cIndex] = inputShape[cIndex] / (m_Param.m_BlockSize * m_Param.m_BlockSize); + + return std::vector({ outputShape }); +} + +void DepthToSpaceLayer::ValidateTensorShapesFromInputs() +{ + VerifyLayerConnections(1, CHECK_LOCATION()); + + std::vector inferredShapes = InferOutputShapes({ + GetInputSlot(0).GetConnection()->GetTensorInfo().GetShape() }); + + BOOST_ASSERT(inferredShapes.size() == 1); + + ConditionalThrowIfNotEqual( + "DepthToSpaceLayer: TensorShape set on OutputSlot[0] does not match the inferred shape.", + GetOutputSlot(0).GetTensorInfo().GetShape(), + inferredShapes[0]); +} + +void DepthToSpaceLayer::Accept(ILayerVisitor& visitor) const +{ + visitor.VisitDepthToSpaceLayer(this, GetParameters(), GetName()); +} + +} // namespace armnn diff --git a/src/armnn/layers/DepthToSpaceLayer.hpp b/src/armnn/layers/DepthToSpaceLayer.hpp new file mode 100644 index 0000000000..cc5abe4cc9 --- /dev/null +++ b/src/armnn/layers/DepthToSpaceLayer.hpp @@ -0,0 +1,50 @@ +// +// Copyright © 2019 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include "LayerWithParameters.hpp" + +namespace armnn +{ + +/// This layer represents a DepthToSpace operation. +class DepthToSpaceLayer : public LayerWithParameters +{ +public: + /// Makes a workload for the DepthToSpace type. + /// @param [in] graph The graph where this layer can be found. + /// @param [in] factory The workload factory which will create the workload. + /// @return A pointer to the created workload, or nullptr if not created. + virtual std::unique_ptr CreateWorkload(const Graph& graph, + const IWorkloadFactory& factory) const override; + + /// Creates a dynamically-allocated copy of this layer. + /// @param [in] graph The graph into which this layer is being cloned. + DepthToSpaceLayer* Clone(Graph& graph) const override; + + /// By default returns inputShapes if the number of inputs are equal to number of outputs, + /// otherwise infers the output shapes from given input shapes and layer properties. + /// @param [in] inputShapes The input shapes layer has. + /// @return A vector to the inferred output shape. + std::vector InferOutputShapes(const std::vector& inputShapes) const override; + + /// Check if the input tensor shape(s) + /// will lead to a valid configuration of @ref DepthToSpaceLayer. + void ValidateTensorShapesFromInputs() override; + + void Accept(ILayerVisitor& visitor) const override; + +protected: + /// Constructor to create a DepthToSpaceLayer. + /// @param [in] param DepthToSpaceDescriptor to configure the DepthToSpaceLayer operation. + /// @param [in] name Optional name for the layer. + DepthToSpaceLayer(const DepthToSpaceDescriptor& param, const char* name); + + /// Default destructor + ~DepthToSpaceLayer() = default; +}; + +} // namespace armnn diff --git a/src/armnn/test/TestNameOnlyLayerVisitor.cpp b/src/armnn/test/TestNameOnlyLayerVisitor.cpp index c738caeb1f..2217a32edf 100644 --- a/src/armnn/test/TestNameOnlyLayerVisitor.cpp +++ b/src/armnn/test/TestNameOnlyLayerVisitor.cpp @@ -49,6 +49,7 @@ TEST_CASE_CHECK_LAYER_VISITOR_NAME_NULLPTR(name, 2) BOOST_AUTO_TEST_SUITE(TestNameOnlyLayerVisitor) TEST_SUITE_NAME_ONLY_LAYER_VISITOR_1_PARAM(Addition) +TEST_SUITE_NAME_ONLY_LAYER_VISITOR_2_PARAM(DepthToSpace) TEST_SUITE_NAME_ONLY_LAYER_VISITOR_1_PARAM(Division) TEST_SUITE_NAME_ONLY_LAYER_VISITOR_1_PARAM(Equal) TEST_SUITE_NAME_ONLY_LAYER_VISITOR_1_PARAM(Floor) diff --git a/src/armnn/test/TestNameOnlyLayerVisitor.hpp b/src/armnn/test/TestNameOnlyLayerVisitor.hpp index 1c5ede0802..4e0aa2f989 100644 --- a/src/armnn/test/TestNameOnlyLayerVisitor.hpp +++ b/src/armnn/test/TestNameOnlyLayerVisitor.hpp @@ -45,6 +45,7 @@ public: \ } // anonymous namespace TEST_LAYER_VISITOR_1_PARAM(Addition) +TEST_LAYER_VISITOR_2_PARAM(DepthToSpace) TEST_LAYER_VISITOR_1_PARAM(Division) TEST_LAYER_VISITOR_1_PARAM(Equal) TEST_LAYER_VISITOR_1_PARAM(Floor) diff --git a/src/armnnSerializer/Serializer.cpp b/src/armnnSerializer/Serializer.cpp index 16b7cff808..f07805cb38 100644 --- a/src/armnnSerializer/Serializer.cpp +++ b/src/armnnSerializer/Serializer.cpp @@ -299,6 +299,13 @@ void SerializerVisitor::VisitConvolution2dLayer(const armnn::IConnectableLayer* CreateAnyLayer(flatBufferLayer.o, serializer::Layer::Layer_Convolution2dLayer); } +void SerializerVisitor::VisitDepthToSpaceLayer(const armnn::IConnectableLayer* layer, + const armnn::DepthToSpaceDescriptor& descriptor, + const char* name) +{ + throw UnimplementedException("SerializerVisitor::VisitDepthToSpaceLayer is not implemented"); +} + void SerializerVisitor::VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer, const armnn::DepthwiseConvolution2dDescriptor& descriptor, const armnn::ConstTensor& weights, diff --git a/src/armnnSerializer/Serializer.hpp b/src/armnnSerializer/Serializer.hpp index 8e65902002..429487da2b 100644 --- a/src/armnnSerializer/Serializer.hpp +++ b/src/armnnSerializer/Serializer.hpp @@ -82,6 +82,10 @@ public: const armnn::Optional& biases, const char* = nullptr) override; + void VisitDepthToSpaceLayer(const armnn::IConnectableLayer* layer, + const armnn::DepthToSpaceDescriptor& descriptor, + const char* name = nullptr) override; + void VisitDepthwiseConvolution2dLayer(const armnn::IConnectableLayer* layer, const armnn::DepthwiseConvolution2dDescriptor& descriptor, const armnn::ConstTensor& weights, diff --git a/src/backends/backendsCommon/LayerSupportBase.cpp b/src/backends/backendsCommon/LayerSupportBase.cpp index 7f1fd1097a..656407d020 100644 --- a/src/backends/backendsCommon/LayerSupportBase.cpp +++ b/src/backends/backendsCommon/LayerSupportBase.cpp @@ -129,6 +129,14 @@ bool LayerSupportBase::IsDebugSupported(const TensorInfo& input, return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); } +bool LayerSupportBase::IsDepthToSpaceSupported(const TensorInfo& input, + const TensorInfo& output, + const DepthToSpaceDescriptor& descriptor, + Optional reasonIfUnsupported) const +{ + return DefaultLayerSupport(__func__, __FILE__, __LINE__, reasonIfUnsupported); +} + bool LayerSupportBase::IsDepthwiseConvolutionSupported(const TensorInfo& input, const TensorInfo& output, const DepthwiseConvolution2dDescriptor& descriptor, diff --git a/src/backends/backendsCommon/LayerSupportBase.hpp b/src/backends/backendsCommon/LayerSupportBase.hpp index 8df1f8d54f..c3875e6ced 100644 --- a/src/backends/backendsCommon/LayerSupportBase.hpp +++ b/src/backends/backendsCommon/LayerSupportBase.hpp @@ -74,6 +74,11 @@ public: const TensorInfo& output, Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsDepthToSpaceSupported(const TensorInfo& input, + const TensorInfo& output, + const DepthToSpaceDescriptor& descriptor, + Optional reasonIfUnsupported = EmptyOptional()) const override; + bool IsDepthwiseConvolutionSupported(const TensorInfo& input, const TensorInfo& output, const DepthwiseConvolution2dDescriptor& descriptor, diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp index c8c4f9aae4..52d14097af 100644 --- a/src/backends/backendsCommon/WorkloadData.cpp +++ b/src/backends/backendsCommon/WorkloadData.cpp @@ -2642,4 +2642,55 @@ void SliceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const } } +void DepthToSpaceQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const +{ + const std::string descriptorName{"DepthToSpaceQueueDescriptor"}; + + ValidateNumInputs(workloadInfo, descriptorName, 1); + ValidateNumOutputs(workloadInfo, descriptorName, 1); + + const TensorInfo& inputInfo = workloadInfo.m_InputTensorInfos[0]; + const TensorInfo& outputInfo = workloadInfo.m_OutputTensorInfos[0]; + + ValidateTensorNumDimensions(inputInfo, descriptorName, 4, "input"); + ValidateTensorNumDimensions(outputInfo, descriptorName, 4, "output"); + + std::vector supportedTypes = + { + DataType::Float32, + DataType::Float16, + DataType::QuantisedAsymm8, + DataType::QuantisedSymm16 + }; + + ValidateDataTypes(inputInfo, supportedTypes, descriptorName); + ValidateDataTypes(outputInfo, supportedTypes, descriptorName); + + ValidateTensorNumElementsMatch(inputInfo, outputInfo, descriptorName, "input", "output"); + + if (m_Parameters.m_BlockSize == 0) + { + throw InvalidArgumentException(descriptorName + ": Block size cannot be 0."); + } + + DataLayoutIndexed dimensionIndices(m_Parameters.m_DataLayout); + const unsigned int wIndex = dimensionIndices.GetWidthIndex(); + const unsigned int hIndex = dimensionIndices.GetHeightIndex(); + const unsigned int cIndex = dimensionIndices.GetChannelsIndex(); + + const TensorShape& outputShape = outputInfo.GetShape(); + if (outputShape[hIndex] % m_Parameters.m_BlockSize != 0 || outputShape[wIndex] % m_Parameters.m_BlockSize != 0) + { + throw InvalidArgumentException(descriptorName + ": Output width and height shape" + "must be divisible by block size."); + } + + const TensorShape& inputShape = inputInfo.GetShape(); + if (inputShape[cIndex] % (m_Parameters.m_BlockSize * m_Parameters.m_BlockSize) != 0) + { + throw InvalidArgumentException(descriptorName + ": The depth of the input tensor" + "must be divisible by the square of block size." ); + } +} + } // namespace armnn diff --git a/src/backends/backendsCommon/WorkloadData.hpp b/src/backends/backendsCommon/WorkloadData.hpp index 1e49243b34..177bfb7af3 100644 --- a/src/backends/backendsCommon/WorkloadData.hpp +++ b/src/backends/backendsCommon/WorkloadData.hpp @@ -538,4 +538,9 @@ struct SliceQueueDescriptor : QueueDescriptorWithParameters void Validate(const WorkloadInfo& workloadInfo) const; }; +struct DepthToSpaceQueueDescriptor : QueueDescriptorWithParameters +{ + void Validate(const WorkloadInfo& workloadInfo) const; +}; + } // namespace armnn diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp index 9d6b2bd6a9..44888b3ac9 100644 --- a/src/backends/backendsCommon/WorkloadFactory.cpp +++ b/src/backends/backendsCommon/WorkloadFactory.cpp @@ -206,6 +206,19 @@ bool IWorkloadFactory::IsLayerSupported(const BackendId& backendId, reason); break; } + case LayerType::DepthToSpace: + { + auto cLayer = boost::polymorphic_downcast(&layer); + + const TensorInfo& input = layer.GetInputSlot(0).GetConnection()->GetTensorInfo(); + const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo(); + + result = layerSupportObject->IsDepthToSpaceSupported(OverrideDataType(input, dataType), + OverrideDataType(output, dataType), + cLayer->GetParameters(), + reason); + break; + } case LayerType::DepthwiseConvolution2d: { auto cLayer = boost::polymorphic_downcast(&layer); @@ -1060,6 +1073,12 @@ std::unique_ptr IWorkloadFactory::CreateDebug(const DebugQueueDescrip return std::unique_ptr(); } +std::unique_ptr IWorkloadFactory::CreateDepthToSpace(const DepthToSpaceQueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + return std::unique_ptr(); +} + std::unique_ptr IWorkloadFactory::CreateDepthwiseConvolution2d( const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const { diff --git a/src/backends/backendsCommon/WorkloadFactory.hpp b/src/backends/backendsCommon/WorkloadFactory.hpp index 91cf2c742c..29ebe2af48 100644 --- a/src/backends/backendsCommon/WorkloadFactory.hpp +++ b/src/backends/backendsCommon/WorkloadFactory.hpp @@ -85,6 +85,9 @@ public: virtual std::unique_ptr CreateDebug(const DebugQueueDescriptor& descriptor, const WorkloadInfo& info) const; + virtual std::unique_ptr CreateDepthToSpace(const DepthToSpaceQueueDescriptor& descriptor, + const WorkloadInfo& info) const; + virtual std::unique_ptr CreateDepthwiseConvolution2d( const DepthwiseConvolution2dQueueDescriptor& descriptor, const WorkloadInfo& info) const; diff --git a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp index 17b7934e9f..e492cd6908 100644 --- a/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp +++ b/src/backends/backendsCommon/test/IsLayerSupportedTestImpl.hpp @@ -413,6 +413,8 @@ DECLARE_LAYER_POLICY_1_PARAM(MemImport) DECLARE_LAYER_POLICY_1_PARAM(Debug) +DECLARE_LAYER_POLICY_2_PARAM(DepthToSpace) + DECLARE_LAYER_POLICY_2_PARAM(DepthwiseConvolution2d) DECLARE_LAYER_POLICY_1_PARAM(Dequantize) -- cgit v1.2.1