• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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