blob: 7ae483ede2f75ff790d3b4eeb264536ccc7855ca [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.2/types.h>
21#include <nnapi/OperandTypes.h>
22#include <nnapi/OperationTypes.h>
23#include <nnapi/Result.h>
24#include <nnapi/SharedMemory.h>
25#include <nnapi/TypeUtils.h>
26#include <nnapi/Types.h>
Michael Butler6547b2a2020-11-22 19:36:30 -080027#include <nnapi/Validation.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080028#include <nnapi/hal/1.0/Conversions.h>
Michael Butler7fd03c22020-12-06 21:50:59 -080029#include <nnapi/hal/1.1/Conversions.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080030#include <nnapi/hal/CommonUtils.h>
Michael Butler4b276a72020-08-06 23:22:35 -070031#include <nnapi/hal/HandleError.h>
Michael Butlerb98aa6d2020-02-22 22:37:59 -080032
33#include <algorithm>
34#include <functional>
35#include <iterator>
36#include <memory>
37#include <type_traits>
38#include <utility>
39
40namespace {
41
42template <typename Type>
43constexpr std::underlying_type_t<Type> underlyingType(Type value) {
44 return static_cast<std::underlying_type_t<Type>>(value);
45}
46
Michael Butler4024d8f2020-12-04 17:38:20 -080047using HalDuration = std::chrono::duration<uint64_t, std::micro>;
Michael Butler6547b2a2020-11-22 19:36:30 -080048constexpr auto kVersion = android::nn::Version::ANDROID_Q;
Michael Butler4024d8f2020-12-04 17:38:20 -080049constexpr uint64_t kNoTiming = std::numeric_limits<uint64_t>::max();
Michael Butler6547b2a2020-11-22 19:36:30 -080050
Michael Butlerb98aa6d2020-02-22 22:37:59 -080051} // namespace
52
53namespace android::nn {
54namespace {
55
56constexpr bool validOperandType(OperandType operandType) {
57 switch (operandType) {
58 case OperandType::FLOAT32:
59 case OperandType::INT32:
60 case OperandType::UINT32:
61 case OperandType::TENSOR_FLOAT32:
62 case OperandType::TENSOR_INT32:
63 case OperandType::TENSOR_QUANT8_ASYMM:
64 case OperandType::BOOL:
65 case OperandType::TENSOR_QUANT16_SYMM:
66 case OperandType::TENSOR_FLOAT16:
67 case OperandType::TENSOR_BOOL8:
68 case OperandType::FLOAT16:
69 case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
70 case OperandType::TENSOR_QUANT16_ASYMM:
71 case OperandType::TENSOR_QUANT8_SYMM:
72 case OperandType::OEM:
73 case OperandType::TENSOR_OEM_BYTE:
74 return true;
75 default:
76 break;
77 }
78 return isExtension(operandType);
79}
80
81using hardware::hidl_handle;
82using hardware::hidl_vec;
83
84template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -080085using unvalidatedConvertOutput =
86 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080087
88template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -080089GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
90 const hidl_vec<Type>& arguments) {
91 std::vector<unvalidatedConvertOutput<Type>> canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080092 canonical.reserve(arguments.size());
93 for (const auto& argument : arguments) {
Michael Butler6547b2a2020-11-22 19:36:30 -080094 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -080095 }
96 return canonical;
97}
98
99template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800100GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
101 const hidl_vec<Type>& arguments) {
102 return unvalidatedConvertVec(arguments);
103}
104
105template <typename Type>
106decltype(nn::unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& halObject) {
107 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
108 const auto maybeVersion = validate(canonical);
109 if (!maybeVersion.has_value()) {
110 return error() << maybeVersion.error();
111 }
112 const auto version = maybeVersion.value();
113 if (version > kVersion) {
114 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
115 }
116 return canonical;
117}
118
119template <typename Type>
120GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> validatedConvert(
121 const hidl_vec<Type>& arguments) {
122 std::vector<unvalidatedConvertOutput<Type>> canonical;
123 canonical.reserve(arguments.size());
124 for (const auto& argument : arguments) {
125 canonical.push_back(NN_TRY(validatedConvert(argument)));
126 }
127 return canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800128}
129
130} // anonymous namespace
131
Michael Butler6547b2a2020-11-22 19:36:30 -0800132GeneralResult<OperandType> unvalidatedConvert(const hal::V1_2::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800133 return static_cast<OperandType>(operandType);
134}
135
Michael Butler6547b2a2020-11-22 19:36:30 -0800136GeneralResult<OperationType> unvalidatedConvert(const hal::V1_2::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800137 return static_cast<OperationType>(operationType);
138}
139
Michael Butler6547b2a2020-11-22 19:36:30 -0800140GeneralResult<DeviceType> unvalidatedConvert(const hal::V1_2::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800141 return static_cast<DeviceType>(deviceType);
142}
143
Michael Butler6547b2a2020-11-22 19:36:30 -0800144GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_2::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800145 const bool validOperandTypes = std::all_of(
146 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
147 [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800148 const auto maybeType = unvalidatedConvert(operandPerformance.type);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800149 return !maybeType.has_value() ? false : validOperandType(maybeType.value());
150 });
151 if (!validOperandTypes) {
Michael Butler4b276a72020-08-06 23:22:35 -0700152 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800153 << "Invalid OperandType when converting OperandPerformance in Capabilities";
154 }
155
156 const auto relaxedFloat32toFloat16PerformanceScalar =
Michael Butler6547b2a2020-11-22 19:36:30 -0800157 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800158 const auto relaxedFloat32toFloat16PerformanceTensor =
Michael Butler6547b2a2020-11-22 19:36:30 -0800159 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
160 auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800161
Michael Butler4b276a72020-08-06 23:22:35 -0700162 auto table = NN_TRY(hal::utils::makeGeneralFailure(
163 Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
164 nn::ErrorStatus::GENERAL_FAILURE));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800165
166 return Capabilities{
167 .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
168 .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
169 .operandPerformance = std::move(table),
170 };
171}
172
Michael Butler6547b2a2020-11-22 19:36:30 -0800173GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800174 const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
175 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800176 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
177 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800178 };
179}
180
Michael Butler6547b2a2020-11-22 19:36:30 -0800181GeneralResult<Operation> unvalidatedConvert(const hal::V1_2::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800182 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800183 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800184 .inputs = operation.inputs,
185 .outputs = operation.outputs,
186 };
187}
188
Michael Butler6547b2a2020-11-22 19:36:30 -0800189GeneralResult<Operand::SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800190 const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
191 return Operand::SymmPerChannelQuantParams{
192 .scales = symmPerChannelQuantParams.scales,
193 .channelDim = symmPerChannelQuantParams.channelDim,
194 };
195}
196
Michael Butler6547b2a2020-11-22 19:36:30 -0800197GeneralResult<Operand> unvalidatedConvert(const hal::V1_2::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800198 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800199 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800200 .dimensions = operand.dimensions,
201 .scale = operand.scale,
202 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800203 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
204 .location = NN_TRY(unvalidatedConvert(operand.location)),
205 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800206 };
207}
208
Michael Butler6547b2a2020-11-22 19:36:30 -0800209GeneralResult<Operand::ExtraParams> unvalidatedConvert(
210 const hal::V1_2::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800211 using Discriminator = hal::V1_2::Operand::ExtraParams::hidl_discriminator;
212 switch (extraParams.getDiscriminator()) {
213 case Discriminator::none:
214 return Operand::NoParams{};
215 case Discriminator::channelQuant:
Michael Butler6547b2a2020-11-22 19:36:30 -0800216 return unvalidatedConvert(extraParams.channelQuant());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800217 case Discriminator::extension:
218 return extraParams.extension();
219 }
Michael Butler4b276a72020-08-06 23:22:35 -0700220 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
221 << "Unrecognized Operand::ExtraParams discriminator: "
222 << underlyingType(extraParams.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800223}
224
Michael Butler6547b2a2020-11-22 19:36:30 -0800225GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model) {
226 auto operations = NN_TRY(unvalidatedConvert(model.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800227
228 // Verify number of consumers.
229 const auto numberOfConsumers =
230 hal::utils::countNumberOfConsumers(model.operands.size(), operations);
231 CHECK(model.operands.size() == numberOfConsumers.size());
232 for (size_t i = 0; i < model.operands.size(); ++i) {
233 if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler4b276a72020-08-06 23:22:35 -0700234 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
235 << "Invalid numberOfConsumers for operand " << i << ", expected "
236 << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800237 }
238 }
239
240 auto main = Model::Subgraph{
Michael Butler6547b2a2020-11-22 19:36:30 -0800241 .operands = NN_TRY(unvalidatedConvert(model.operands)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800242 .operations = std::move(operations),
243 .inputIndexes = model.inputIndexes,
244 .outputIndexes = model.outputIndexes,
245 };
246
247 return Model{
248 .main = std::move(main),
Michael Butler6547b2a2020-11-22 19:36:30 -0800249 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
250 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800251 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800252 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800253 };
254}
255
Michael Butler6547b2a2020-11-22 19:36:30 -0800256GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800257 const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
258 return Model::ExtensionNameAndPrefix{
259 .name = extensionNameAndPrefix.name,
260 .prefix = extensionNameAndPrefix.prefix,
261 };
262}
263
Michael Butler6547b2a2020-11-22 19:36:30 -0800264GeneralResult<OutputShape> unvalidatedConvert(const hal::V1_2::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800265 return OutputShape{
266 .dimensions = outputShape.dimensions,
267 .isSufficient = outputShape.isSufficient,
268 };
269}
270
Michael Butler6547b2a2020-11-22 19:36:30 -0800271GeneralResult<MeasureTiming> unvalidatedConvert(const hal::V1_2::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800272 return static_cast<MeasureTiming>(measureTiming);
273}
274
Michael Butler6547b2a2020-11-22 19:36:30 -0800275GeneralResult<Timing> unvalidatedConvert(const hal::V1_2::Timing& timing) {
Michael Butler4024d8f2020-12-04 17:38:20 -0800276 constexpr uint64_t kMaxTiming = std::chrono::floor<HalDuration>(Duration::max()).count();
277 constexpr auto convertTiming = [](uint64_t halTiming) -> OptionalDuration {
278 if (halTiming == kNoTiming) {
279 return {};
280 }
281 if (halTiming > kMaxTiming) {
282 return Duration::max();
283 }
284 return HalDuration{halTiming};
285 };
286 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
287 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800288}
289
Michael Butler6547b2a2020-11-22 19:36:30 -0800290GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800291 return Extension{
292 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800293 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800294 };
295}
296
Michael Butler6547b2a2020-11-22 19:36:30 -0800297GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800298 const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation) {
299 return Extension::OperandTypeInformation{
300 .type = operandTypeInformation.type,
301 .isTensor = operandTypeInformation.isTensor,
302 .byteSize = operandTypeInformation.byteSize,
303 };
304}
305
Michael Butler6547b2a2020-11-22 19:36:30 -0800306GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) {
Michael Butlerab2f4822021-02-08 00:05:07 -0800307 if (hidlHandle.getNativeHandle() == nullptr) {
308 return nullptr;
309 }
310 auto handle = NN_TRY(hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle()));
311 return std::make_shared<const Handle>(std::move(handle));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800312}
313
Michael Butler6547b2a2020-11-22 19:36:30 -0800314GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
315 return validatedConvert(deviceType);
316}
317
318GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities) {
319 return validatedConvert(capabilities);
320}
321
322GeneralResult<Model> convert(const hal::V1_2::Model& model) {
323 return validatedConvert(model);
324}
325
326GeneralResult<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming) {
327 return validatedConvert(measureTiming);
328}
329
330GeneralResult<Timing> convert(const hal::V1_2::Timing& timing) {
331 return validatedConvert(timing);
332}
333
Michael Butler4b276a72020-08-06 23:22:35 -0700334GeneralResult<std::vector<Extension>> convert(const hidl_vec<hal::V1_2::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800335 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800336}
337
Slava Shklyaev49817a02020-10-27 18:44:01 +0000338GeneralResult<std::vector<SharedHandle>> convert(const hidl_vec<hidl_handle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800339 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800340}
341
Michael Butler4b276a72020-08-06 23:22:35 -0700342GeneralResult<std::vector<OutputShape>> convert(
343 const hidl_vec<hal::V1_2::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800344 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800345}
346
347} // namespace android::nn
348
349namespace android::hardware::neuralnetworks::V1_2::utils {
350namespace {
351
Michael Butler6547b2a2020-11-22 19:36:30 -0800352using utils::unvalidatedConvert;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800353
Michael Butler6547b2a2020-11-22 19:36:30 -0800354nn::GeneralResult<V1_0::OperandLifeTime> unvalidatedConvert(const nn::Operand::LifeTime& lifetime) {
355 return V1_0::utils::unvalidatedConvert(lifetime);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800356}
357
Michael Butler6547b2a2020-11-22 19:36:30 -0800358nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800359 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800360 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800361}
362
Michael Butler6547b2a2020-11-22 19:36:30 -0800363nn::GeneralResult<V1_0::DataLocation> unvalidatedConvert(const nn::DataLocation& location) {
364 return V1_0::utils::unvalidatedConvert(location);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800365}
366
Michael Butler6547b2a2020-11-22 19:36:30 -0800367nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
368 const nn::Model::OperandValues& operandValues) {
369 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800370}
371
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800372nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800373 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800374}
375
376template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -0800377using unvalidatedConvertOutput =
378 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800379
380template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800381nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
382 const std::vector<Type>& arguments) {
383 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800384 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800385 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800386 }
387 return halObject;
388}
389
390template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800391nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
392 const std::vector<Type>& arguments) {
393 return unvalidatedConvertVec(arguments);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800394}
395
Michael Butler4b276a72020-08-06 23:22:35 -0700396nn::GeneralResult<Operand::ExtraParams> makeExtraParams(nn::Operand::NoParams /*noParams*/) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800397 return Operand::ExtraParams{};
398}
399
Michael Butler4b276a72020-08-06 23:22:35 -0700400nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800401 const nn::Operand::SymmPerChannelQuantParams& channelQuant) {
402 Operand::ExtraParams ret;
Michael Butler6547b2a2020-11-22 19:36:30 -0800403 ret.channelQuant(NN_TRY(unvalidatedConvert(channelQuant)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800404 return ret;
405}
406
Michael Butler4b276a72020-08-06 23:22:35 -0700407nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
408 const nn::Operand::ExtensionParams& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800409 Operand::ExtraParams ret;
410 ret.extension(extension);
411 return ret;
412}
413
Michael Butler6547b2a2020-11-22 19:36:30 -0800414template <typename Type>
415decltype(utils::unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& canonical) {
416 const auto maybeVersion = nn::validate(canonical);
417 if (!maybeVersion.has_value()) {
418 return nn::error() << maybeVersion.error();
419 }
420 const auto version = maybeVersion.value();
421 if (version > kVersion) {
422 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
423 }
424 return utils::unvalidatedConvert(canonical);
425}
426
427template <typename Type>
428nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> validatedConvert(
429 const std::vector<Type>& arguments) {
430 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
431 for (size_t i = 0; i < arguments.size(); ++i) {
432 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
433 }
434 return halObject;
435}
436
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800437} // anonymous namespace
438
Michael Butler6547b2a2020-11-22 19:36:30 -0800439nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800440 return static_cast<OperandType>(operandType);
441}
442
Michael Butler6547b2a2020-11-22 19:36:30 -0800443nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800444 return static_cast<OperationType>(operationType);
445}
446
Michael Butler6547b2a2020-11-22 19:36:30 -0800447nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800448 switch (deviceType) {
449 case nn::DeviceType::UNKNOWN:
Michael Butler4b276a72020-08-06 23:22:35 -0700450 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Invalid DeviceType UNKNOWN";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800451 case nn::DeviceType::OTHER:
452 case nn::DeviceType::CPU:
453 case nn::DeviceType::GPU:
454 case nn::DeviceType::ACCELERATOR:
455 return static_cast<DeviceType>(deviceType);
456 }
Michael Butler4b276a72020-08-06 23:22:35 -0700457 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
458 << "Invalid DeviceType " << underlyingType(deviceType);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800459}
460
Michael Butler6547b2a2020-11-22 19:36:30 -0800461nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800462 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
463 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
464 std::copy_if(capabilities.operandPerformance.asVector().begin(),
465 capabilities.operandPerformance.asVector().end(),
466 std::back_inserter(operandPerformance),
467 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
468 return nn::validOperandType(operandPerformance.type);
469 });
470
471 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800472 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
473 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
474 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
475 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
476 .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800477 };
478}
479
Michael Butler6547b2a2020-11-22 19:36:30 -0800480nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800481 const nn::Capabilities::OperandPerformance& operandPerformance) {
482 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800483 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
484 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800485 };
486}
487
Michael Butler6547b2a2020-11-22 19:36:30 -0800488nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800489 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800490 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800491 .inputs = operation.inputs,
492 .outputs = operation.outputs,
493 };
494}
495
Michael Butler6547b2a2020-11-22 19:36:30 -0800496nn::GeneralResult<SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800497 const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
498 return SymmPerChannelQuantParams{
499 .scales = symmPerChannelQuantParams.scales,
500 .channelDim = symmPerChannelQuantParams.channelDim,
501 };
502}
503
Michael Butler6547b2a2020-11-22 19:36:30 -0800504nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800505 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800506 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800507 .dimensions = operand.dimensions,
508 .numberOfConsumers = 0,
509 .scale = operand.scale,
510 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800511 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
512 .location = NN_TRY(unvalidatedConvert(operand.location)),
513 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800514 };
515}
516
Michael Butler6547b2a2020-11-22 19:36:30 -0800517nn::GeneralResult<Operand::ExtraParams> unvalidatedConvert(
518 const nn::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800519 return std::visit([](const auto& x) { return makeExtraParams(x); }, extraParams);
520}
521
Michael Butler6547b2a2020-11-22 19:36:30 -0800522nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800523 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700524 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800525 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800526 }
527
Michael Butler6547b2a2020-11-22 19:36:30 -0800528 auto operands = NN_TRY(unvalidatedConvert(model.main.operands));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800529
530 // Update number of consumers.
531 const auto numberOfConsumers =
532 hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
533 CHECK(operands.size() == numberOfConsumers.size());
534 for (size_t i = 0; i < operands.size(); ++i) {
535 operands[i].numberOfConsumers = numberOfConsumers[i];
536 }
537
538 return Model{
539 .operands = std::move(operands),
Michael Butler6547b2a2020-11-22 19:36:30 -0800540 .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800541 .inputIndexes = model.main.inputIndexes,
542 .outputIndexes = model.main.outputIndexes,
Michael Butler6547b2a2020-11-22 19:36:30 -0800543 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
544 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800545 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800546 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800547 };
548}
549
Michael Butler6547b2a2020-11-22 19:36:30 -0800550nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800551 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
552 return Model::ExtensionNameAndPrefix{
553 .name = extensionNameAndPrefix.name,
554 .prefix = extensionNameAndPrefix.prefix,
555 };
556}
557
Michael Butler6547b2a2020-11-22 19:36:30 -0800558nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800559 return OutputShape{.dimensions = outputShape.dimensions,
560 .isSufficient = outputShape.isSufficient};
561}
562
Michael Butler6547b2a2020-11-22 19:36:30 -0800563nn::GeneralResult<MeasureTiming> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800564 return static_cast<MeasureTiming>(measureTiming);
565}
566
Michael Butler6547b2a2020-11-22 19:36:30 -0800567nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
Michael Butler4024d8f2020-12-04 17:38:20 -0800568 constexpr auto convertTiming = [](nn::OptionalDuration canonicalTiming) -> uint64_t {
569 if (!canonicalTiming.has_value()) {
570 return kNoTiming;
571 }
572 return std::chrono::ceil<HalDuration>(*canonicalTiming).count();
573 };
574 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
575 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800576}
577
Michael Butler6547b2a2020-11-22 19:36:30 -0800578nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800579 return Extension{
580 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800581 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800582 };
583}
584
Michael Butler6547b2a2020-11-22 19:36:30 -0800585nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800586 const nn::Extension::OperandTypeInformation& operandTypeInformation) {
587 return Extension::OperandTypeInformation{
588 .type = operandTypeInformation.type,
589 .isTensor = operandTypeInformation.isTensor,
590 .byteSize = operandTypeInformation.byteSize,
591 };
592}
593
Michael Butler6547b2a2020-11-22 19:36:30 -0800594nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
Michael Butlerab2f4822021-02-08 00:05:07 -0800595 if (handle == nullptr) {
596 return {};
597 }
598 return hal::utils::hidlHandleFromSharedHandle(*handle);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800599}
600
Michael Butler6547b2a2020-11-22 19:36:30 -0800601nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
602 return validatedConvert(deviceType);
603}
604
605nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
606 return validatedConvert(capabilities);
607}
608
609nn::GeneralResult<Model> convert(const nn::Model& model) {
610 return validatedConvert(model);
611}
612
613nn::GeneralResult<MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
614 return validatedConvert(measureTiming);
615}
616
617nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
618 return validatedConvert(timing);
619}
620
Michael Butler4b276a72020-08-06 23:22:35 -0700621nn::GeneralResult<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800622 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800623}
624
Slava Shklyaev49817a02020-10-27 18:44:01 +0000625nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800626 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800627}
628
Michael Butler4b276a72020-08-06 23:22:35 -0700629nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800630 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800631}
632
Michael Butler7fd03c22020-12-06 21:50:59 -0800633nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
634 return V1_1::utils::convert(deviceStatus);
635}
636
637nn::GeneralResult<V1_0::Request> convert(const nn::Request& request) {
638 return V1_1::utils::convert(request);
639}
640
641nn::GeneralResult<V1_0::ErrorStatus> convert(const nn::ErrorStatus& status) {
642 return V1_1::utils::convert(status);
643}
644
645nn::GeneralResult<V1_1::ExecutionPreference> convert(
646 const nn::ExecutionPreference& executionPreference) {
647 return V1_1::utils::convert(executionPreference);
648}
649
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800650} // namespace android::hardware::neuralnetworks::V1_2::utils