16 const std::vector<const TensorInfo*>& inputs,
17 const std::vector<const TensorInfo*>& outputs,
21 "ConvertResizeToTosaOperator: Resize must have only one input." );
23 "ConvertResizeToTosaOperator: NCHW not supported.");
26 if (resizeDescriptor->
m_Method == ResizeMethod::NearestNeighbor)
28 mode = tosa::ResizeMode_NEAREST;
30 else if (resizeDescriptor->
m_Method == ResizeMethod::Bilinear)
32 mode = tosa::ResizeMode_BILINEAR;
40 std::string inputName = std::string(
"input_");
41 std::string outputName = std::string(
"output0_");
52 int32_t inputHeight =
static_cast<int32_t
>(inputs[0]->GetShape()[1]);
53 int32_t inputWidth =
static_cast<int32_t
>(inputs[0]->GetShape()[2]);
55 int32_t outputHeight =
static_cast<int32_t
>(resizeDescriptor->
m_TargetHeight);
56 int32_t outputWidth =
static_cast<int32_t
>(resizeDescriptor->
m_TargetWidth);
63 auto preprocessResizeParameters = [&](
int inputSize,
int outputSize,
int& scale_n,
int& scale_d,
int& offset)
76 bool applyAligned = alignCorners && (outputSize > 1);
77 scale_n = applyAligned ? (outputSize - 1) : outputSize;
78 scale_d = applyAligned ? (inputSize - 1) : inputSize;
81 int gcd = std::gcd(scale_n, scale_d);
82 scale_n = 2 * scale_n / gcd;
83 scale_d = 2 * scale_d / gcd;
86 offset = halfPixel ? (scale_d / 2 - scale_n / 2) : 0;
89 if ((offset & 1) == 0)
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);
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;
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) };
112 std::vector<int16_t> offset = {
static_cast<int16_t
>(offset_y),
113 static_cast<int16_t
>(offset_x) };
115 std::vector<int16_t> border = {
static_cast<int16_t
>(border_y),
116 static_cast<int16_t
>(border_x) };
118 auto isInt16Range = [](
int x)
120 return (x <= std::numeric_limits<int16_t>::max()) && (x >= std::numeric_limits<int16_t>::min());
123 if (inputs[0]->IsQuantized())
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))
131 throw armnn::Exception(
"ConvertResizeToTosaOperator: stride or offset out of 16 bit range");
135 TosaResizeAttribute resizeAttribute(scale, offset, border, mode);
137 auto* op =
new TosaSerializationOperator(Op_RESIZE,
138 Attribute_ResizeAttribute,
143 std::vector<TosaSerializationTensor*> tensors;
148 if(inputName.find(
"input_") != std::string::npos)
151 DType inputDType =
ArmNNToDType(inputs[0]->GetDataType());
153 tensors.push_back(
new TosaSerializationTensor(inputName, inputShape, inputDType, {}));
157 DType outputDType =
ArmNNToDType(outputs[0]->GetDataType());
159 tensors.push_back(
new TosaSerializationTensor(outputName, outputShape, outputDType, {}));
163 return new TosaSerializationBasicBlock(blockName,