void exportAsReshape(loco::Node *node, FlatBufferBuilder &builder,
std::vector<int32_t> &new_shape_vec, SerializedModelData &gd)
{
+ // NOTE TFLite has two ways to get new shape paramter,
+ // one is by attribute 'new_shape' and the other is by input 'shape'.
+ // Therefore TFLite interpreter calculates Reshape operation correctly
+ // if one of them is valid.
+ // However, since NN runtime usually get new shape parameter by input 'shape',
+ // passing new shape only by attribute can cause some problems.
+ // Of course, the opposite situation can be occurred in the future.
+ // To prevent those problems, we pass new shape parameter not only by attribute
+ // but also by input.
+
+ auto input_shape_shape_vec_offset =
+ builder.CreateVector(std::vector<int32_t>{(int32_t)new_shape_vec.size()});
+
+ size_t input_shape_vec_size = new_shape_vec.size() * sizeof(int32_t);
+ auto input_shape_input_vec_offset =
+ builder.CreateVector(reinterpret_cast<uint8_t *>(new_shape_vec.data()), input_shape_vec_size);
+ auto input_shape_buffer_offset = CreateBuffer(builder, input_shape_input_vec_offset);
+
+ const auto input_shape_buffer_id = static_cast<uint32_t>(gd._buffers.size());
+ gd._buffers.push_back(input_shape_buffer_offset);
+
+ auto input_shape_tensor_id = static_cast<int32_t>(gd._tensors.size());
+ auto name_offset = builder.CreateString("t_" + std::to_string(input_shape_tensor_id));
+ auto input_shape_tensor_offset = CreateTensor(
+ builder, input_shape_shape_vec_offset, TensorType_INT32, input_shape_buffer_id, name_offset);
+ gd._tensors.push_back(input_shape_tensor_offset);
+
uint32_t op_idx = gd.registerBuiltinOpcode(tflite::BuiltinOperator_RESHAPE);
- std::vector<int32_t> inputs_vec{get_tensor_index(node->arg(0))};
+ std::vector<int32_t> inputs_vec{get_tensor_index(node->arg(0)), input_shape_tensor_id};
std::vector<int32_t> outputs_vec{get_tensor_index(static_cast<loco::Node *>(node))};
auto inputs = builder.CreateVector(inputs_vec);
auto outputs = builder.CreateVector(outputs_vec);