Release 18.05.01
[platform/upstream/armnn.git] / src / armnn / layers / DepthwiseConvolution2dLayer.cpp
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // See LICENSE file in the project root for full license information.
4 //
5 #include "DepthwiseConvolution2dLayer.hpp"
6
7 #include "LayerCloneBase.hpp"
8
9 #include <armnn/TypesUtils.hpp>
10 #include <backends/CpuTensorHandle.hpp>
11 #include <backends/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     DepthwiseConvolution2dQueueDescriptor descriptor;
26
27     descriptor.m_Weight = m_Weight.get();
28     if (m_Param.m_BiasEnabled)
29     {
30         descriptor.m_Bias = m_Bias.get();
31     }
32     return factory.CreateDepthwiseConvolution2d(descriptor, PrepInfoAndDesc(descriptor, graph));
33 }
34
35 DepthwiseConvolution2dLayer* DepthwiseConvolution2dLayer::Clone(Graph& graph) const
36 {
37     auto layer      = CloneBase<DepthwiseConvolution2dLayer>(graph, m_Param, GetName());
38     layer->m_Weight = m_Weight ? std::make_unique<ScopedCpuTensorHandle>(*m_Weight) : nullptr;
39
40     if (layer->m_Param.m_BiasEnabled)
41     {
42         layer->m_Bias = m_Bias ? std::make_unique<ScopedCpuTensorHandle>(*m_Bias) : nullptr;
43     }
44
45     return std::move(layer);
46 }
47
48 void DepthwiseConvolution2dLayer::ValidateTensorShapesFromInputs()
49 {
50     ConditionalThrow<LayerValidationException>(GetInputSlot(0).GetConnection() != nullptr,
51                      "DepthwiseConvolution2dLayer: InputSlot must be connected to an OutputSlot");
52     ConditionalThrow<LayerValidationException>(GetInputSlot(0).GetConnection()->IsTensorInfoSet(),
53                      "DepthwiseConvolution2dLayer: TensorInfo must be set on connected OutputSlot.");
54
55     IOutputSlot* input = GetInputSlot(0).GetConnection();
56     const TensorShape& inputShape = input->GetTensorInfo().GetShape();
57     const TensorShape filterShape = m_Weight->GetTensorInfo().GetShape();
58
59     BOOST_ASSERT_MSG(inputShape.GetNumDimensions() == 4, "Convolutions will always have 4D input.");
60
61     unsigned int inWidth = inputShape[3];
62     unsigned int inHeight = inputShape[2];
63     unsigned int inBatchSize = inputShape[0];
64
65     unsigned int filterWidth = filterShape[3];
66     unsigned int readWidth = (inWidth + m_Param.m_PadLeft + m_Param.m_PadRight) - (filterWidth);
67     unsigned int outWidth =  1+(readWidth / m_Param.m_StrideX);
68
69     unsigned int filterHeight = filterShape[2];
70     unsigned int readHeight = (inHeight + m_Param.m_PadTop + m_Param.m_PadBottom) - (filterHeight);
71     unsigned int outHeight = 1+(readHeight / m_Param.m_StrideY);
72     unsigned int depthMultiplier = filterShape[0];
73
74     unsigned int outChannels = filterShape[1]*depthMultiplier;
75     unsigned int outBatchSize = inBatchSize;
76
77     TensorShape outShape({outBatchSize, outChannels, outHeight, outWidth});
78     ConditionalThrowIfNotEqual<LayerValidationException>(
79         "DepthwiseConvolution2dLayer: "
80         "TensorShape set on OutputSlot[0] does not match the inferred shape.",
81         GetOutputSlot(0).GetTensorInfo().GetShape(),
82         outShape);
83 }
84
85 } // namespace armnn