20{
22 "ConvertResizeToTosaOperator: Resize must have only one input." );
24 "ConvertResizeToTosaOperator: NCHW not supported.");
25
26 ResizeMode mode;
27 if (resizeDescriptor->
m_Method == ResizeMethod::NearestNeighbor)
28 {
29 mode = tosa::ResizeMode_NEAREST;
30 }
31 else if (resizeDescriptor->
m_Method == ResizeMethod::Bilinear)
32 {
33 mode = tosa::ResizeMode_BILINEAR;
34 }
35 else
36 {
38 }
39
40 std::string inputName = std::string("input_");
41 std::string outputName = std::string("output0_");
43
44
45
46 if(layer != nullptr)
47 {
50 }
51
52 int32_t inputHeight = static_cast<int32_t>(inputs[0]->GetShape()[1]);
53 int32_t inputWidth = static_cast<int32_t>(inputs[0]->GetShape()[2]);
54
55 int32_t outputHeight =
static_cast<int32_t
>(resizeDescriptor->
m_TargetHeight);
56 int32_t outputWidth =
static_cast<int32_t
>(resizeDescriptor->
m_TargetWidth);
59
60
61
62
63 auto preprocessResizeParameters = [&](int inputSize, int outputSize, int& scale_n, int& scale_d, int& offset)
64 {
65
66 if (inputSize == 1)
67 {
68 scale_n = outputSize;
69 scale_d = 1;
70 offset = 0;
71 return;
72 }
73
74
75
76 bool applyAligned = alignCorners && (outputSize > 1);
77 scale_n = applyAligned ? (outputSize - 1) : outputSize;
78 scale_d = applyAligned ? (inputSize - 1) : inputSize;
79
80
81 int gcd = std::gcd(scale_n, scale_d);
82 scale_n = 2 * scale_n / gcd;
83 scale_d = 2 * scale_d / gcd;
84
85
86 offset = halfPixel ? (scale_d / 2 - scale_n / 2) : 0;
87
88
89 if ((offset & 1) == 0)
90 {
91 scale_n /= 2;
92 scale_d /= 2;
93 offset /= 2;
94 }
95 };
96
97 int scale_y_n, scale_y_d, offset_y;
98 int scale_x_n, scale_x_d, offset_x;
99 preprocessResizeParameters(inputHeight, outputHeight, scale_y_n, scale_y_d, offset_y);
100 preprocessResizeParameters(inputWidth, outputWidth, scale_x_n, scale_x_d, offset_x);
101
102 int border_y = scale_y_d * (outputHeight - 1) - scale_y_n * (inputHeight - 1) + offset_y;
103 int border_x = scale_x_d * (outputWidth - 1) - scale_x_n * (inputWidth - 1) + offset_x;
104
105
106 std::vector<int16_t> scale = { static_cast<int16_t>(scale_y_n),
107 static_cast<int16_t>(scale_y_d),
108 static_cast<int16_t>(scale_x_n),
109 static_cast<int16_t>(scale_x_d) };
110
111
112 std::vector<int16_t> offset = { static_cast<int16_t>(offset_y),
113 static_cast<int16_t>(offset_x) };
114
115 std::vector<int16_t> border = { static_cast<int16_t>(border_y),
116 static_cast<int16_t>(border_x) };
117
118 auto isInt16Range = [](int x)
119 {
120 return (x <= std::numeric_limits<int16_t>::max()) && (x >= std::numeric_limits<int16_t>::min());
121 };
122
123 if (inputs[0]->IsQuantized())
124 {
125
126 if (!isInt16Range(scale_y_n) || !isInt16Range(scale_y_d) ||
127 !isInt16Range(scale_x_n) || !isInt16Range(scale_x_d) ||
128 !isInt16Range(offset_y) || !isInt16Range(offset_x) ||
129 !isInt16Range(border_y) || !isInt16Range(border_x))
130 {
131 throw armnn::Exception(
"ConvertResizeToTosaOperator: stride or offset out of 16 bit range");
132 }
133 }
134
135 TosaResizeAttribute resizeAttribute(scale, offset, border, mode);
136
137 std::vector<TosaSerializationTensor*> tensors;
138
139 DType inputDType =
ArmNNToDType(inputs[0]->GetDataType());
140 DType outputDType =
ArmNNToDType(outputs[0]->GetDataType());
141
142 if(inputs[0]->GetDataType() == DataType::QSymmS16 && mode == tosa::ResizeMode_BILINEAR)
143 {
144 throw armnn::Exception(
"ConvertResizeToTosaOperator(): Bilinear INT16 is not yet implemented.");
145 }
146
147 if (inputs[0]->GetDataType() == DataType::Signed32 && mode == tosa::ResizeMode_BILINEAR)
148 {
149 throw armnn::Exception(
"ConvertResizeToTosaOperator(): Bilinear INT32 is not supported.");
150 }
151
152
153
154
155 if (inputName.find("input_") != std::string::npos)
156 {
158
159 tensors.push_back(new TosaSerializationTensor(inputName, inputShape, inputDType, {}));
160 }
161
163
164 if (mode == tosa::ResizeMode_BILINEAR &&
165 inputDType == DType::DType_INT8 &&
166 outputDType == DType::DType_INT8)
167 {
168 std::string inoutResizeToRescale = std::string(
"inout_resize2rescale_bilinear_") +
GetUniqueTosaMappingID();
169
170
171
172 tensors.push_back(new TosaSerializationTensor(inoutResizeToRescale, outputShape, DType::DType_INT32, {}));
173
174 auto* resizeOp = new TosaSerializationOperator(Op_RESIZE,
175 Attribute_ResizeAttribute,
176 &resizeAttribute,
177 {inputName},
178 {inoutResizeToRescale});
179
180 tensors.push_back(new TosaSerializationTensor(outputName, outputShape, outputDType, {}));
181
182
183 double scale_bi { 1. / static_cast<double>(scale_y_n * scale_x_n) };
184
185 TosaSerializationOperator* rescaleOp {nullptr};
186
188 outputName,
189 scale_bi,
190 0,
191 0,
192 false,
193 false,
194 true,
195 true,
196 &rescaleOp);
197
198 return new TosaSerializationBasicBlock(blockName,
200 { resizeOp, rescaleOp },
201 tensors,
202 { inputName },
203 { outputName });
204 }
205 else
206 {
207 tensors.push_back(new TosaSerializationTensor(outputName, outputShape, outputDType, {}));
208
209 auto* op = new TosaSerializationOperator(Op_RESIZE,
210 Attribute_ResizeAttribute,
211 &resizeAttribute,
212 {inputName},
213 {outputName});
214
215
216
217 return new TosaSerializationBasicBlock(blockName,
219 {op},
220 tensors,
221 {inputName},
222 {outputName});
223 }
224}
#define ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(_cond, _str)
std::string GenerateUniqueOutputName(const Layer &layer, uint32_t layerSlot=0)
const std::string mainName
DType ArmNNToDType(const DataType &type)
std::string GenerateUniqueInputName(const armnn::InputSlot &slot)
std::string GetUniqueTosaMappingID()
std::vector< int32_t > GetTosaTensorShape(const TensorShape &shape)
void CreateRescaleTosaOperator(const std::string &inputName, const std::string &outputName, double scale, int32_t input_zp, int32_t output_zp, bool input_unsigned, bool output_unsigned, bool double_round, bool scale32, TosaSerializationOperator **op)
Creates a Tosa rescale operator.
Base class for all ArmNN exceptions so that users can filter to just those.
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
bool m_HalfPixelCenters
Half Pixel Centers.
uint32_t m_TargetHeight
Target height value.
DataLayout m_DataLayout
The data layout to be used (NCHW, NHWC).
ResizeMethod m_Method
The Interpolation method to use (Bilinear, NearestNeighbor).
uint32_t m_TargetWidth
Target width value.
bool m_AlignCorners
Aligned corners.