1 // Copyright 2019 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "Driver.hpp"
16
17 #if defined(_WIN32)
18 # include "Windows.h"
19 # define OS_WINDOWS 1
20 #elif defined(__APPLE__)
21 # include "dlfcn.h"
22 # define OS_MAC 1
23 #elif defined(__ANDROID__)
24 # include "dlfcn.h"
25 # define OS_ANDROID 1
26 #elif defined(__linux__)
27 # include "dlfcn.h"
28 # define OS_LINUX 1
29 #elif defined(__Fuchsia__)
30 # include <zircon/dlfcn.h>
31 # define OS_FUCHSIA 1
32 #else
33 # error Unimplemented platform
34 #endif
35
Driver()36 Driver::Driver()
37 : vk_icdGetInstanceProcAddr(nullptr)
38 , dll(nullptr){
39 #define VK_GLOBAL(N, R, ...) N = nullptr
40 #include "VkGlobalFuncs.hpp"
41 #undef VK_GLOBAL
42
43 #define VK_INSTANCE(N, R, ...) N = nullptr
44 #include "VkInstanceFuncs.hpp"
45 #undef VK_INSTANCE
46 }
47
~Driver()48 Driver::~Driver()
49 {
50 unload();
51 }
52
loadSwiftShader()53 bool Driver::loadSwiftShader()
54 {
55 #if OS_WINDOWS
56 # if !defined(STANDALONE)
57 // The DLL is delay loaded (see BUILD.gn), so we can load
58 // the correct ones from Chrome's swiftshader subdirectory.
59 HMODULE libvulkan = LoadLibraryA("swiftshader\\libvulkan.dll");
60 EXPECT_NE((HMODULE)NULL, libvulkan);
61 return true;
62 # elif defined(NDEBUG)
63 # if defined(_WIN64)
64 return load("./build/Release_x64/vk_swiftshader.dll") ||
65 load("./build/Release/vk_swiftshader.dll") ||
66 load("./vk_swiftshader.dll");
67 # else
68 return load("./build/Release_Win32/vk_swiftshader.dll") ||
69 load("./build/Release/vk_swiftshader.dll") ||
70 load("./vk_swiftshader.dll");
71 # endif
72 # else
73 # if defined(_WIN64)
74 return load("./build/Debug_x64/vk_swiftshader.dll") ||
75 load("./build/Debug/vk_swiftshader.dll") ||
76 load("./vk_swiftshader.dll");
77 # else
78 return load("./build/Debug_Win32/vk_swiftshader.dll") ||
79 load("./build/Debug/vk_swiftshader.dll") ||
80 load("./vk_swiftshader.dll");
81 # endif
82 # endif
83 #elif OS_MAC
84 return load("./build/Darwin/libvk_swiftshader.dylib") ||
85 load("swiftshader/libvk_swiftshader.dylib") ||
86 load("libvk_swiftshader.dylib");
87 #elif OS_LINUX
88 return load("./build/Linux/libvk_swiftshader.so") ||
89 load("swiftshader/libvk_swiftshader.so") ||
90 load("./libvk_swiftshader.so") ||
91 load("libvk_swiftshader.so");
92 #elif OS_ANDROID || OS_FUCHSIA
93 return load("libvk_swiftshader.so");
94 #else
95 # error Unimplemented platform
96 #endif
97 }
98
loadSystem()99 bool Driver::loadSystem()
100 {
101 #if OS_LINUX
102 return load("libvulkan.so.1");
103 #else
104 return false;
105 #endif
106 }
107
load(const char * path)108 bool Driver::load(const char *path)
109 {
110 #if OS_WINDOWS
111 dll = LoadLibraryA(path);
112 #elif(OS_MAC || OS_LINUX || OS_ANDROID || OS_FUCHSIA)
113 dll = dlopen(path, RTLD_LAZY | RTLD_LOCAL);
114 #else
115 return false;
116 #endif
117 if(dll == nullptr)
118 {
119 return false;
120 }
121
122 // Is the driver an ICD?
123 if(!lookup(&vk_icdGetInstanceProcAddr, "vk_icdGetInstanceProcAddr"))
124 {
125 // Nope, attempt to use the loader version.
126 if(!lookup(&vk_icdGetInstanceProcAddr, "vkGetInstanceProcAddr"))
127 {
128 return false;
129 }
130 }
131
132 #define VK_GLOBAL(N, R, ...) \
133 if(auto pfn = vk_icdGetInstanceProcAddr(nullptr, #N)) \
134 { \
135 N = reinterpret_cast<decltype(N)>(pfn); \
136 }
137 #include "VkGlobalFuncs.hpp"
138 #undef VK_GLOBAL
139
140 return true;
141 }
142
unload()143 void Driver::unload()
144 {
145 if(!isLoaded())
146 {
147 return;
148 }
149
150 #if OS_WINDOWS
151 FreeLibrary((HMODULE)dll);
152 #elif(OS_LINUX || OS_FUCHSIA)
153 dlclose(dll);
154 #endif
155
156 dll = nullptr;
157
158 #define VK_GLOBAL(N, R, ...) N = nullptr
159 #include "VkGlobalFuncs.hpp"
160 #undef VK_GLOBAL
161
162 #define VK_INSTANCE(N, R, ...) N = nullptr
163 #include "VkInstanceFuncs.hpp"
164 #undef VK_INSTANCE
165 }
166
isLoaded() const167 bool Driver::isLoaded() const
168 {
169 return dll != nullptr;
170 }
171
resolve(VkInstance instance)172 bool Driver::resolve(VkInstance instance)
173 {
174 if(!isLoaded())
175 {
176 return false;
177 }
178
179 #define VK_INSTANCE(N, R, ...) \
180 if(auto pfn = vk_icdGetInstanceProcAddr(instance, #N)) \
181 { \
182 N = reinterpret_cast<decltype(N)>(pfn); \
183 } \
184 else \
185 { \
186 return false; \
187 }
188 #include "VkInstanceFuncs.hpp"
189 #undef VK_INSTANCE
190
191 return true;
192 }
193
lookup(const char * name)194 void *Driver::lookup(const char *name)
195 {
196 #if OS_WINDOWS
197 return GetProcAddress((HMODULE)dll, name);
198 #elif(OS_MAC || OS_LINUX || OS_ANDROID || OS_FUCHSIA)
199 return dlsym(dll, name);
200 #else
201 return nullptr;
202 #endif
203 }
204