blob: c8e83a2fc469fddf68c6eb4578d68f0cb28e2cc0 [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
Michael Butler388bceb2021-02-03 15:15:43 -080040#include "Utils.h"
41
Michael Butlerb98aa6d2020-02-22 22:37:59 -080042namespace {
43
44template <typename Type>
45constexpr std::underlying_type_t<Type> underlyingType(Type value) {
46 return static_cast<std::underlying_type_t<Type>>(value);
47}
48
Michael Butler4024d8f2020-12-04 17:38:20 -080049using HalDuration = std::chrono::duration<uint64_t, std::micro>;
Michael Butler6547b2a2020-11-22 19:36:30 -080050
Michael Butlerb98aa6d2020-02-22 22:37:59 -080051} // namespace
52
53namespace android::nn {
54namespace {
55
Michael Butlerb98aa6d2020-02-22 22:37:59 -080056using hardware::hidl_handle;
57using hardware::hidl_vec;
58
59template <typename Input>
Michael Butler388bceb2021-02-03 15:15:43 -080060using UnvalidatedConvertOutput =
Michael Butler6547b2a2020-11-22 19:36:30 -080061 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080062
63template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -080064GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -080065 const hidl_vec<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -080066 std::vector<UnvalidatedConvertOutput<Type>> canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080067 canonical.reserve(arguments.size());
68 for (const auto& argument : arguments) {
Michael Butler6547b2a2020-11-22 19:36:30 -080069 canonical.push_back(NN_TRY(nn::unvalidatedConvert(argument)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -080070 }
71 return canonical;
72}
73
74template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -080075GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& halObject) {
Michael Butler6547b2a2020-11-22 19:36:30 -080076 auto canonical = NN_TRY(nn::unvalidatedConvert(halObject));
Michael Butler388bceb2021-02-03 15:15:43 -080077 NN_TRY(hal::V1_2::utils::compliantVersion(canonical));
Michael Butler6547b2a2020-11-22 19:36:30 -080078 return canonical;
79}
80
81template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -080082GeneralResult<std::vector<UnvalidatedConvertOutput<Type>>> validatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -080083 const hidl_vec<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -080084 std::vector<UnvalidatedConvertOutput<Type>> canonical;
Michael Butler6547b2a2020-11-22 19:36:30 -080085 canonical.reserve(arguments.size());
86 for (const auto& argument : arguments) {
87 canonical.push_back(NN_TRY(validatedConvert(argument)));
88 }
89 return canonical;
Michael Butlerb98aa6d2020-02-22 22:37:59 -080090}
91
92} // anonymous namespace
93
Michael Butler6547b2a2020-11-22 19:36:30 -080094GeneralResult<OperandType> unvalidatedConvert(const hal::V1_2::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -080095 return static_cast<OperandType>(operandType);
96}
97
Michael Butler6547b2a2020-11-22 19:36:30 -080098GeneralResult<OperationType> unvalidatedConvert(const hal::V1_2::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -080099 return static_cast<OperationType>(operationType);
100}
101
Michael Butler6547b2a2020-11-22 19:36:30 -0800102GeneralResult<DeviceType> unvalidatedConvert(const hal::V1_2::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800103 return static_cast<DeviceType>(deviceType);
104}
105
Michael Butler6547b2a2020-11-22 19:36:30 -0800106GeneralResult<Capabilities> unvalidatedConvert(const hal::V1_2::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800107 const bool validOperandTypes = std::all_of(
108 capabilities.operandPerformance.begin(), capabilities.operandPerformance.end(),
109 [](const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
Michael Butler388bceb2021-02-03 15:15:43 -0800110 return validatedConvert(operandPerformance.type).has_value();
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800111 });
112 if (!validOperandTypes) {
Michael Butler4b276a72020-08-06 23:22:35 -0700113 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800114 << "Invalid OperandType when converting OperandPerformance in Capabilities";
115 }
116
117 const auto relaxedFloat32toFloat16PerformanceScalar =
Michael Butler6547b2a2020-11-22 19:36:30 -0800118 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800119 const auto relaxedFloat32toFloat16PerformanceTensor =
Michael Butler6547b2a2020-11-22 19:36:30 -0800120 NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
121 auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800122
Michael Butlerff9a5a52021-10-15 16:23:20 -0700123 auto table =
124 NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800125
126 return Capabilities{
127 .relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
128 .relaxedFloat32toFloat16PerformanceTensor = relaxedFloat32toFloat16PerformanceTensor,
129 .operandPerformance = std::move(table),
130 };
131}
132
Michael Butler6547b2a2020-11-22 19:36:30 -0800133GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800134 const hal::V1_2::Capabilities::OperandPerformance& operandPerformance) {
135 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800136 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
137 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800138 };
139}
140
Michael Butler6547b2a2020-11-22 19:36:30 -0800141GeneralResult<Operation> unvalidatedConvert(const hal::V1_2::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800142 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800143 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800144 .inputs = operation.inputs,
145 .outputs = operation.outputs,
146 };
147}
148
Michael Butler6547b2a2020-11-22 19:36:30 -0800149GeneralResult<Operand::SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800150 const hal::V1_2::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
151 return Operand::SymmPerChannelQuantParams{
152 .scales = symmPerChannelQuantParams.scales,
153 .channelDim = symmPerChannelQuantParams.channelDim,
154 };
155}
156
Michael Butler6547b2a2020-11-22 19:36:30 -0800157GeneralResult<Operand> unvalidatedConvert(const hal::V1_2::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800158 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800159 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800160 .dimensions = operand.dimensions,
161 .scale = operand.scale,
162 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800163 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
164 .location = NN_TRY(unvalidatedConvert(operand.location)),
165 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800166 };
167}
168
Michael Butler6547b2a2020-11-22 19:36:30 -0800169GeneralResult<Operand::ExtraParams> unvalidatedConvert(
170 const hal::V1_2::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800171 using Discriminator = hal::V1_2::Operand::ExtraParams::hidl_discriminator;
172 switch (extraParams.getDiscriminator()) {
173 case Discriminator::none:
174 return Operand::NoParams{};
175 case Discriminator::channelQuant:
Michael Butler6547b2a2020-11-22 19:36:30 -0800176 return unvalidatedConvert(extraParams.channelQuant());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800177 case Discriminator::extension:
178 return extraParams.extension();
179 }
Michael Butler4b276a72020-08-06 23:22:35 -0700180 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
181 << "Unrecognized Operand::ExtraParams discriminator: "
182 << underlyingType(extraParams.getDiscriminator());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800183}
184
Michael Butler6547b2a2020-11-22 19:36:30 -0800185GeneralResult<Model> unvalidatedConvert(const hal::V1_2::Model& model) {
186 auto operations = NN_TRY(unvalidatedConvert(model.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800187
188 // Verify number of consumers.
189 const auto numberOfConsumers =
Michael Butler301ef062021-10-14 22:04:59 -0700190 NN_TRY(countNumberOfConsumers(model.operands.size(), operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800191 CHECK(model.operands.size() == numberOfConsumers.size());
192 for (size_t i = 0; i < model.operands.size(); ++i) {
193 if (model.operands[i].numberOfConsumers != numberOfConsumers[i]) {
Michael Butler4b276a72020-08-06 23:22:35 -0700194 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
195 << "Invalid numberOfConsumers for operand " << i << ", expected "
196 << numberOfConsumers[i] << " but found " << model.operands[i].numberOfConsumers;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800197 }
198 }
199
200 auto main = Model::Subgraph{
Michael Butler6547b2a2020-11-22 19:36:30 -0800201 .operands = NN_TRY(unvalidatedConvert(model.operands)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800202 .operations = std::move(operations),
203 .inputIndexes = model.inputIndexes,
204 .outputIndexes = model.outputIndexes,
205 };
206
207 return Model{
208 .main = std::move(main),
Michael Butler6547b2a2020-11-22 19:36:30 -0800209 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
210 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800211 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800212 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800213 };
214}
215
Michael Butler6547b2a2020-11-22 19:36:30 -0800216GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800217 const hal::V1_2::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
218 return Model::ExtensionNameAndPrefix{
219 .name = extensionNameAndPrefix.name,
220 .prefix = extensionNameAndPrefix.prefix,
221 };
222}
223
Michael Butler6547b2a2020-11-22 19:36:30 -0800224GeneralResult<OutputShape> unvalidatedConvert(const hal::V1_2::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800225 return OutputShape{
226 .dimensions = outputShape.dimensions,
227 .isSufficient = outputShape.isSufficient,
228 };
229}
230
Michael Butler6547b2a2020-11-22 19:36:30 -0800231GeneralResult<MeasureTiming> unvalidatedConvert(const hal::V1_2::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800232 return static_cast<MeasureTiming>(measureTiming);
233}
234
Michael Butler6547b2a2020-11-22 19:36:30 -0800235GeneralResult<Timing> unvalidatedConvert(const hal::V1_2::Timing& timing) {
Michael Butler4024d8f2020-12-04 17:38:20 -0800236 constexpr uint64_t kMaxTiming = std::chrono::floor<HalDuration>(Duration::max()).count();
237 constexpr auto convertTiming = [](uint64_t halTiming) -> OptionalDuration {
Michael Butler388bceb2021-02-03 15:15:43 -0800238 constexpr uint64_t kNoTiming = std::numeric_limits<uint64_t>::max();
Michael Butler4024d8f2020-12-04 17:38:20 -0800239 if (halTiming == kNoTiming) {
240 return {};
241 }
242 if (halTiming > kMaxTiming) {
243 return Duration::max();
244 }
245 return HalDuration{halTiming};
246 };
247 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
248 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800249}
250
Michael Butler6547b2a2020-11-22 19:36:30 -0800251GeneralResult<Extension> unvalidatedConvert(const hal::V1_2::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800252 return Extension{
253 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800254 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800255 };
256}
257
Michael Butler6547b2a2020-11-22 19:36:30 -0800258GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800259 const hal::V1_2::Extension::OperandTypeInformation& operandTypeInformation) {
260 return Extension::OperandTypeInformation{
261 .type = operandTypeInformation.type,
262 .isTensor = operandTypeInformation.isTensor,
263 .byteSize = operandTypeInformation.byteSize,
264 };
265}
266
Michael Butler6547b2a2020-11-22 19:36:30 -0800267GeneralResult<SharedHandle> unvalidatedConvert(const hidl_handle& hidlHandle) {
Michael Butlerab2f4822021-02-08 00:05:07 -0800268 if (hidlHandle.getNativeHandle() == nullptr) {
269 return nullptr;
270 }
271 auto handle = NN_TRY(hal::utils::sharedHandleFromNativeHandle(hidlHandle.getNativeHandle()));
272 return std::make_shared<const Handle>(std::move(handle));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800273}
274
Michael Butler6547b2a2020-11-22 19:36:30 -0800275GeneralResult<DeviceType> convert(const hal::V1_2::DeviceType& deviceType) {
276 return validatedConvert(deviceType);
277}
278
279GeneralResult<Capabilities> convert(const hal::V1_2::Capabilities& capabilities) {
280 return validatedConvert(capabilities);
281}
282
283GeneralResult<Model> convert(const hal::V1_2::Model& model) {
284 return validatedConvert(model);
285}
286
287GeneralResult<MeasureTiming> convert(const hal::V1_2::MeasureTiming& measureTiming) {
288 return validatedConvert(measureTiming);
289}
290
291GeneralResult<Timing> convert(const hal::V1_2::Timing& timing) {
292 return validatedConvert(timing);
293}
294
Michael Butler76e491f2020-12-19 01:55:32 -0800295GeneralResult<SharedMemory> convert(const hardware::hidl_memory& memory) {
296 return validatedConvert(memory);
297}
298
Michael Butler4b276a72020-08-06 23:22:35 -0700299GeneralResult<std::vector<Extension>> convert(const hidl_vec<hal::V1_2::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800300 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800301}
302
Slava Shklyaev49817a02020-10-27 18:44:01 +0000303GeneralResult<std::vector<SharedHandle>> convert(const hidl_vec<hidl_handle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800304 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800305}
306
Michael Butler4b276a72020-08-06 23:22:35 -0700307GeneralResult<std::vector<OutputShape>> convert(
308 const hidl_vec<hal::V1_2::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800309 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800310}
311
312} // namespace android::nn
313
314namespace android::hardware::neuralnetworks::V1_2::utils {
315namespace {
316
Michael Butler6547b2a2020-11-22 19:36:30 -0800317using utils::unvalidatedConvert;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800318
Michael Butler6547b2a2020-11-22 19:36:30 -0800319nn::GeneralResult<V1_0::OperandLifeTime> unvalidatedConvert(const nn::Operand::LifeTime& lifetime) {
320 return V1_0::utils::unvalidatedConvert(lifetime);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800321}
322
Michael Butler6547b2a2020-11-22 19:36:30 -0800323nn::GeneralResult<V1_0::PerformanceInfo> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800324 const nn::Capabilities::PerformanceInfo& performanceInfo) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800325 return V1_0::utils::unvalidatedConvert(performanceInfo);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800326}
327
Michael Butler6547b2a2020-11-22 19:36:30 -0800328nn::GeneralResult<V1_0::DataLocation> unvalidatedConvert(const nn::DataLocation& location) {
329 return V1_0::utils::unvalidatedConvert(location);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800330}
331
Michael Butler6547b2a2020-11-22 19:36:30 -0800332nn::GeneralResult<hidl_vec<uint8_t>> unvalidatedConvert(
333 const nn::Model::OperandValues& operandValues) {
334 return V1_0::utils::unvalidatedConvert(operandValues);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800335}
336
Michael Butlerfadeb8a2021-02-07 00:11:13 -0800337nn::GeneralResult<hidl_memory> unvalidatedConvert(const nn::SharedMemory& memory) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800338 return V1_0::utils::unvalidatedConvert(memory);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800339}
340
341template <typename Input>
Michael Butler388bceb2021-02-03 15:15:43 -0800342using UnvalidatedConvertOutput =
Michael Butler6547b2a2020-11-22 19:36:30 -0800343 std::decay_t<decltype(unvalidatedConvert(std::declval<Input>()).value())>;
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800344
345template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -0800346nn::GeneralResult<hidl_vec<UnvalidatedConvertOutput<Type>>> unvalidatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -0800347 const std::vector<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -0800348 hidl_vec<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800349 for (size_t i = 0; i < arguments.size(); ++i) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800350 halObject[i] = NN_TRY(unvalidatedConvert(arguments[i]));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800351 }
352 return halObject;
353}
354
Michael Butler4b276a72020-08-06 23:22:35 -0700355nn::GeneralResult<Operand::ExtraParams> makeExtraParams(nn::Operand::NoParams /*noParams*/) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800356 return Operand::ExtraParams{};
357}
358
Michael Butler4b276a72020-08-06 23:22:35 -0700359nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800360 const nn::Operand::SymmPerChannelQuantParams& channelQuant) {
361 Operand::ExtraParams ret;
Michael Butler6547b2a2020-11-22 19:36:30 -0800362 ret.channelQuant(NN_TRY(unvalidatedConvert(channelQuant)));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800363 return ret;
364}
365
Michael Butler4b276a72020-08-06 23:22:35 -0700366nn::GeneralResult<Operand::ExtraParams> makeExtraParams(
367 const nn::Operand::ExtensionParams& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800368 Operand::ExtraParams ret;
369 ret.extension(extension);
370 return ret;
371}
372
Michael Butler6547b2a2020-11-22 19:36:30 -0800373template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -0800374nn::GeneralResult<UnvalidatedConvertOutput<Type>> validatedConvert(const Type& canonical) {
375 NN_TRY(compliantVersion(canonical));
376 return unvalidatedConvert(canonical);
Michael Butler6547b2a2020-11-22 19:36:30 -0800377}
378
379template <typename Type>
Michael Butler388bceb2021-02-03 15:15:43 -0800380nn::GeneralResult<hidl_vec<UnvalidatedConvertOutput<Type>>> validatedConvert(
Michael Butler6547b2a2020-11-22 19:36:30 -0800381 const std::vector<Type>& arguments) {
Michael Butler388bceb2021-02-03 15:15:43 -0800382 hidl_vec<UnvalidatedConvertOutput<Type>> halObject(arguments.size());
Michael Butler6547b2a2020-11-22 19:36:30 -0800383 for (size_t i = 0; i < arguments.size(); ++i) {
384 halObject[i] = NN_TRY(validatedConvert(arguments[i]));
385 }
386 return halObject;
387}
388
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800389} // anonymous namespace
390
Michael Butler6547b2a2020-11-22 19:36:30 -0800391nn::GeneralResult<OperandType> unvalidatedConvert(const nn::OperandType& operandType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800392 return static_cast<OperandType>(operandType);
393}
394
Michael Butler6547b2a2020-11-22 19:36:30 -0800395nn::GeneralResult<OperationType> unvalidatedConvert(const nn::OperationType& operationType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800396 return static_cast<OperationType>(operationType);
397}
398
Michael Butler6547b2a2020-11-22 19:36:30 -0800399nn::GeneralResult<DeviceType> unvalidatedConvert(const nn::DeviceType& deviceType) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800400 switch (deviceType) {
401 case nn::DeviceType::UNKNOWN:
Michael Butler4b276a72020-08-06 23:22:35 -0700402 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE) << "Invalid DeviceType UNKNOWN";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800403 case nn::DeviceType::OTHER:
404 case nn::DeviceType::CPU:
405 case nn::DeviceType::GPU:
406 case nn::DeviceType::ACCELERATOR:
407 return static_cast<DeviceType>(deviceType);
408 }
Michael Butler4b276a72020-08-06 23:22:35 -0700409 return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
410 << "Invalid DeviceType " << underlyingType(deviceType);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800411}
412
Michael Butler6547b2a2020-11-22 19:36:30 -0800413nn::GeneralResult<Capabilities> unvalidatedConvert(const nn::Capabilities& capabilities) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800414 std::vector<nn::Capabilities::OperandPerformance> operandPerformance;
415 operandPerformance.reserve(capabilities.operandPerformance.asVector().size());
416 std::copy_if(capabilities.operandPerformance.asVector().begin(),
417 capabilities.operandPerformance.asVector().end(),
418 std::back_inserter(operandPerformance),
419 [](const nn::Capabilities::OperandPerformance& operandPerformance) {
Michael Butler388bceb2021-02-03 15:15:43 -0800420 return compliantVersion(operandPerformance.type).has_value();
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800421 });
422
423 return Capabilities{
Michael Butler6547b2a2020-11-22 19:36:30 -0800424 .relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
425 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceScalar)),
426 .relaxedFloat32toFloat16PerformanceTensor = NN_TRY(
427 unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor)),
428 .operandPerformance = NN_TRY(unvalidatedConvert(operandPerformance)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800429 };
430}
431
Michael Butler6547b2a2020-11-22 19:36:30 -0800432nn::GeneralResult<Capabilities::OperandPerformance> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800433 const nn::Capabilities::OperandPerformance& operandPerformance) {
434 return Capabilities::OperandPerformance{
Michael Butler6547b2a2020-11-22 19:36:30 -0800435 .type = NN_TRY(unvalidatedConvert(operandPerformance.type)),
436 .info = NN_TRY(unvalidatedConvert(operandPerformance.info)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800437 };
438}
439
Michael Butler6547b2a2020-11-22 19:36:30 -0800440nn::GeneralResult<Operation> unvalidatedConvert(const nn::Operation& operation) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800441 return Operation{
Michael Butler6547b2a2020-11-22 19:36:30 -0800442 .type = NN_TRY(unvalidatedConvert(operation.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800443 .inputs = operation.inputs,
444 .outputs = operation.outputs,
445 };
446}
447
Michael Butler6547b2a2020-11-22 19:36:30 -0800448nn::GeneralResult<SymmPerChannelQuantParams> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800449 const nn::Operand::SymmPerChannelQuantParams& symmPerChannelQuantParams) {
450 return SymmPerChannelQuantParams{
451 .scales = symmPerChannelQuantParams.scales,
452 .channelDim = symmPerChannelQuantParams.channelDim,
453 };
454}
455
Michael Butler6547b2a2020-11-22 19:36:30 -0800456nn::GeneralResult<Operand> unvalidatedConvert(const nn::Operand& operand) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800457 return Operand{
Michael Butler6547b2a2020-11-22 19:36:30 -0800458 .type = NN_TRY(unvalidatedConvert(operand.type)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800459 .dimensions = operand.dimensions,
460 .numberOfConsumers = 0,
461 .scale = operand.scale,
462 .zeroPoint = operand.zeroPoint,
Michael Butler6547b2a2020-11-22 19:36:30 -0800463 .lifetime = NN_TRY(unvalidatedConvert(operand.lifetime)),
464 .location = NN_TRY(unvalidatedConvert(operand.location)),
465 .extraParams = NN_TRY(unvalidatedConvert(operand.extraParams)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800466 };
467}
468
Michael Butler6547b2a2020-11-22 19:36:30 -0800469nn::GeneralResult<Operand::ExtraParams> unvalidatedConvert(
470 const nn::Operand::ExtraParams& extraParams) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800471 return std::visit([](const auto& x) { return makeExtraParams(x); }, extraParams);
472}
473
Michael Butler6547b2a2020-11-22 19:36:30 -0800474nn::GeneralResult<Model> unvalidatedConvert(const nn::Model& model) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800475 if (!hal::utils::hasNoPointerData(model)) {
Michael Butler4b276a72020-08-06 23:22:35 -0700476 return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
Michael Butler6547b2a2020-11-22 19:36:30 -0800477 << "Model cannot be unvalidatedConverted because it contains pointer-based memory";
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800478 }
479
Michael Butler6547b2a2020-11-22 19:36:30 -0800480 auto operands = NN_TRY(unvalidatedConvert(model.main.operands));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800481
482 // Update number of consumers.
483 const auto numberOfConsumers =
Michael Butler301ef062021-10-14 22:04:59 -0700484 NN_TRY(countNumberOfConsumers(operands.size(), model.main.operations));
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800485 CHECK(operands.size() == numberOfConsumers.size());
486 for (size_t i = 0; i < operands.size(); ++i) {
487 operands[i].numberOfConsumers = numberOfConsumers[i];
488 }
489
490 return Model{
491 .operands = std::move(operands),
Michael Butler6547b2a2020-11-22 19:36:30 -0800492 .operations = NN_TRY(unvalidatedConvert(model.main.operations)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800493 .inputIndexes = model.main.inputIndexes,
494 .outputIndexes = model.main.outputIndexes,
Michael Butler6547b2a2020-11-22 19:36:30 -0800495 .operandValues = NN_TRY(unvalidatedConvert(model.operandValues)),
496 .pools = NN_TRY(unvalidatedConvert(model.pools)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800497 .relaxComputationFloat32toFloat16 = model.relaxComputationFloat32toFloat16,
Michael Butler6547b2a2020-11-22 19:36:30 -0800498 .extensionNameToPrefix = NN_TRY(unvalidatedConvert(model.extensionNameToPrefix)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800499 };
500}
501
Michael Butler6547b2a2020-11-22 19:36:30 -0800502nn::GeneralResult<Model::ExtensionNameAndPrefix> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800503 const nn::Model::ExtensionNameAndPrefix& extensionNameAndPrefix) {
504 return Model::ExtensionNameAndPrefix{
505 .name = extensionNameAndPrefix.name,
506 .prefix = extensionNameAndPrefix.prefix,
507 };
508}
509
Michael Butler6547b2a2020-11-22 19:36:30 -0800510nn::GeneralResult<OutputShape> unvalidatedConvert(const nn::OutputShape& outputShape) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800511 return OutputShape{.dimensions = outputShape.dimensions,
512 .isSufficient = outputShape.isSufficient};
513}
514
Michael Butler6547b2a2020-11-22 19:36:30 -0800515nn::GeneralResult<MeasureTiming> unvalidatedConvert(const nn::MeasureTiming& measureTiming) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800516 return static_cast<MeasureTiming>(measureTiming);
517}
518
Michael Butler6547b2a2020-11-22 19:36:30 -0800519nn::GeneralResult<Timing> unvalidatedConvert(const nn::Timing& timing) {
Michael Butler4024d8f2020-12-04 17:38:20 -0800520 constexpr auto convertTiming = [](nn::OptionalDuration canonicalTiming) -> uint64_t {
Michael Butler388bceb2021-02-03 15:15:43 -0800521 constexpr uint64_t kNoTiming = std::numeric_limits<uint64_t>::max();
Michael Butler4024d8f2020-12-04 17:38:20 -0800522 if (!canonicalTiming.has_value()) {
523 return kNoTiming;
524 }
525 return std::chrono::ceil<HalDuration>(*canonicalTiming).count();
526 };
527 return Timing{.timeOnDevice = convertTiming(timing.timeOnDevice),
528 .timeInDriver = convertTiming(timing.timeInDriver)};
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800529}
530
Michael Butler6547b2a2020-11-22 19:36:30 -0800531nn::GeneralResult<Extension> unvalidatedConvert(const nn::Extension& extension) {
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800532 return Extension{
533 .name = extension.name,
Michael Butler6547b2a2020-11-22 19:36:30 -0800534 .operandTypes = NN_TRY(unvalidatedConvert(extension.operandTypes)),
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800535 };
536}
537
Michael Butler6547b2a2020-11-22 19:36:30 -0800538nn::GeneralResult<Extension::OperandTypeInformation> unvalidatedConvert(
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800539 const nn::Extension::OperandTypeInformation& operandTypeInformation) {
540 return Extension::OperandTypeInformation{
541 .type = operandTypeInformation.type,
542 .isTensor = operandTypeInformation.isTensor,
543 .byteSize = operandTypeInformation.byteSize,
544 };
545}
546
Michael Butler6547b2a2020-11-22 19:36:30 -0800547nn::GeneralResult<hidl_handle> unvalidatedConvert(const nn::SharedHandle& handle) {
Michael Butlerab2f4822021-02-08 00:05:07 -0800548 if (handle == nullptr) {
549 return {};
550 }
551 return hal::utils::hidlHandleFromSharedHandle(*handle);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800552}
553
Michael Butler6547b2a2020-11-22 19:36:30 -0800554nn::GeneralResult<DeviceType> convert(const nn::DeviceType& deviceType) {
555 return validatedConvert(deviceType);
556}
557
558nn::GeneralResult<Capabilities> convert(const nn::Capabilities& capabilities) {
559 return validatedConvert(capabilities);
560}
561
562nn::GeneralResult<Model> convert(const nn::Model& model) {
563 return validatedConvert(model);
564}
565
566nn::GeneralResult<MeasureTiming> convert(const nn::MeasureTiming& measureTiming) {
567 return validatedConvert(measureTiming);
568}
569
570nn::GeneralResult<Timing> convert(const nn::Timing& timing) {
571 return validatedConvert(timing);
572}
573
Michael Butler4b276a72020-08-06 23:22:35 -0700574nn::GeneralResult<hidl_vec<Extension>> convert(const std::vector<nn::Extension>& extensions) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800575 return validatedConvert(extensions);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800576}
577
Slava Shklyaev49817a02020-10-27 18:44:01 +0000578nn::GeneralResult<hidl_vec<hidl_handle>> convert(const std::vector<nn::SharedHandle>& handles) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800579 return validatedConvert(handles);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800580}
581
Michael Butler4b276a72020-08-06 23:22:35 -0700582nn::GeneralResult<hidl_vec<OutputShape>> convert(const std::vector<nn::OutputShape>& outputShapes) {
Michael Butler6547b2a2020-11-22 19:36:30 -0800583 return validatedConvert(outputShapes);
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800584}
585
Michael Butler7fd03c22020-12-06 21:50:59 -0800586nn::GeneralResult<V1_0::DeviceStatus> convert(const nn::DeviceStatus& deviceStatus) {
587 return V1_1::utils::convert(deviceStatus);
588}
589
590nn::GeneralResult<V1_0::Request> convert(const nn::Request& request) {
591 return V1_1::utils::convert(request);
592}
593
594nn::GeneralResult<V1_0::ErrorStatus> convert(const nn::ErrorStatus& status) {
595 return V1_1::utils::convert(status);
596}
597
598nn::GeneralResult<V1_1::ExecutionPreference> convert(
599 const nn::ExecutionPreference& executionPreference) {
600 return V1_1::utils::convert(executionPreference);
601}
602
Michael Butlerb98aa6d2020-02-22 22:37:59 -0800603} // namespace android::hardware::neuralnetworks::V1_2::utils