xref: /aosp_15_r20/external/armnn/src/backends/backendsCommon/DynamicBackend.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2017 Arm Ltd. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker 
6*89c4ff92SAndroid Build Coastguard Worker #include <armnn/backends/DynamicBackend.hpp>
7*89c4ff92SAndroid Build Coastguard Worker #include <backendsCommon/DynamicBackendUtils.hpp>
8*89c4ff92SAndroid Build Coastguard Worker 
9*89c4ff92SAndroid Build Coastguard Worker namespace armnn
10*89c4ff92SAndroid Build Coastguard Worker {
11*89c4ff92SAndroid Build Coastguard Worker 
DynamicBackend(const void * sharedObjectHandle)12*89c4ff92SAndroid Build Coastguard Worker DynamicBackend::DynamicBackend(const void* sharedObjectHandle)
13*89c4ff92SAndroid Build Coastguard Worker     : m_BackendIdFunction(nullptr)
14*89c4ff92SAndroid Build Coastguard Worker     , m_BackendVersionFunction(nullptr)
15*89c4ff92SAndroid Build Coastguard Worker     , m_BackendFactoryFunction(nullptr)
16*89c4ff92SAndroid Build Coastguard Worker     , m_Handle(const_cast<void*>(sharedObjectHandle), &DynamicBackendUtils::CloseHandle)
17*89c4ff92SAndroid Build Coastguard Worker {
18*89c4ff92SAndroid Build Coastguard Worker     if (m_Handle == nullptr)
19*89c4ff92SAndroid Build Coastguard Worker     {
20*89c4ff92SAndroid Build Coastguard Worker         throw InvalidArgumentException("Cannot create a DynamicBackend object from an invalid shared object handle");
21*89c4ff92SAndroid Build Coastguard Worker     }
22*89c4ff92SAndroid Build Coastguard Worker 
23*89c4ff92SAndroid Build Coastguard Worker     // These calls will throw in case of error
24*89c4ff92SAndroid Build Coastguard Worker     m_BackendIdFunction      = SetFunctionPointer<IdFunctionType>("GetBackendId");
25*89c4ff92SAndroid Build Coastguard Worker     m_BackendVersionFunction = SetFunctionPointer<VersionFunctionType>("GetVersion");
26*89c4ff92SAndroid Build Coastguard Worker     m_BackendFactoryFunction = SetFunctionPointer<FactoryFunctionType>("BackendFactory");
27*89c4ff92SAndroid Build Coastguard Worker 
28*89c4ff92SAndroid Build Coastguard Worker     // Check that the backend is compatible with the current Backend API
29*89c4ff92SAndroid Build Coastguard Worker     BackendId backendId = GetBackendId();
30*89c4ff92SAndroid Build Coastguard Worker     BackendVersion backendVersion = GetBackendVersion();
31*89c4ff92SAndroid Build Coastguard Worker     if (!DynamicBackendUtils::IsBackendCompatible(backendVersion))
32*89c4ff92SAndroid Build Coastguard Worker     {
33*89c4ff92SAndroid Build Coastguard Worker         // This exception message could not be formatted simply using fmt::format
34*89c4ff92SAndroid Build Coastguard Worker         std::stringstream message;
35*89c4ff92SAndroid Build Coastguard Worker         message << "The dynamic backend " << backendId << " (version " << backendVersion <<
36*89c4ff92SAndroid Build Coastguard Worker         ") is not compatible with the current Backend API (version " << IBackendInternal::GetApiVersion() << ")";
37*89c4ff92SAndroid Build Coastguard Worker 
38*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException(message.str());
39*89c4ff92SAndroid Build Coastguard Worker     }
40*89c4ff92SAndroid Build Coastguard Worker }
41*89c4ff92SAndroid Build Coastguard Worker 
GetBackendId()42*89c4ff92SAndroid Build Coastguard Worker BackendId DynamicBackend::GetBackendId()
43*89c4ff92SAndroid Build Coastguard Worker {
44*89c4ff92SAndroid Build Coastguard Worker     if (m_BackendIdFunction == nullptr)
45*89c4ff92SAndroid Build Coastguard Worker     {
46*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException("GetBackendId error: invalid function pointer");
47*89c4ff92SAndroid Build Coastguard Worker     }
48*89c4ff92SAndroid Build Coastguard Worker 
49*89c4ff92SAndroid Build Coastguard Worker     const char* backendId = m_BackendIdFunction();
50*89c4ff92SAndroid Build Coastguard Worker     if (backendId == nullptr)
51*89c4ff92SAndroid Build Coastguard Worker     {
52*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException("GetBackendId error: invalid backend id");
53*89c4ff92SAndroid Build Coastguard Worker     }
54*89c4ff92SAndroid Build Coastguard Worker 
55*89c4ff92SAndroid Build Coastguard Worker     return BackendId(backendId);
56*89c4ff92SAndroid Build Coastguard Worker }
57*89c4ff92SAndroid Build Coastguard Worker 
GetBackendVersion()58*89c4ff92SAndroid Build Coastguard Worker BackendVersion DynamicBackend::GetBackendVersion()
59*89c4ff92SAndroid Build Coastguard Worker {
60*89c4ff92SAndroid Build Coastguard Worker     if (m_BackendVersionFunction == nullptr)
61*89c4ff92SAndroid Build Coastguard Worker     {
62*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException("GetBackendVersion error: invalid function pointer");
63*89c4ff92SAndroid Build Coastguard Worker     }
64*89c4ff92SAndroid Build Coastguard Worker 
65*89c4ff92SAndroid Build Coastguard Worker     uint32_t major = 0;
66*89c4ff92SAndroid Build Coastguard Worker     uint32_t minor = 0;
67*89c4ff92SAndroid Build Coastguard Worker     m_BackendVersionFunction(&major, &minor);
68*89c4ff92SAndroid Build Coastguard Worker 
69*89c4ff92SAndroid Build Coastguard Worker     return BackendVersion{ major, minor };
70*89c4ff92SAndroid Build Coastguard Worker }
71*89c4ff92SAndroid Build Coastguard Worker 
GetBackend()72*89c4ff92SAndroid Build Coastguard Worker IBackendInternalUniquePtr DynamicBackend::GetBackend()
73*89c4ff92SAndroid Build Coastguard Worker {
74*89c4ff92SAndroid Build Coastguard Worker     // This call throws in case of error
75*89c4ff92SAndroid Build Coastguard Worker     return CreateBackend();
76*89c4ff92SAndroid Build Coastguard Worker }
77*89c4ff92SAndroid Build Coastguard Worker 
GetFactoryFunction()78*89c4ff92SAndroid Build Coastguard Worker BackendRegistry::FactoryFunction DynamicBackend::GetFactoryFunction()
79*89c4ff92SAndroid Build Coastguard Worker {
80*89c4ff92SAndroid Build Coastguard Worker     if (m_BackendFactoryFunction == nullptr)
81*89c4ff92SAndroid Build Coastguard Worker     {
82*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException("GetFactoryFunction error: invalid function pointer");
83*89c4ff92SAndroid Build Coastguard Worker     }
84*89c4ff92SAndroid Build Coastguard Worker 
85*89c4ff92SAndroid Build Coastguard Worker     return [this]() -> IBackendInternalUniquePtr
86*89c4ff92SAndroid Build Coastguard Worker     {
87*89c4ff92SAndroid Build Coastguard Worker         // This call throws in case of error
88*89c4ff92SAndroid Build Coastguard Worker         return CreateBackend();
89*89c4ff92SAndroid Build Coastguard Worker     };
90*89c4ff92SAndroid Build Coastguard Worker }
91*89c4ff92SAndroid Build Coastguard Worker 
92*89c4ff92SAndroid Build Coastguard Worker template<typename BackendFunctionType>
SetFunctionPointer(const std::string & backendFunctionName)93*89c4ff92SAndroid Build Coastguard Worker BackendFunctionType DynamicBackend::SetFunctionPointer(const std::string& backendFunctionName)
94*89c4ff92SAndroid Build Coastguard Worker {
95*89c4ff92SAndroid Build Coastguard Worker     if (m_Handle == nullptr)
96*89c4ff92SAndroid Build Coastguard Worker     {
97*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException("SetFunctionPointer error: invalid shared object handle");
98*89c4ff92SAndroid Build Coastguard Worker     }
99*89c4ff92SAndroid Build Coastguard Worker 
100*89c4ff92SAndroid Build Coastguard Worker     if (backendFunctionName.empty())
101*89c4ff92SAndroid Build Coastguard Worker     {
102*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException("SetFunctionPointer error: backend function name must not be empty");
103*89c4ff92SAndroid Build Coastguard Worker     }
104*89c4ff92SAndroid Build Coastguard Worker 
105*89c4ff92SAndroid Build Coastguard Worker     // This call will throw in case of error
106*89c4ff92SAndroid Build Coastguard Worker     auto functionPointer = DynamicBackendUtils::GetEntryPoint<BackendFunctionType>(m_Handle.get(),
107*89c4ff92SAndroid Build Coastguard Worker                                                                                    backendFunctionName.c_str());
108*89c4ff92SAndroid Build Coastguard Worker     if (!functionPointer)
109*89c4ff92SAndroid Build Coastguard Worker     {
110*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException("SetFunctionPointer error: invalid backend function pointer returned");
111*89c4ff92SAndroid Build Coastguard Worker     }
112*89c4ff92SAndroid Build Coastguard Worker 
113*89c4ff92SAndroid Build Coastguard Worker     return functionPointer;
114*89c4ff92SAndroid Build Coastguard Worker }
115*89c4ff92SAndroid Build Coastguard Worker 
CreateBackend()116*89c4ff92SAndroid Build Coastguard Worker IBackendInternalUniquePtr DynamicBackend::CreateBackend()
117*89c4ff92SAndroid Build Coastguard Worker {
118*89c4ff92SAndroid Build Coastguard Worker     if (m_BackendFactoryFunction == nullptr)
119*89c4ff92SAndroid Build Coastguard Worker     {
120*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException("CreateBackend error: invalid function pointer");
121*89c4ff92SAndroid Build Coastguard Worker     }
122*89c4ff92SAndroid Build Coastguard Worker 
123*89c4ff92SAndroid Build Coastguard Worker     auto backendPointer = reinterpret_cast<IBackendInternal*>(m_BackendFactoryFunction());
124*89c4ff92SAndroid Build Coastguard Worker     if (backendPointer == nullptr)
125*89c4ff92SAndroid Build Coastguard Worker     {
126*89c4ff92SAndroid Build Coastguard Worker         throw RuntimeException("CreateBackend error: backend instance must not be null");
127*89c4ff92SAndroid Build Coastguard Worker     }
128*89c4ff92SAndroid Build Coastguard Worker 
129*89c4ff92SAndroid Build Coastguard Worker     return std::unique_ptr<IBackendInternal>(backendPointer);
130*89c4ff92SAndroid Build Coastguard Worker }
131*89c4ff92SAndroid Build Coastguard Worker 
132*89c4ff92SAndroid Build Coastguard Worker } // namespace armnn
133