blob: 3790d1f61eb3a5ec8b3248ba65c1b5489901623d [file] [log] [blame]
Michael Butlera685c3d2020-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 Butler32acc062020-11-22 19:36:30 -080027#include <nnapi/Validation.h>
Michael Butlera685c3d2020-02-22 22:37:59 -080028#include <nnapi/hal/1.0/Conversions.h>
29#include <nnapi/hal/CommonUtils.h>
Michael Butler3670c382020-08-06 23:22:35 -070030#include <nnapi/hal/HandleError.h>
Michael Butlera685c3d2020-02-22 22:37:59 -080031
32#include <algorithm>
33#include <functional>
34#include <iterator>
35#include <memory>
36#include <type_traits>
37#include <utility>
38
39namespace {
40
41template <typename Type>
42constexpr std::underlying_type_t<Type> underlyingType(Type value) {
43 return static_cast<std::underlying_type_t<Type>>(value);
44}
45
Michael Butlerca114202020-12-04 17:38:20 -080046using HalDuration = std::chrono::duration<uint64_t, std::micro>;
Michael Butler32acc062020-11-22 19:36:30 -080047constexpr auto kVersion = android::nn::Version::ANDROID_Q;
Michael Butlerca114202020-12-04 17:38:20 -080048constexpr uint64_t kNoTiming = std::numeric_limits<uint64_t>::max();
Michael Butler32acc062020-11-22 19:36:30 -080049
Michael Butlera685c3d2020-02-22 22:37:59 -080050} // namespace
51
52namespace android::nn {
53namespace {
54
55constexpr bool validOperandType(OperandType operandType) {
56 switch (operandType) {
57 case OperandType::FLOAT32:
58 case OperandType::INT32:
59 case OperandType::UINT32:
60 case OperandType::TENSOR_FLOAT32:
61 case OperandType::TENSOR_INT32:
62 case OperandType::TENSOR_QUANT8_ASYMM:
63 case OperandType::BOOL:
64 case OperandType::TENSOR_QUANT16_SYMM:
65 case OperandType::TENSOR_FLOAT16:
66 case OperandType::TENSOR_BOOL8:
67 case OperandType::FLOAT16:
68 case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
69 case OperandType::TENSOR_QUANT16_ASYMM:
70 case OperandType::TENSOR_QUANT8_SYMM:
71 case OperandType::OEM:
72 case OperandType::TENSOR_OEM_BYTE:
73 return true;
74 default:
75 break;
76 }
77 return isExtension(operandType);
78}
79
80using hardware::hidl_handle;
81using hardware::hidl_vec;
82
83template <typename Input>
Michael Butler32acc062020-11-22 19:36:30 -080084using unvalidatedConvertOutput =
85 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlera685c3d2020-02-22 22:37:59 -080086
87template <typename Type>
Michael Butler32acc062020-11-22 19:36:30 -080088GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
89 const hidl_vec<Type>& arguments) {
90 std::vector<unvalidatedConvertOutput<Type>> canonical;
Michael Butlera685c3d2020-02-22 22:37:59 -080091 canonical.reserve(arguments.size());
92 for (const auto& argument : arguments) {
Michael Butler32acc062020-11-22 19:36:30 -080093 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
Michael Butlera685c3d2020-02-22 22:37:59 -080094 }
95 return canonical;
96}
97
98template <typename Type>
Michael Butler32acc062020-11-22 19:36:30 -080099GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
100 const hidl_vec<Type>& arguments) {
101 return unvalidatedConvertVec(arguments);
102}
103
104template <typename Type>
105decltype(nn::unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& halObject) {
106 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
107 const auto maybeVersion = validate(canonical);
108 if (!maybeVersion.has_value()) {
109 return error() << maybeVersion.error();
110 }
111 const auto version = maybeVersion.value();
112 if (version > kVersion) {
113 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
114 }
115 return canonical;
116}
117
118template <typename Type>
119GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> validatedConvert(
120 const hidl_vec<Type>& arguments) {
121 std::vector<unvalidatedConvertOutput<Type>> canonical;
122 canonical.reserve(arguments.size());
123 for (const auto& argument : arguments) {
124 canonical.push_back(NN_TRY(validatedConvert(argument)));
125 }
126 return canonical;
Michael Butlera685c3d2020-02-22 22:37:59 -0800127}
128
129} // anonymous namespace
130
Michael Butler32acc062020-11-22 19:36:30 -0800131GeneralResult<OperandType> unvalidatedConvert(const hal::V1_2::OperandType& operandType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800132 return static_cast<OperandType>(operandType);
133}
134
Michael Butler32acc062020-11-22 19:36:30 -0800135GeneralResult<OperationType> unvalidatedConvert(const hal::V1_2::OperationType& operationType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800136 return static_cast<OperationType>(operationType);
137}
138
Michael Butler32acc062020-11-22 19:36:30 -0800139GeneralResult<DeviceType> unvalidatedConvert(const hal::V1_2::DeviceType& deviceType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800140 return static_cast<DeviceType>(deviceType);
141}
142
Michael Butler32acc062020-11-22 19:36:30 -0800143GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_2::Capabilities& capabilities) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800144 const bool validOperandTypes = std::all_of(
145 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
146 [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
Michael Butler32acc062020-11-22 19:36:30 -0800147 const auto maybeType = unvalidatedConvert(operandPerformance.type);
Michael Butlera685c3d2020-02-22 22:37:59 -0800148 return !maybeType.has_value() ? false : validOperandType(maybeType.value());
149 });
150 if (!validOperandTypes) {
Michael Butler3670c382020-08-06 23:22:35 -0700151 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlera685c3d2020-02-22 22:37:59 -0800152 << "Invalid OperandType when converting OperandPerformance in Capabilities";
153 }
154
155 const auto relaxedFloat32toFloat16PerformanceScalar =
Michael Butler32acc062020-11-22 19:36:30 -0800156 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
Michael Butlera685c3d2020-02-22 22:37:59 -0800157 const auto relaxedFloat32toFloat16PerformanceTensor =
Michael Butler32acc062020-11-22 19:36:30 -0800158 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
159 auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
Michael Butlera685c3d2020-02-22 22:37:59 -0800160
Michael Butler3670c382020-08-06 23:22:35 -0700161 auto table = NN_TRY(hal::utils::makeGeneralFailure(
162 Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
163 nn::ErrorStatus::GENERAL_FAILURE));
Michael Butlera685c3d2020-02-22 22:37:59 -0800164
165 return Capabilities{
166 .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
167 .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
168 .operandPerformance = std::move(table),
169 };
170}
171
Michael Butler32acc062020-11-22 19:36:30 -0800172GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800173 const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
174 return Capabilities::OperandPerformance{
Michael Butler32acc062020-11-22 19:36:30 -0800175 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
176 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800177 };
178}
179
Michael Butler32acc062020-11-22 19:36:30 -0800180GeneralResult<Operation> unvalidatedConvert(const hal::V1_2::Operation& operation) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800181 return Operation{
Michael Butler32acc062020-11-22 19:36:30 -0800182 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800183 .inputs = operation.inputs,
184 .outputs = operation.outputs,
185 };
186}
187
Michael Butler32acc062020-11-22 19:36:30 -0800188GeneralResult<Operand::SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800189 const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
190 return Operand::SymmPerChannelQuantParams{
191 .scales = symmPerChannelQuantParams.scales,
192 .channelDim = symmPerChannelQuantParams.channelDim,
193 };
194}
195
Michael Butler32acc062020-11-22 19:36:30 -0800196GeneralResult<Operand> unvalidatedConvert(const hal::V1_2::Operand& operand) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800197 return Operand{
Michael Butler32acc062020-11-22 19:36:30 -0800198 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800199 .dimensions = operand.dimensions,
200 .scale = operand.scale,
201 .zeroPoint = operand.zeroPoint,
Michael Butler32acc062020-11-22 19:36:30 -0800202 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
203 .location = NN_TRY(unvalidatedConvert(operand.location)),
204 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800205 };
206}
207
Michael Butler32acc062020-11-22 19:36:30 -0800208GeneralResult<Operand::ExtraParams> unvalidatedConvert(
209 const hal::V1_2::Operand::ExtraParams& extraParams) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800210 using Discriminator = hal::V1_2::Operand::ExtraParams::hidl_discriminator;
211 switch (extraParams.getDiscriminator()) {
212 case Discriminator::none:
213 return Operand::NoParams{};
214 case Discriminator::channelQuant:
Michael Butler32acc062020-11-22 19:36:30 -0800215 return unvalidatedConvert(extraParams.channelQuant());
Michael Butlera685c3d2020-02-22 22:37:59 -0800216 case Discriminator::extension:
217 return extraParams.extension();
218 }
Michael Butler3670c382020-08-06 23:22:35 -0700219 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
220 << "Unrecognized Operand::ExtraParams discriminator: "
221 << underlyingType(extraParams.getDiscriminator());
Michael Butlera685c3d2020-02-22 22:37:59 -0800222}
223
Michael Butler32acc062020-11-22 19:36:30 -0800224GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model) {
225 auto operations = NN_TRY(unvalidatedConvert(model.operations));
Michael Butlera685c3d2020-02-22 22:37:59 -0800226
227 // Verify number of consumers.
228 const auto numberOfConsumers =
229 hal::utils::countNumberOfConsumers(model.operands.size(), operations);
230 CHECK(model.operands.size() == numberOfConsumers.size());
231 for (size_t i = 0; i < model.operands.size(); ++i) {
232 if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler3670c382020-08-06 23:22:35 -0700233 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
234 << "Invalid numberOfConsumers for operand " << i << ", expected "
235 << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
Michael Butlera685c3d2020-02-22 22:37:59 -0800236 }
237 }
238
239 auto main = Model::Subgraph{
Michael Butler32acc062020-11-22 19:36:30 -0800240 .operands = NN_TRY(unvalidatedConvert(model.operands)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800241 .operations = std::move(operations),
242 .inputIndexes = model.inputIndexes,
243 .outputIndexes = model.outputIndexes,
244 };
245
246 return Model{
247 .main = std::move(main),
Michael Butler32acc062020-11-22 19:36:30 -0800248 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
249 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800250 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler32acc062020-11-22 19:36:30 -0800251 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800252 };
253}
254
Michael Butler32acc062020-11-22 19:36:30 -0800255GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800256 const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
257 return Model::ExtensionNameAndPrefix{
258 .name = extensionNameAndPrefix.name,
259 .prefix = extensionNameAndPrefix.prefix,
260 };
261}
262
Michael Butler32acc062020-11-22 19:36:30 -0800263GeneralResult<OutputShape> unvalidatedConvert(const hal::V1_2::OutputShape& outputShape) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800264 return OutputShape{
265 .dimensions = outputShape.dimensions,
266 .isSufficient = outputShape.isSufficient,
267 };
268}
269
Michael Butler32acc062020-11-22 19:36:30 -0800270GeneralResult<MeasureTiming> unvalidatedConvert(const hal::V1_2::MeasureTiming& measureTiming) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800271 return static_cast<MeasureTiming>(measureTiming);
272}
273
Michael Butler32acc062020-11-22 19:36:30 -0800274GeneralResult<Timing> unvalidatedConvert(const hal::V1_2::Timing& timing) {
Michael Butlerca114202020-12-04 17:38:20 -0800275 constexpr uint64_t kMaxTiming = std::chrono::floor<HalDuration>(Duration::max()).count();
276 constexpr auto convertTiming = [](uint64_t halTiming) -> OptionalDuration {
277 if (halTiming == kNoTiming) {
278 return {};
279 }
280 if (halTiming > kMaxTiming) {
281 return Duration::max();
282 }
283 return HalDuration{halTiming};
284 };
285 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
286 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlera685c3d2020-02-22 22:37:59 -0800287}
288
Michael Butler32acc062020-11-22 19:36:30 -0800289GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800290 return Extension{
291 .name = extension.name,
Michael Butler32acc062020-11-22 19:36:30 -0800292 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800293 };
294}
295
Michael Butler32acc062020-11-22 19:36:30 -0800296GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800297 const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation) {
298 return Extension::OperandTypeInformation{
299 .type = operandTypeInformation.type,
300 .isTensor = operandTypeInformation.isTensor,
301 .byteSize = operandTypeInformation.byteSize,
302 };
303}
304
Michael Butler32acc062020-11-22 19:36:30 -0800305GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) {
Slava Shklyaevd4290b82020-10-27 18:44:01 +0000306 return hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle());
Michael Butlera685c3d2020-02-22 22:37:59 -0800307}
308
Michael Butler32acc062020-11-22 19:36:30 -0800309GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
310 return validatedConvert(deviceType);
311}
312
313GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities) {
314 return validatedConvert(capabilities);
315}
316
317GeneralResult<Model> convert(const hal::V1_2::Model& model) {
318 return validatedConvert(model);
319}
320
321GeneralResult<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming) {
322 return validatedConvert(measureTiming);
323}
324
325GeneralResult<Timing> convert(const hal::V1_2::Timing& timing) {
326 return validatedConvert(timing);
327}
328
Michael Butler3670c382020-08-06 23:22:35 -0700329GeneralResult<std::vector<Extension>> convert(const hidl_vec<hal::V1_2::Extension>& extensions) {
Michael Butler32acc062020-11-22 19:36:30 -0800330 return validatedConvert(extensions);
Michael Butlera685c3d2020-02-22 22:37:59 -0800331}
332
Slava Shklyaevd4290b82020-10-27 18:44:01 +0000333GeneralResult<std::vector<SharedHandle>> convert(const hidl_vec<hidl_handle>& handles) {
Michael Butler32acc062020-11-22 19:36:30 -0800334 return validatedConvert(handles);
Michael Butlera685c3d2020-02-22 22:37:59 -0800335}
336
Michael Butler3670c382020-08-06 23:22:35 -0700337GeneralResult<std::vector<OutputShape>> convert(
338 const hidl_vec<hal::V1_2::OutputShape>& outputShapes) {
Michael Butler32acc062020-11-22 19:36:30 -0800339 return validatedConvert(outputShapes);
Michael Butlera685c3d2020-02-22 22:37:59 -0800340}
341
342} // namespace android::nn
343
344namespace android::hardware::neuralnetworks::V1_2::utils {
345namespace {
346
Michael Butler32acc062020-11-22 19:36:30 -0800347using utils::unvalidatedConvert;
Michael Butlera685c3d2020-02-22 22:37:59 -0800348
Michael Butler32acc062020-11-22 19:36:30 -0800349nn::GeneralResult<V1_0::OperandLifeTime> unvalidatedConvert(const nn::Operand::LifeTime& lifetime) {
350 return V1_0::utils::unvalidatedConvert(lifetime);
Michael Butlera685c3d2020-02-22 22:37:59 -0800351}
352
Michael Butler32acc062020-11-22 19:36:30 -0800353nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800354 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler32acc062020-11-22 19:36:30 -0800355 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlera685c3d2020-02-22 22:37:59 -0800356}
357
Michael Butler32acc062020-11-22 19:36:30 -0800358nn::GeneralResult<V1_0::DataLocation> unvalidatedConvert(const nn::DataLocation& location) {
359 return V1_0::utils::unvalidatedConvert(location);
Michael Butlera685c3d2020-02-22 22:37:59 -0800360}
361
Michael Butler32acc062020-11-22 19:36:30 -0800362nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
363 const nn::Model::OperandValues& operandValues) {
364 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlera685c3d2020-02-22 22:37:59 -0800365}
366
Michael Butler32acc062020-11-22 19:36:30 -0800367nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory) {
368 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlera685c3d2020-02-22 22:37:59 -0800369}
370
371template <typename Input>
Michael Butler32acc062020-11-22 19:36:30 -0800372using unvalidatedConvertOutput =
373 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlera685c3d2020-02-22 22:37:59 -0800374
375template <typename Type>
Michael Butler32acc062020-11-22 19:36:30 -0800376nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
377 const std::vector<Type>& arguments) {
378 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlera685c3d2020-02-22 22:37:59 -0800379 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler32acc062020-11-22 19:36:30 -0800380 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlera685c3d2020-02-22 22:37:59 -0800381 }
382 return halObject;
383}
384
385template <typename Type>
Michael Butler32acc062020-11-22 19:36:30 -0800386nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
387 const std::vector<Type>& arguments) {
388 return unvalidatedConvertVec(arguments);
Michael Butlera685c3d2020-02-22 22:37:59 -0800389}
390
Michael Butler3670c382020-08-06 23:22:35 -0700391nn::GeneralResult<Operand::ExtraParams> makeExtraParams(nn::Operand::NoParams /*noParams*/) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800392 return Operand::ExtraParams{};
393}
394
Michael Butler3670c382020-08-06 23:22:35 -0700395nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
Michael Butlera685c3d2020-02-22 22:37:59 -0800396 const nn::Operand::SymmPerChannelQuantParams& channelQuant) {
397 Operand::ExtraParams ret;
Michael Butler32acc062020-11-22 19:36:30 -0800398 ret.channelQuant(NN_TRY(unvalidatedConvert(channelQuant)));
Michael Butlera685c3d2020-02-22 22:37:59 -0800399 return ret;
400}
401
Michael Butler3670c382020-08-06 23:22:35 -0700402nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
403 const nn::Operand::ExtensionParams& extension) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800404 Operand::ExtraParams ret;
405 ret.extension(extension);
406 return ret;
407}
408
Michael Butler32acc062020-11-22 19:36:30 -0800409template <typename Type>
410decltype(utils::unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& canonical) {
411 const auto maybeVersion = nn::validate(canonical);
412 if (!maybeVersion.has_value()) {
413 return nn::error() << maybeVersion.error();
414 }
415 const auto version = maybeVersion.value();
416 if (version > kVersion) {
417 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
418 }
419 return utils::unvalidatedConvert(canonical);
420}
421
422template <typename Type>
423nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> validatedConvert(
424 const std::vector<Type>& arguments) {
425 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
426 for (size_t i = 0; i < arguments.size(); ++i) {
427 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
428 }
429 return halObject;
430}
431
Michael Butlera685c3d2020-02-22 22:37:59 -0800432} // anonymous namespace
433
Michael Butler32acc062020-11-22 19:36:30 -0800434nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800435 return static_cast<OperandType>(operandType);
436}
437
Michael Butler32acc062020-11-22 19:36:30 -0800438nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800439 return static_cast<OperationType>(operationType);
440}
441
Michael Butler32acc062020-11-22 19:36:30 -0800442nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800443 switch (deviceType) {
444 case nn::DeviceType::UNKNOWN:
Michael Butler3670c382020-08-06 23:22:35 -0700445 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Invalid DeviceType UNKNOWN";
Michael Butlera685c3d2020-02-22 22:37:59 -0800446 case nn::DeviceType::OTHER:
447 case nn::DeviceType::CPU:
448 case nn::DeviceType::GPU:
449 case nn::DeviceType::ACCELERATOR:
450 return static_cast<DeviceType>(deviceType);
451 }
Michael Butler3670c382020-08-06 23:22:35 -0700452 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
453 << "Invalid DeviceType " << underlyingType(deviceType);
Michael Butlera685c3d2020-02-22 22:37:59 -0800454}
455
Michael Butler32acc062020-11-22 19:36:30 -0800456nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800457 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
458 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
459 std::copy_if(capabilities.operandPerformance.asVector().begin(),
460 capabilities.operandPerformance.asVector().end(),
461 std::back_inserter(operandPerformance),
462 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
463 return nn::validOperandType(operandPerformance.type);
464 });
465
466 return Capabilities{
Michael Butler32acc062020-11-22 19:36:30 -0800467 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
468 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
469 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
470 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
471 .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800472 };
473}
474
Michael Butler32acc062020-11-22 19:36:30 -0800475nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800476 const nn::Capabilities::OperandPerformance& operandPerformance) {
477 return Capabilities::OperandPerformance{
Michael Butler32acc062020-11-22 19:36:30 -0800478 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
479 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800480 };
481}
482
Michael Butler32acc062020-11-22 19:36:30 -0800483nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800484 return Operation{
Michael Butler32acc062020-11-22 19:36:30 -0800485 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800486 .inputs = operation.inputs,
487 .outputs = operation.outputs,
488 };
489}
490
Michael Butler32acc062020-11-22 19:36:30 -0800491nn::GeneralResult<SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800492 const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
493 return SymmPerChannelQuantParams{
494 .scales = symmPerChannelQuantParams.scales,
495 .channelDim = symmPerChannelQuantParams.channelDim,
496 };
497}
498
Michael Butler32acc062020-11-22 19:36:30 -0800499nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800500 return Operand{
Michael Butler32acc062020-11-22 19:36:30 -0800501 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800502 .dimensions = operand.dimensions,
503 .numberOfConsumers = 0,
504 .scale = operand.scale,
505 .zeroPoint = operand.zeroPoint,
Michael Butler32acc062020-11-22 19:36:30 -0800506 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
507 .location = NN_TRY(unvalidatedConvert(operand.location)),
508 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800509 };
510}
511
Michael Butler32acc062020-11-22 19:36:30 -0800512nn::GeneralResult<Operand::ExtraParams> unvalidatedConvert(
513 const nn::Operand::ExtraParams& extraParams) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800514 return std::visit([](const auto& x) { return makeExtraParams(x); }, extraParams);
515}
516
Michael Butler32acc062020-11-22 19:36:30 -0800517nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800518 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler3670c382020-08-06 23:22:35 -0700519 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler32acc062020-11-22 19:36:30 -0800520 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlera685c3d2020-02-22 22:37:59 -0800521 }
522
Michael Butler32acc062020-11-22 19:36:30 -0800523 auto operands = NN_TRY(unvalidatedConvert(model.main.operands));
Michael Butlera685c3d2020-02-22 22:37:59 -0800524
525 // Update number of consumers.
526 const auto numberOfConsumers =
527 hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
528 CHECK(operands.size() == numberOfConsumers.size());
529 for (size_t i = 0; i < operands.size(); ++i) {
530 operands[i].numberOfConsumers = numberOfConsumers[i];
531 }
532
533 return Model{
534 .operands = std::move(operands),
Michael Butler32acc062020-11-22 19:36:30 -0800535 .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800536 .inputIndexes = model.main.inputIndexes,
537 .outputIndexes = model.main.outputIndexes,
Michael Butler32acc062020-11-22 19:36:30 -0800538 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
539 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800540 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler32acc062020-11-22 19:36:30 -0800541 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800542 };
543}
544
Michael Butler32acc062020-11-22 19:36:30 -0800545nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800546 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
547 return Model::ExtensionNameAndPrefix{
548 .name = extensionNameAndPrefix.name,
549 .prefix = extensionNameAndPrefix.prefix,
550 };
551}
552
Michael Butler32acc062020-11-22 19:36:30 -0800553nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800554 return OutputShape{.dimensions = outputShape.dimensions,
555 .isSufficient = outputShape.isSufficient};
556}
557
Michael Butler32acc062020-11-22 19:36:30 -0800558nn::GeneralResult<MeasureTiming> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800559 return static_cast<MeasureTiming>(measureTiming);
560}
561
Michael Butler32acc062020-11-22 19:36:30 -0800562nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
Michael Butlerca114202020-12-04 17:38:20 -0800563 constexpr auto convertTiming = [](nn::OptionalDuration canonicalTiming) -> uint64_t {
564 if (!canonicalTiming.has_value()) {
565 return kNoTiming;
566 }
567 return std::chrono::ceil<HalDuration>(*canonicalTiming).count();
568 };
569 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
570 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlera685c3d2020-02-22 22:37:59 -0800571}
572
Michael Butler32acc062020-11-22 19:36:30 -0800573nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
Michael Butlera685c3d2020-02-22 22:37:59 -0800574 return Extension{
575 .name = extension.name,
Michael Butler32acc062020-11-22 19:36:30 -0800576 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlera685c3d2020-02-22 22:37:59 -0800577 };
578}
579
Michael Butler32acc062020-11-22 19:36:30 -0800580nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlera685c3d2020-02-22 22:37:59 -0800581 const nn::Extension::OperandTypeInformation& operandTypeInformation) {
582 return Extension::OperandTypeInformation{
583 .type = operandTypeInformation.type,
584 .isTensor = operandTypeInformation.isTensor,
585 .byteSize = operandTypeInformation.byteSize,
586 };
587}
588
Michael Butler32acc062020-11-22 19:36:30 -0800589nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
Slava Shklyaevd4290b82020-10-27 18:44:01 +0000590 return hal::utils::hidlHandleFromSharedHandle(handle);
Michael Butlera685c3d2020-02-22 22:37:59 -0800591}
592
Michael Butler32acc062020-11-22 19:36:30 -0800593nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
594 return validatedConvert(deviceType);
595}
596
597nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
598 return validatedConvert(capabilities);
599}
600
601nn::GeneralResult<Model> convert(const nn::Model& model) {
602 return validatedConvert(model);
603}
604
605nn::GeneralResult<MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
606 return validatedConvert(measureTiming);
607}
608
609nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
610 return validatedConvert(timing);
611}
612
Michael Butler3670c382020-08-06 23:22:35 -0700613nn::GeneralResult<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions) {
Michael Butler32acc062020-11-22 19:36:30 -0800614 return validatedConvert(extensions);
Michael Butlera685c3d2020-02-22 22:37:59 -0800615}
616
Slava Shklyaevd4290b82020-10-27 18:44:01 +0000617nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
Michael Butler32acc062020-11-22 19:36:30 -0800618 return validatedConvert(handles);
Michael Butlera685c3d2020-02-22 22:37:59 -0800619}
620
Michael Butler3670c382020-08-06 23:22:35 -0700621nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes) {
Michael Butler32acc062020-11-22 19:36:30 -0800622 return validatedConvert(outputShapes);
Michael Butlera685c3d2020-02-22 22:37:59 -0800623}
624
625} // namespace android::hardware::neuralnetworks::V1_2::utils