IVGCVSW-1946: Remove armnn/src from the include paths
[platform/upstream/armnn.git] / src / armnn / layers / DepthwiseConvolution2dLayer.cpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "DepthwiseConvolution2dLayer.hpp"
6
7 #include "LayerCloneBase.hpp"
8
9 #include <armnn/TypesUtils.hpp>
10 #include <backendsCommon/CpuTensorHandle.hpp>
11 #include <backendsCommon/WorkloadFactory.hpp>
12
13 namespace armnn
14 {
15
16 DepthwiseConvolution2dLayer::DepthwiseConvolution2dLayer(const DepthwiseConvolution2dDescriptor& param,
17                                                          const char* name)
18     : LayerWithParameters(1, 1, LayerType::DepthwiseConvolution2d, param, name)
19 {
20 }
21
22 std::unique_ptr<IWorkload> DepthwiseConvolution2dLayer::CreateWorkload(const Graph&                  graph,
23                                                                        const IWorkloadFactory& factory) const
24 {
25     // on this level constant data should not be released..
26     BOOST_ASSERT_MSG(m_Weight != nullptr, "DepthwiseConvolution2dLayer: Weights data should not be null.");
27
28     DepthwiseConvolution2dQueueDescriptor descriptor;
29
30     descriptor.m_Weight = m_Weight.get();
31
32     if (m_Param.m_BiasEnabled)
33     {
34         BOOST_ASSERT_MSG(m_Bias != nullptr, "DepthwiseConvolution2dLayer: Bias data should not be null.");
35         descriptor.m_Bias = m_Bias.get();
36     }
37     return factory.CreateDepthwiseConvolution2d(descriptor, PrepInfoAndDesc(descriptor, graph));
38 }
39
40 DepthwiseConvolution2dLayer* DepthwiseConvolution2dLayer::Clone(Graph& graph) const
41 {
42     auto layer      = CloneBase<DepthwiseConvolution2dLayer>(graph, m_Param, GetName());
43     layer->m_Weight = m_Weight ? std::make_unique<ScopedCpuTensorHandle>(*m_Weight) : nullptr;
44
45     if (layer->m_Param.m_BiasEnabled)
46     {
47         layer->m_Bias = m_Bias ? std::make_unique<ScopedCpuTensorHandle>(*m_Bias) : nullptr;
48     }
49
50     return std::move(layer);
51 }
52
53 std::vector<TensorShape>
54 DepthwiseConvolution2dLayer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
55 {
56     BOOST_ASSERT(inputShapes.size() == 2);
57     const TensorShape& inputShape = inputShapes[0];
58     const TensorShape filterShape = inputShapes[1];
59
60     BOOST_ASSERT_MSG(inputShape.GetNumDimensions() == 4, "Convolutions will always have 4D input.");
61
62     DataLayoutIndexed dataLayoutIndex(m_Param.m_DataLayout);
63
64     unsigned int inWidth = inputShape[dataLayoutIndex.GetWidthIndex()];
65     unsigned int inHeight = inputShape[dataLayoutIndex.GetHeightIndex()];
66     unsigned int inBatchSize = inputShape[0];
67
68     unsigned int filterWidth = filterShape[dataLayoutIndex.GetWidthIndex()];
69     unsigned int readWidth = (inWidth + m_Param.m_PadLeft + m_Param.m_PadRight) - (filterWidth);
70     unsigned int outWidth =  1 + (readWidth / m_Param.m_StrideX);
71
72     unsigned int filterHeight = filterShape[dataLayoutIndex.GetHeightIndex()];
73     unsigned int readHeight = (inHeight + m_Param.m_PadTop + m_Param.m_PadBottom) - (filterHeight);
74     unsigned int outHeight = 1 + (readHeight / m_Param.m_StrideY);
75     unsigned int depthMultiplier = filterShape[0];
76
77     unsigned int outChannels = filterShape[dataLayoutIndex.GetChannelsIndex()] * depthMultiplier;
78     unsigned int outBatchSize = inBatchSize;
79
80     TensorShape tensorShape = m_Param.m_DataLayout == armnn::DataLayout::NHWC ?
81         TensorShape( { outBatchSize, outHeight, outWidth, outChannels } ) :
82         TensorShape( { outBatchSize, outChannels, outHeight, outWidth });
83
84     return std::vector<TensorShape>({ tensorShape });
85 }
86
87 void DepthwiseConvolution2dLayer::ValidateTensorShapesFromInputs()
88 {
89     VerifyLayerConnections(1, CHECK_LOCATION());
90
91     // on this level constant data should not be released..
92     BOOST_ASSERT_MSG(m_Weight != nullptr, "DepthwiseConvolution2dLayer: Weights data should not be null.");
93
94     auto inferredShapes = InferOutputShapes({
95         GetInputSlot(0).GetConnection()->GetTensorInfo().GetShape(),
96         m_Weight->GetTensorInfo().GetShape()
97      });
98
99     BOOST_ASSERT(inferredShapes.size() == 1);
100
101     ConditionalThrowIfNotEqual<LayerValidationException>(
102         "DepthwiseConvolution2dLayer: TensorShape set on OutputSlot[0] does not match the inferred shape.",
103         GetOutputSlot(0).GetTensorInfo().GetShape(),
104         inferredShapes[0]);
105 }
106
107 Layer::ConstantTensors DepthwiseConvolution2dLayer::GetConstantTensorsByRef()
108 {
109     return {m_Weight, m_Bias};
110 }
111
112 } // namespace armnn