| 2708 | } |
| 2709 | |
| 2710 | TfLiteStatus NNAPIDelegateKernel::Invoke(TfLiteContext* context, |
| 2711 | TfLiteNode* node) { |
| 2712 | ANeuralNetworksExecution* execution = nullptr; |
| 2713 | RETURN_TFLITE_ERROR_IF_NN_ERROR( |
| 2714 | context, nnapi_->ANeuralNetworksExecution_create(nn_compilation_.get(), |
| 2715 | &execution)); |
| 2716 | std::unique_ptr<ANeuralNetworksExecution, NNFreeExecution> |
| 2717 | execution_unique_ptr(execution); |
| 2718 | |
| 2719 | // Set the input tensor buffers. Note: we access tflite tensors using |
| 2720 | // absolute indices but NN api indices inputs by relative indices. |
| 2721 | int relative_input_index = 0; |
| 2722 | |
| 2723 | size_t input_offset = 0; |
| 2724 | for (auto absolute_input_index : TfLiteIntArrayView(node->inputs)) { |
| 2725 | if (absolute_input_index == kOptionalTensor) { |
| 2726 | continue; |
| 2727 | } |
| 2728 | TfLiteTensor* tensor = &context->tensors[absolute_input_index]; |
| 2729 | if (tensor->allocation_type != kTfLiteMmapRo) { |
| 2730 | if (tensor->buffer_handle != kTfLiteNullBufferHandle && |
| 2731 | tensor->buffer_handle < tensor_memory_map_->size()) { |
| 2732 | RETURN_TFLITE_ERROR_IF_NN_ERROR( |
| 2733 | context, nnapi_->ANeuralNetworksExecution_setInputFromMemory( |
| 2734 | execution, relative_input_index, nullptr, |
| 2735 | tensor_memory_map_->at(tensor->buffer_handle).memory, |
| 2736 | 0, tensor->bytes)); |
| 2737 | relative_input_index++; |
| 2738 | continue; |
| 2739 | } |
| 2740 | TfLiteType ann_type_equivalent = |
| 2741 | operand_mapping_.lite_index_to_ann_type_conversion( |
| 2742 | absolute_input_index); |
| 2743 | int tensor_size = 0; |
| 2744 | if (ann_type_equivalent != kTfLiteNoType) { |
| 2745 | const auto num_elements = NumElements(tensor); |
| 2746 | uint8_t* input_ptr = nn_input_memory_->get_data_ptr() + input_offset; |
| 2747 | if (tensor->type == kTfLiteUInt8 && |
| 2748 | ann_type_equivalent == kTfLiteInt32) { |
| 2749 | for (int i = 0; i < num_elements; ++i) { |
| 2750 | reinterpret_cast<int32_t*>(input_ptr)[i] = |
| 2751 | static_cast<const int32_t>(tensor->data.raw_const[i]); |
| 2752 | } |
| 2753 | } else if (tensor->type == kTfLiteInt8 && |
| 2754 | ann_type_equivalent == kTfLiteUInt8) { |
| 2755 | // Explicitly convert int8 values to uint8 values. |
| 2756 | for (int i = 0; i < num_elements; ++i) { |
| 2757 | input_ptr[i] = static_cast<const uint8_t>( |
| 2758 | static_cast<int32_t>(tensor->data.int8[i]) + 128); |
| 2759 | } |
| 2760 | } else if (tensor->type == kTfLiteInt8 && |
| 2761 | ann_type_equivalent == kTfLiteInt32) { |
| 2762 | for (int i = 0; i < num_elements; ++i) { |
| 2763 | reinterpret_cast<int32_t*>(input_ptr)[i] = |
| 2764 | static_cast<const int32_t>(tensor->data.raw_const[i]) + 128; |
| 2765 | } |
| 2766 | } else { |
| 2767 | context->ReportError( |