blob: f11474fd60238bc1b471d19a19dfc17950127657 [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>
29#include <nnapi/hal/CommonUtils.h>
Michael Butler4b276a72020-08-06 23:22:35 -070030#include <nnapi/hal/HandleError.h>
Michael Butlerb98aa6d2020-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 Butler6547b2a2020-11-22 19:36:30 -080046constexpr auto kVersion = android::nn::Version::ANDROID_Q;
47
Michael Butlerb98aa6d2020-02-22 22:37:59 -080048} // namespace
49
50namespace android::nn {
51namespace {
52
53constexpr bool validOperandType(OperandType operandType) {
54 switch (operandType) {
55 case OperandType::FLOAT32:
56 case OperandType::INT32:
57 case OperandType::UINT32:
58 case OperandType::TENSOR_FLOAT32:
59 case OperandType::TENSOR_INT32:
60 case OperandType::TENSOR_QUANT8_ASYMM:
61 case OperandType::BOOL:
62 case OperandType::TENSOR_QUANT16_SYMM:
63 case OperandType::TENSOR_FLOAT16:
64 case OperandType::TENSOR_BOOL8:
65 case OperandType::FLOAT16:
66 case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
67 case OperandType::TENSOR_QUANT16_ASYMM:
68 case OperandType::TENSOR_QUANT8_SYMM:
69 case OperandType::OEM:
70 case OperandType::TENSOR_OEM_BYTE:
71 return true;
72 default:
73 break;
74 }
75 return isExtension(operandType);
76}
77
78using hardware::hidl_handle;
79using hardware::hidl_vec;
80
81template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -080082using unvalidatedConvertOutput =
83 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080084
85template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -080086GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
87 const hidl_vec<Type>& arguments) {
88 std::vector<unvalidatedConvertOutput<Type>> canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080089 canonical.reserve(arguments.size());
90 for (const auto& argument : arguments) {
Michael Butler6547b2a2020-11-22 19:36:30 -080091 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -080092 }
93 return canonical;
94}
95
96template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -080097GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
98 const hidl_vec<Type>& arguments) {
99 return unvalidatedConvertVec(arguments);
100}
101
102template <typename Type>
103decltype(nn::unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& halObject) {
104 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
105 const auto maybeVersion = validate(canonical);
106 if (!maybeVersion.has_value()) {
107 return error() << maybeVersion.error();
108 }
109 const auto version = maybeVersion.value();
110 if (version > kVersion) {
111 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
112 }
113 return canonical;
114}
115
116template <typename Type>
117GeneralResult<std::vector<unvalidatedConvertOutput<Type>>> validatedConvert(
118 const hidl_vec<Type>& arguments) {
119 std::vector<unvalidatedConvertOutput<Type>> canonical;
120 canonical.reserve(arguments.size());
121 for (const auto& argument : arguments) {
122 canonical.push_back(NN_TRY(validatedConvert(argument)));
123 }
124 return canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800125}
126
127} // anonymous namespace
128
Michael Butler6547b2a2020-11-22 19:36:30 -0800129GeneralResult<OperandType> unvalidatedConvert(const hal::V1_2::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800130 return static_cast<OperandType>(operandType);
131}
132
Michael Butler6547b2a2020-11-22 19:36:30 -0800133GeneralResult<OperationType> unvalidatedConvert(const hal::V1_2::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800134 return static_cast<OperationType>(operationType);
135}
136
Michael Butler6547b2a2020-11-22 19:36:30 -0800137GeneralResult<DeviceType> unvalidatedConvert(const hal::V1_2::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800138 return static_cast<DeviceType>(deviceType);
139}
140
Michael Butler6547b2a2020-11-22 19:36:30 -0800141GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_2::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800142 const bool validOperandTypes = std::all_of(
143 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
144 [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800145 const auto maybeType = unvalidatedConvert(operandPerformance.type);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800146 return !maybeType.has_value() ? false : validOperandType(maybeType.value());
147 });
148 if (!validOperandTypes) {
Michael Butler4b276a72020-08-06 23:22:35 -0700149 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800150 << "Invalid OperandType when converting OperandPerformance in Capabilities";
151 }
152
153 const auto relaxedFloat32toFloat16PerformanceScalar =
Michael Butler6547b2a2020-11-22 19:36:30 -0800154 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800155 const auto relaxedFloat32toFloat16PerformanceTensor =
Michael Butler6547b2a2020-11-22 19:36:30 -0800156 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
157 auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800158
Michael Butler4b276a72020-08-06 23:22:35 -0700159 auto table = NN_TRY(hal::utils::makeGeneralFailure(
160 Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
161 nn::ErrorStatus::GENERAL_FAILURE));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800162
163 return Capabilities{
164 .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
165 .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
166 .operandPerformance = std::move(table),
167 };
168}
169
Michael Butler6547b2a2020-11-22 19:36:30 -0800170GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800171 const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
172 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800173 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
174 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800175 };
176}
177
Michael Butler6547b2a2020-11-22 19:36:30 -0800178GeneralResult<Operation> unvalidatedConvert(const hal::V1_2::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800179 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800180 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800181 .inputs = operation.inputs,
182 .outputs = operation.outputs,
183 };
184}
185
Michael Butler6547b2a2020-11-22 19:36:30 -0800186GeneralResult<Operand::SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800187 const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
188 return Operand::SymmPerChannelQuantParams{
189 .scales = symmPerChannelQuantParams.scales,
190 .channelDim = symmPerChannelQuantParams.channelDim,
191 };
192}
193
Michael Butler6547b2a2020-11-22 19:36:30 -0800194GeneralResult<Operand> unvalidatedConvert(const hal::V1_2::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800195 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800196 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800197 .dimensions = operand.dimensions,
198 .scale = operand.scale,
199 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800200 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
201 .location = NN_TRY(unvalidatedConvert(operand.location)),
202 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800203 };
204}
205
Michael Butler6547b2a2020-11-22 19:36:30 -0800206GeneralResult<Operand::ExtraParams> unvalidatedConvert(
207 const hal::V1_2::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800208 using Discriminator = hal::V1_2::Operand::ExtraParams::hidl_discriminator;
209 switch (extraParams.getDiscriminator()) {
210 case Discriminator::none:
211 return Operand::NoParams{};
212 case Discriminator::channelQuant:
Michael Butler6547b2a2020-11-22 19:36:30 -0800213 return unvalidatedConvert(extraParams.channelQuant());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800214 case Discriminator::extension:
215 return extraParams.extension();
216 }
Michael Butler4b276a72020-08-06 23:22:35 -0700217 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
218 << "Unrecognized Operand::ExtraParams discriminator: "
219 << underlyingType(extraParams.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800220}
221
Michael Butler6547b2a2020-11-22 19:36:30 -0800222GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model) {
223 auto operations = NN_TRY(unvalidatedConvert(model.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800224
225 // Verify number of consumers.
226 const auto numberOfConsumers =
227 hal::utils::countNumberOfConsumers(model.operands.size(), operations);
228 CHECK(model.operands.size() == numberOfConsumers.size());
229 for (size_t i = 0; i < model.operands.size(); ++i) {
230 if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler4b276a72020-08-06 23:22:35 -0700231 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
232 << "Invalid numberOfConsumers for operand " << i << ", expected "
233 << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800234 }
235 }
236
237 auto main = Model::Subgraph{
Michael Butler6547b2a2020-11-22 19:36:30 -0800238 .operands = NN_TRY(unvalidatedConvert(model.operands)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800239 .operations = std::move(operations),
240 .inputIndexes = model.inputIndexes,
241 .outputIndexes = model.outputIndexes,
242 };
243
244 return Model{
245 .main = std::move(main),
Michael Butler6547b2a2020-11-22 19:36:30 -0800246 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
247 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800248 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800249 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800250 };
251}
252
Michael Butler6547b2a2020-11-22 19:36:30 -0800253GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800254 const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
255 return Model::ExtensionNameAndPrefix{
256 .name = extensionNameAndPrefix.name,
257 .prefix = extensionNameAndPrefix.prefix,
258 };
259}
260
Michael Butler6547b2a2020-11-22 19:36:30 -0800261GeneralResult<OutputShape> unvalidatedConvert(const hal::V1_2::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800262 return OutputShape{
263 .dimensions = outputShape.dimensions,
264 .isSufficient = outputShape.isSufficient,
265 };
266}
267
Michael Butler6547b2a2020-11-22 19:36:30 -0800268GeneralResult<MeasureTiming> unvalidatedConvert(const hal::V1_2::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800269 return static_cast<MeasureTiming>(measureTiming);
270}
271
Michael Butler6547b2a2020-11-22 19:36:30 -0800272GeneralResult<Timing> unvalidatedConvert(const hal::V1_2::Timing& timing) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800273 return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
274}
275
Michael Butler6547b2a2020-11-22 19:36:30 -0800276GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800277 return Extension{
278 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800279 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800280 };
281}
282
Michael Butler6547b2a2020-11-22 19:36:30 -0800283GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800284 const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation) {
285 return Extension::OperandTypeInformation{
286 .type = operandTypeInformation.type,
287 .isTensor = operandTypeInformation.isTensor,
288 .byteSize = operandTypeInformation.byteSize,
289 };
290}
291
Michael Butler6547b2a2020-11-22 19:36:30 -0800292GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) {
Slava Shklyaev49817a02020-10-27 18:44:01 +0000293 return hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800294}
295
Michael Butler6547b2a2020-11-22 19:36:30 -0800296GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
297 return validatedConvert(deviceType);
298}
299
300GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities) {
301 return validatedConvert(capabilities);
302}
303
304GeneralResult<Model> convert(const hal::V1_2::Model& model) {
305 return validatedConvert(model);
306}
307
308GeneralResult<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming) {
309 return validatedConvert(measureTiming);
310}
311
312GeneralResult<Timing> convert(const hal::V1_2::Timing& timing) {
313 return validatedConvert(timing);
314}
315
Michael Butler4b276a72020-08-06 23:22:35 -0700316GeneralResult<std::vector<Extension>> convert(const hidl_vec<hal::V1_2::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800317 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800318}
319
Slava Shklyaev49817a02020-10-27 18:44:01 +0000320GeneralResult<std::vector<SharedHandle>> convert(const hidl_vec<hidl_handle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800321 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800322}
323
Michael Butler4b276a72020-08-06 23:22:35 -0700324GeneralResult<std::vector<OutputShape>> convert(
325 const hidl_vec<hal::V1_2::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800326 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800327}
328
329} // namespace android::nn
330
331namespace android::hardware::neuralnetworks::V1_2::utils {
332namespace {
333
Michael Butler6547b2a2020-11-22 19:36:30 -0800334using utils::unvalidatedConvert;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800335
Michael Butler6547b2a2020-11-22 19:36:30 -0800336nn::GeneralResult<V1_0::OperandLifeTime> unvalidatedConvert(const nn::Operand::LifeTime& lifetime) {
337 return V1_0::utils::unvalidatedConvert(lifetime);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800338}
339
Michael Butler6547b2a2020-11-22 19:36:30 -0800340nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800341 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800342 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800343}
344
Michael Butler6547b2a2020-11-22 19:36:30 -0800345nn::GeneralResult<V1_0::DataLocation> unvalidatedConvert(const nn::DataLocation& location) {
346 return V1_0::utils::unvalidatedConvert(location);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800347}
348
Michael Butler6547b2a2020-11-22 19:36:30 -0800349nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
350 const nn::Model::OperandValues& operandValues) {
351 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800352}
353
Michael Butler6547b2a2020-11-22 19:36:30 -0800354nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::Memory& memory) {
355 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800356}
357
358template <typename Input>
Michael Butler6547b2a2020-11-22 19:36:30 -0800359using unvalidatedConvertOutput =
360 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800361
362template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800363nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvertVec(
364 const std::vector<Type>& arguments) {
365 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800366 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800367 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800368 }
369 return halObject;
370}
371
372template <typename Type>
Michael Butler6547b2a2020-11-22 19:36:30 -0800373nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> unvalidatedConvert(
374 const std::vector<Type>& arguments) {
375 return unvalidatedConvertVec(arguments);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800376}
377
Michael Butler4b276a72020-08-06 23:22:35 -0700378nn::GeneralResult<Operand::ExtraParams> makeExtraParams(nn::Operand::NoParams /*noParams*/) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800379 return Operand::ExtraParams{};
380}
381
Michael Butler4b276a72020-08-06 23:22:35 -0700382nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800383 const nn::Operand::SymmPerChannelQuantParams& channelQuant) {
384 Operand::ExtraParams ret;
Michael Butler6547b2a2020-11-22 19:36:30 -0800385 ret.channelQuant(NN_TRY(unvalidatedConvert(channelQuant)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800386 return ret;
387}
388
Michael Butler4b276a72020-08-06 23:22:35 -0700389nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
390 const nn::Operand::ExtensionParams& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800391 Operand::ExtraParams ret;
392 ret.extension(extension);
393 return ret;
394}
395
Michael Butler6547b2a2020-11-22 19:36:30 -0800396template <typename Type>
397decltype(utils::unvalidatedConvert(std::declval<Type>())) validatedConvert(const Type& canonical) {
398 const auto maybeVersion = nn::validate(canonical);
399 if (!maybeVersion.has_value()) {
400 return nn::error() << maybeVersion.error();
401 }
402 const auto version = maybeVersion.value();
403 if (version > kVersion) {
404 return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
405 }
406 return utils::unvalidatedConvert(canonical);
407}
408
409template <typename Type>
410nn::GeneralResult<hidl_vec<unvalidatedConvertOutput<Type>>> validatedConvert(
411 const std::vector<Type>& arguments) {
412 hidl_vec<unvalidatedConvertOutput<Type>> halObject(arguments.size());
413 for (size_t i = 0; i < arguments.size(); ++i) {
414 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
415 }
416 return halObject;
417}
418
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800419} // anonymous namespace
420
Michael Butler6547b2a2020-11-22 19:36:30 -0800421nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800422 return static_cast<OperandType>(operandType);
423}
424
Michael Butler6547b2a2020-11-22 19:36:30 -0800425nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800426 return static_cast<OperationType>(operationType);
427}
428
Michael Butler6547b2a2020-11-22 19:36:30 -0800429nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800430 switch (deviceType) {
431 case nn::DeviceType::UNKNOWN:
Michael Butler4b276a72020-08-06 23:22:35 -0700432 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Invalid DeviceType UNKNOWN";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800433 case nn::DeviceType::OTHER:
434 case nn::DeviceType::CPU:
435 case nn::DeviceType::GPU:
436 case nn::DeviceType::ACCELERATOR:
437 return static_cast<DeviceType>(deviceType);
438 }
Michael Butler4b276a72020-08-06 23:22:35 -0700439 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
440 << "Invalid DeviceType " << underlyingType(deviceType);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800441}
442
Michael Butler6547b2a2020-11-22 19:36:30 -0800443nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800444 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
445 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
446 std::copy_if(capabilities.operandPerformance.asVector().begin(),
447 capabilities.operandPerformance.asVector().end(),
448 std::back_inserter(operandPerformance),
449 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
450 return nn::validOperandType(operandPerformance.type);
451 });
452
453 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800454 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
455 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
456 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
457 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
458 .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800459 };
460}
461
Michael Butler6547b2a2020-11-22 19:36:30 -0800462nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800463 const nn::Capabilities::OperandPerformance& operandPerformance) {
464 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800465 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
466 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800467 };
468}
469
Michael Butler6547b2a2020-11-22 19:36:30 -0800470nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800471 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800472 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800473 .inputs = operation.inputs,
474 .outputs = operation.outputs,
475 };
476}
477
Michael Butler6547b2a2020-11-22 19:36:30 -0800478nn::GeneralResult<SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800479 const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
480 return SymmPerChannelQuantParams{
481 .scales = symmPerChannelQuantParams.scales,
482 .channelDim = symmPerChannelQuantParams.channelDim,
483 };
484}
485
Michael Butler6547b2a2020-11-22 19:36:30 -0800486nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800487 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800488 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800489 .dimensions = operand.dimensions,
490 .numberOfConsumers = 0,
491 .scale = operand.scale,
492 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800493 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
494 .location = NN_TRY(unvalidatedConvert(operand.location)),
495 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800496 };
497}
498
Michael Butler6547b2a2020-11-22 19:36:30 -0800499nn::GeneralResult<Operand::ExtraParams> unvalidatedConvert(
500 const nn::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800501 return std::visit([](const auto& x) { return makeExtraParams(x); }, extraParams);
502}
503
Michael Butler6547b2a2020-11-22 19:36:30 -0800504nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800505 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700506 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800507 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800508 }
509
Michael Butler6547b2a2020-11-22 19:36:30 -0800510 auto operands = NN_TRY(unvalidatedConvert(model.main.operands));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800511
512 // Update number of consumers.
513 const auto numberOfConsumers =
514 hal::utils::countNumberOfConsumers(operands.size(), model.main.operations);
515 CHECK(operands.size() == numberOfConsumers.size());
516 for (size_t i = 0; i < operands.size(); ++i) {
517 operands[i].numberOfConsumers = numberOfConsumers[i];
518 }
519
520 return Model{
521 .operands = std::move(operands),
Michael Butler6547b2a2020-11-22 19:36:30 -0800522 .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800523 .inputIndexes = model.main.inputIndexes,
524 .outputIndexes = model.main.outputIndexes,
Michael Butler6547b2a2020-11-22 19:36:30 -0800525 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
526 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800527 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800528 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800529 };
530}
531
Michael Butler6547b2a2020-11-22 19:36:30 -0800532nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800533 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
534 return Model::ExtensionNameAndPrefix{
535 .name = extensionNameAndPrefix.name,
536 .prefix = extensionNameAndPrefix.prefix,
537 };
538}
539
Michael Butler6547b2a2020-11-22 19:36:30 -0800540nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800541 return OutputShape{.dimensions = outputShape.dimensions,
542 .isSufficient = outputShape.isSufficient};
543}
544
Michael Butler6547b2a2020-11-22 19:36:30 -0800545nn::GeneralResult<MeasureTiming> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800546 return static_cast<MeasureTiming>(measureTiming);
547}
548
Michael Butler6547b2a2020-11-22 19:36:30 -0800549nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800550 return Timing{.timeOnDevice = timing.timeOnDevice, .timeInDriver = timing.timeInDriver};
551}
552
Michael Butler6547b2a2020-11-22 19:36:30 -0800553nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800554 return Extension{
555 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800556 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800557 };
558}
559
Michael Butler6547b2a2020-11-22 19:36:30 -0800560nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800561 const nn::Extension::OperandTypeInformation& operandTypeInformation) {
562 return Extension::OperandTypeInformation{
563 .type = operandTypeInformation.type,
564 .isTensor = operandTypeInformation.isTensor,
565 .byteSize = operandTypeInformation.byteSize,
566 };
567}
568
Michael Butler6547b2a2020-11-22 19:36:30 -0800569nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
Slava Shklyaev49817a02020-10-27 18:44:01 +0000570 return hal::utils::hidlHandleFromSharedHandle(handle);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800571}
572
Michael Butler6547b2a2020-11-22 19:36:30 -0800573nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
574 return validatedConvert(deviceType);
575}
576
577nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
578 return validatedConvert(capabilities);
579}
580
581nn::GeneralResult<Model> convert(const nn::Model& model) {
582 return validatedConvert(model);
583}
584
585nn::GeneralResult<MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
586 return validatedConvert(measureTiming);
587}
588
589nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
590 return validatedConvert(timing);
591}
592
Michael Butler4b276a72020-08-06 23:22:35 -0700593nn::GeneralResult<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800594 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800595}
596
Slava Shklyaev49817a02020-10-27 18:44:01 +0000597nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800598 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800599}
600
Michael Butler4b276a72020-08-06 23:22:35 -0700601nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800602 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800603}
604
605} // namespace android::hardware::neuralnetworks::V1_2::utils