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