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(
"input0_");
41 std::string outputName = std::string(
"output0_");
56 int32_t inputHeight =
static_cast<int32_t
>(inputs[0]->GetShape()[1]);
57 int32_t inputWidth =
static_cast<int32_t
>(inputs[0]->GetShape()[2]);
59 int32_t outputHeight =
static_cast<int32_t
>(resizeDescriptor->
m_TargetHeight);
60 int32_t outputWidth =
static_cast<int32_t
>(resizeDescriptor->
m_TargetWidth);
67 auto preprocessResizeParameters = [&](
int inputSize,
int outputSize,
int& scale_n,
int& scale_d,
int& offset)
80 bool applyAligned = alignCorners && (outputSize > 1);
81 scale_n = applyAligned ? (outputSize - 1) : outputSize;
82 scale_d = applyAligned ? (inputSize - 1) : inputSize;
85 int gcd = std::gcd(scale_n, scale_d);
86 scale_n = 2 * scale_n / gcd;
87 scale_d = 2 * scale_d / gcd;
90 offset = halfPixel ? (scale_d / 2 - scale_n / 2) : 0;
93 if ((offset & 1) == 0)
101 int scale_y_n, scale_y_d, offset_y;
102 int scale_x_n, scale_x_d, offset_x;
103 preprocessResizeParameters(inputHeight, outputHeight, scale_y_n, scale_y_d, offset_y);
104 preprocessResizeParameters(inputWidth, outputWidth, scale_x_n, scale_x_d, offset_x);
106 int border_y = scale_y_d * (outputHeight - 1) - scale_y_n * (inputHeight - 1) + offset_y;
107 int border_x = scale_x_d * (outputWidth - 1) - scale_x_n * (inputWidth - 1) + offset_x;
110 std::vector<int16_t> scale = {
static_cast<int16_t
>(scale_y_n),
111 static_cast<int16_t
>(scale_y_d),
112 static_cast<int16_t
>(scale_x_n),
113 static_cast<int16_t
>(scale_x_d) };
116 std::vector<int16_t> offset = {
static_cast<int16_t
>(offset_y),
117 static_cast<int16_t
>(offset_x) };
119 std::vector<int16_t> border = {
static_cast<int16_t
>(border_y),
120 static_cast<int16_t
>(border_x) };
122 auto isInt16Range = [](
int x)
124 return (x <= std::numeric_limits<int16_t>::max()) && (x >= std::numeric_limits<int16_t>::min());
127 if (inputs[0]->IsQuantized())
130 if (!isInt16Range(scale_y_n) || !isInt16Range(scale_y_d) ||
131 !isInt16Range(scale_x_n) || !isInt16Range(scale_x_d) ||
132 !isInt16Range(offset_y) || !isInt16Range(offset_x) ||
133 !isInt16Range(border_y) || !isInt16Range(border_x))
135 throw armnn::Exception(
"ConvertResizeToTosaOperator: stride or offset out of 16 bit range");
139 TosaResizeAttribute resizeAttribute(scale, offset, border, mode);
141 auto* op =
new TosaSerializationOperator(Op_RESIZE,
142 Attribute_ResizeAttribute,
147 std::vector<TosaSerializationTensor*> tensors;
152 if(inputName.find(
"input0_") != std::string::npos)
155 DType inputDType =
ArmNNToDType(inputs[0]->GetDataType());
157 tensors.push_back(
new TosaSerializationTensor(inputName, inputShape, inputDType, {}));
161 DType outputDType =
ArmNNToDType(outputs[0]->GetDataType());
163 tensors.push_back(
new TosaSerializationTensor(outputName, outputShape, outputDType, {}));
167 return new TosaSerializationBasicBlock(blockName,