1 /* 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 #ifndef ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H 18 #define ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H 19 20 #include <cutils/native_handle.h> 21 #include <hidl/HidlSupport.h> 22 #include <nnapi/Result.h> 23 #include <nnapi/SharedMemory.h> 24 #include <nnapi/Types.h> 25 #include <functional> 26 #include <vector> 27 28 // Shorthands 29 namespace android::hardware::neuralnetworks { 30 namespace hal = ::android::hardware::neuralnetworks; 31 } // namespace android::hardware::neuralnetworks 32 33 // Shorthands 34 namespace aidl::android::hardware::neuralnetworks { 35 namespace aidl_hal = ::aidl::android::hardware::neuralnetworks; 36 namespace hal = ::android::hardware::neuralnetworks; 37 namespace nn = ::android::nn; 38 } // namespace aidl::android::hardware::neuralnetworks 39 40 // Shorthands 41 namespace android::nn { 42 namespace hal = ::android::hardware::neuralnetworks; 43 namespace aidl_hal = ::aidl::android::hardware::neuralnetworks; 44 } // namespace android::nn 45 46 namespace android::hardware::neuralnetworks::utils { 47 48 nn::Capabilities::OperandPerformanceTable makeQuantized8PerformanceConsistentWithP( 49 const nn::Capabilities::PerformanceInfo& float32Performance, 50 const nn::Capabilities::PerformanceInfo& quantized8Performance); 51 52 // Indicates if the object contains no pointer-based data that could be relocated to shared memory. 53 bool hasNoPointerData(const nn::Model& model); 54 bool hasNoPointerData(const nn::Request& request); 55 56 // Relocate pointer-based data to shared memory. If `model` has no Operand::LifeTime::POINTER data, 57 // the function returns with a reference to `model`. If `model` has Operand::LifeTime::POINTER data, 58 // the model is copied to `maybeModelInSharedOut` with the POINTER data relocated to a memory pool, 59 // and the function returns with a reference to `*maybeModelInSharedOut`. 60 nn::GeneralResult<std::reference_wrapper<const nn::Model>> flushDataFromPointerToShared( 61 const nn::Model* model, std::optional<nn::Model>* maybeModelInSharedOut); 62 63 // Record a relocation mapping between pointer-based data and shared memory. 64 // Only two specializations of this template may exist: 65 // - RelocationInfo<const void*> for request inputs 66 // - RelocationInfo<void*> for request outputs 67 template <typename PointerType> 68 struct RelocationInfo { 69 PointerType data; 70 size_t length; 71 size_t offset; 72 }; 73 using InputRelocationInfo = RelocationInfo<const void*>; 74 using OutputRelocationInfo = RelocationInfo<void*>; 75 76 // Keep track of the relocation mapping between pointer-based data and shared memory pool, 77 // and provide method to copy the data between pointers and the shared memory pool. 78 // Only two specializations of this template may exist: 79 // - RelocationTracker<InputRelocationInfo> for request inputs 80 // - RelocationTracker<OutputRelocationInfo> for request outputs 81 template <typename RelocationInfoType> 82 class RelocationTracker { 83 public: create(std::vector<RelocationInfoType> relocationInfos,nn::SharedMemory memory)84 static nn::GeneralResult<std::unique_ptr<RelocationTracker>> create( 85 std::vector<RelocationInfoType> relocationInfos, nn::SharedMemory memory) { 86 auto mapping = NN_TRY(map(memory)); 87 return std::make_unique<RelocationTracker<RelocationInfoType>>( 88 std::move(relocationInfos), std::move(memory), std::move(mapping)); 89 } 90 RelocationTracker(std::vector<RelocationInfoType> relocationInfos,nn::SharedMemory memory,nn::Mapping mapping)91 RelocationTracker(std::vector<RelocationInfoType> relocationInfos, nn::SharedMemory memory, 92 nn::Mapping mapping) 93 : kRelocationInfos(std::move(relocationInfos)), 94 kMemory(std::move(memory)), 95 kMapping(std::move(mapping)) {} 96 97 // Specializations defined in CommonUtils.cpp. 98 // For InputRelocationTracker, this method will copy pointer data to the shared memory pool. 99 // For OutputRelocationTracker, this method will copy shared memory data to the pointers. 100 void flush() const; 101 102 private: 103 const std::vector<RelocationInfoType> kRelocationInfos; 104 const nn::SharedMemory kMemory; 105 const nn::Mapping kMapping; 106 }; 107 using InputRelocationTracker = RelocationTracker<InputRelocationInfo>; 108 using OutputRelocationTracker = RelocationTracker<OutputRelocationInfo>; 109 110 struct RequestRelocation { 111 std::unique_ptr<InputRelocationTracker> input; 112 std::unique_ptr<OutputRelocationTracker> output; 113 }; 114 115 // Relocate pointer-based data to shared memory. If `request` has no 116 // Request::Argument::LifeTime::POINTER data, the function returns with a reference to `request`. If 117 // `request` has Request::Argument::LifeTime::POINTER data, the request is copied to 118 // `maybeRequestInSharedOut` with the POINTER data relocated to a memory pool, and the function 119 // returns with a reference to `*maybeRequestInSharedOut`. The `relocationOut` will be set to track 120 // the input and output relocations. 121 // 122 // Unlike `flushDataFromPointerToShared`, this method will not copy the input pointer data to the 123 // shared memory pool. Use `relocationOut` to flush the input or output data after the call. 124 nn::GeneralResult<std::reference_wrapper<const nn::Request>> convertRequestFromPointerToShared( 125 const nn::Request* request, uint32_t alignment, uint32_t padding, 126 std::optional<nn::Request>* maybeRequestInSharedOut, RequestRelocation* relocationOut); 127 128 nn::GeneralResult<std::vector<uint32_t>> countNumberOfConsumers( 129 size_t numberOfOperands, const std::vector<nn::Operation>& operations); 130 131 nn::GeneralResult<hidl_memory> createHidlMemoryFromSharedMemory(const nn::SharedMemory& memory); 132 nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory); 133 134 nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::Handle& handle); 135 nn::GeneralResult<nn::Handle> sharedHandleFromNativeHandle(const native_handle_t* handle); 136 137 nn::GeneralResult<hidl_vec<hidl_handle>> convertSyncFences( 138 const std::vector<nn::SyncFence>& fences); 139 140 } // namespace android::hardware::neuralnetworks::utils 141 142 #endif // ANDROID_HARDWARE_INTERFACES_NEURALNETWORKS_UTILS_COMMON_COMMON_UTILS_H 143