blob: 467ceb389b8954b2ca6e95ec780ae8c2d892447a [file] [log] [blame]
Michael Butlerb98aa6d2020-02-22 22:37:59 -08001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Conversions.h"
18
19#include <android-base/logging.h>
20#include <android/hardware/neuralnetworks/1.0/types.h>
21#include <android/hardware/neuralnetworks/1.1/types.h>
22#include <nnapi/OperandTypes.h>
23#include <nnapi/OperationTypes.h>
24#include <nnapi/Result.h>
25#include <nnapi/SharedMemory.h>
Michael Butler6547b2a2020-11-22 19:36:30 -080026#include <nnapi/TypeUtils.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080027#include <nnapi/Types.h>
Michael Butler6547b2a2020-11-22 19:36:30 -080028#include <nnapi/Validation.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080029#include <nnapi/hal/1.0/Conversions.h>
30#include <nnapi/hal/CommonUtils.h>
31
32#include <algorithm>
33#include <functional>
34#include <iterator>
35#include <type_traits>
36#include <utility>
37
Michael Butler388bceb2021-02-03 15:15:43 -080038#include "Utils.h"
Michael Butler6547b2a2020-11-22 19:36:30 -080039
Michael Butlerb98aa6d2020-02-22 22:37:59 -080040namespace android::nn {
41namespace {
42
43using hardware::hidl_vec;
44
45template <typename Input>
Michael Butler388bceb2021-02-03 15:15:43 -080046using UnvalidatedConvertOutput =
Michael Butler6547b2a2020-11-22 19:36:30 -080047 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080048
49template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -080050GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -080051 const hidl_vec<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -080052 std::vector<UnvalidatedConvertOutput<Type>> canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080053 canonical.reserve(arguments.size());
54 for (const auto& argument : arguments) {
Michael Butler6547b2a2020-11-22 19:36:30 -080055 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
56 }
57 return canonical;
58}
59
60template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -080061GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& halObject) {
Michael Butler6547b2a2020-11-22 19:36:30 -080062 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
Michael Butler388bceb2021-02-03 15:15:43 -080063 NN_TRY(hal::V1_1::utils::compliantVersion(canonical));
Michael Butlerb98aa6d2020-02-22 22:37:59 -080064 return canonical;
65}
66
67} // anonymous namespace
68
Michael Butler6547b2a2020-11-22 19:36:30 -080069GeneralResult<OperationType> unvalidatedConvert(const hal::V1_1::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -080070 return static_cast<OperationType>(operationType);
71}
72
Michael Butler6547b2a2020-11-22 19:36:30 -080073GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_1::Capabilities& capabilities) {
74 const auto quantized8Performance =
75 NN_TRY(unvalidatedConvert(capabilities.quantized8Performance));
76 const auto float32Performance = NN_TRY(unvalidatedConvert(capabilities.float32Performance));
Michael Butlerb98aa6d2020-02-22 22:37:59 -080077 const auto relaxedFloat32toFloat16Performance =
Michael Butler6547b2a2020-11-22 19:36:30 -080078 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16Performance));
Michael Butlerb98aa6d2020-02-22 22:37:59 -080079
80 auto table = hal::utils::makeQuantized8PerformanceConsistentWithP(float32Performance,
81 quantized8Performance);
82
83 return Capabilities{
84 .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16Performance,
85 .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16Performance,
86 .operandPerformance = std::move(table),
87 };
88}
89
Michael Butler6547b2a2020-11-22 19:36:30 -080090GeneralResult<Operation> unvalidatedConvert(const hal::V1_1::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -080091 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -080092 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -080093 .inputs = operation.inputs,
94 .outputs = operation.outputs,
95 };
96}
97
Michael Butler6547b2a2020-11-22 19:36:30 -080098GeneralResult<Model> unvalidatedConvert(const hal::V1_1::Model& model) {
99 auto operations = NN_TRY(unvalidatedConvert(model.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800100
101 // Verify number of consumers.
102 const auto numberOfConsumers =
Michael Butler68b69262021-02-09 15:36:11 -0800103 NN_TRY(hal::utils::countNumberOfConsumers(model.operands.size(), operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800104 CHECK(model.operands.size() == numberOfConsumers.size());
105 for (size_t i = 0; i < model.operands.size(); ++i) {
106 if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler4b276a72020-08-06 23:22:35 -0700107 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
108 << "Invalid numberOfConsumers for operand " << i << ", expected "
109 << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800110 }
111 }
112
113 auto main = Model::Subgraph{
Michael Butler6547b2a2020-11-22 19:36:30 -0800114 .operands = NN_TRY(unvalidatedConvert(model.operands)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800115 .operations = std::move(operations),
116 .inputIndexes = model.inputIndexes,
117 .outputIndexes = model.outputIndexes,
118 };
119
120 return Model{
121 .main = std::move(main),
Michael Butler6547b2a2020-11-22 19:36:30 -0800122 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
123 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800124 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
125 };
126}
127
Michael Butler6547b2a2020-11-22 19:36:30 -0800128GeneralResult<ExecutionPreference> unvalidatedConvert(
Michael Butler4b276a72020-08-06 23:22:35 -0700129 const hal::V1_1::ExecutionPreference& executionPreference) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800130 return static_cast<ExecutionPreference>(executionPreference);
131}
132
Michael Butler6547b2a2020-11-22 19:36:30 -0800133GeneralResult<Capabilities> convert(const hal::V1_1::Capabilities& capabilities) {
134 return validatedConvert(capabilities);
135}
136
137GeneralResult<Model> convert(const hal::V1_1::Model& model) {
138 return validatedConvert(model);
139}
140
141GeneralResult<ExecutionPreference> convert(
142 const hal::V1_1::ExecutionPreference& executionPreference) {
143 return validatedConvert(executionPreference);
144}
145
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800146} // namespace android::nn
147
148namespace android::hardware::neuralnetworks::V1_1::utils {
149namespace {
150
Michael Butler6547b2a2020-11-22 19:36:30 -0800151using utils::unvalidatedConvert;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800152
Michael Butler6547b2a2020-11-22 19:36:30 -0800153nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800154 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800155 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800156}
157
Michael Butler6547b2a2020-11-22 19:36:30 -0800158nn::GeneralResult<V1_0::Operand> unvalidatedConvert(const nn::Operand& operand) {
159 return V1_0::utils::unvalidatedConvert(operand);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800160}
161
Michael Butler6547b2a2020-11-22 19:36:30 -0800162nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
163 const nn::Model::OperandValues& operandValues) {
164 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800165}
166
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800167nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800168 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800169}
170
171template <typename Input>
Michael Butler388bceb2021-02-03 15:15:43 -0800172using UnvalidatedConvertOutput =
Michael Butler6547b2a2020-11-22 19:36:30 -0800173 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800174
175template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -0800176nn::GeneralResult<hidl_vec<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -0800177 const std::vector<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -0800178 hidl_vec<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800179 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800180 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800181 }
182 return halObject;
183}
184
Michael Butler6547b2a2020-11-22 19:36:30 -0800185template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -0800186nn::GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& canonical) {
187 NN_TRY(compliantVersion(canonical));
188 return unvalidatedConvert(canonical);
Michael Butler6547b2a2020-11-22 19:36:30 -0800189}
190
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800191} // anonymous namespace
192
Michael Butler6547b2a2020-11-22 19:36:30 -0800193nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800194 return static_cast<OperationType>(operationType);
195}
196
Michael Butler6547b2a2020-11-22 19:36:30 -0800197nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800198 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800199 .float32Performance = NN_TRY(unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800200 capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_FLOAT32))),
Michael Butler6547b2a2020-11-22 19:36:30 -0800201 .quantized8Performance = NN_TRY(unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800202 capabilities.operandPerformance.lookup(nn::OperandType::TENSOR_QUANT8_ASYMM))),
Michael Butler6547b2a2020-11-22 19:36:30 -0800203 .relaxedFloat32toFloat16Performance = NN_TRY(
204 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800205 };
206}
207
Michael Butler6547b2a2020-11-22 19:36:30 -0800208nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800209 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800210 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800211 .inputs = operation.inputs,
212 .outputs = operation.outputs,
213 };
214}
215
Michael Butler6547b2a2020-11-22 19:36:30 -0800216nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800217 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700218 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800219 << "Mdoel cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800220 }
221
Michael Butler6547b2a2020-11-22 19:36:30 -0800222 auto operands = NN_TRY(unvalidatedConvert(model.main.operands));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800223
224 // Update number of consumers.
225 const auto numberOfConsumers =
Michael Butler68b69262021-02-09 15:36:11 -0800226 NN_TRY(hal::utils::countNumberOfConsumers(operands.size(), model.main.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800227 CHECK(operands.size() == numberOfConsumers.size());
228 for (size_t i = 0; i < operands.size(); ++i) {
229 operands[i].numberOfConsumers = numberOfConsumers[i];
230 }
231
232 return Model{
233 .operands = std::move(operands),
Michael Butler6547b2a2020-11-22 19:36:30 -0800234 .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800235 .inputIndexes = model.main.inputIndexes,
236 .outputIndexes = model.main.outputIndexes,
Michael Butler6547b2a2020-11-22 19:36:30 -0800237 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
238 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800239 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
240 };
241}
242
Michael Butler6547b2a2020-11-22 19:36:30 -0800243nn::GeneralResult<ExecutionPreference> unvalidatedConvert(
244 const nn::ExecutionPreference& executionPreference) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800245 return static_cast<ExecutionPreference>(executionPreference);
246}
247
Michael Butler6547b2a2020-11-22 19:36:30 -0800248nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
249 return validatedConvert(capabilities);
250}
251
252nn::GeneralResult<Model> convert(const nn::Model& model) {
253 return validatedConvert(model);
254}
255
256nn::GeneralResult<ExecutionPreference> convert(const nn::ExecutionPreference& executionPreference) {
257 return validatedConvert(executionPreference);
258}
259
Michael Butler7fd03c22020-12-06 21:50:59 -0800260nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
261 return V1_0::utils::convert(deviceStatus);
262}
263
264nn::GeneralResult<V1_0::Request> convert(const nn::Request& request) {
265 return V1_0::utils::convert(request);
266}
267
268nn::GeneralResult<V1_0::ErrorStatus> convert(const nn::ErrorStatus& status) {
269 return V1_0::utils::convert(status);
270}
271
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800272} // namespace android::hardware::neuralnetworks::V1_1::utils