• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright (c) 2015-2016 The Khronos Group Inc.
4  * Copyright (c) 2015-2016 Valve Corporation
5  * Copyright (c) 2015-2016 LunarG, Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  * Author: Ian Elliot <ian@lunarg.com>
20  * Author: Jon Ashburn <jon@lunarg.com>
21  *
22  */
23 #pragma once
24 
25 #if defined(_WIN32)
26 // WinSock2.h must be included *BEFORE* windows.h
27 #include <WinSock2.h>
28 #endif // _WIN32
29 
30 #include "vulkan/vk_platform.h"
31 #include "vulkan/vk_sdk_platform.h"
32 
33 #if defined(__linux__)
34 /* Linux-specific common code: */
35 
36 // Headers:
37 //#define _GNU_SOURCE 1
38 // TBD: Are the contents of the following file used?
39 #include <unistd.h>
40 // Note: The following file is for dynamic loading:
41 #include <dlfcn.h>
42 #include <pthread.h>
43 #include <assert.h>
44 #include <string.h>
45 #include <stdbool.h>
46 #include <stdlib.h>
47 #include <libgen.h>
48 
49 // VK Library Filenames, Paths, etc.:
50 #define PATH_SEPERATOR ':'
51 #define DIRECTORY_SYMBOL '/'
52 
53 #define VULKAN_DIR            "/vulkan/"
54 #define VULKAN_ICDCONF_DIR    "icd.d"
55 #define VULKAN_ICD_DIR        "icd"
56 #define VULKAN_ELAYERCONF_DIR "explicit_layer.d"
57 #define VULKAN_ILAYERCONF_DIR "implicit_layer.d"
58 #define VULKAN_LAYER_DIR      "layer"
59 
60 #if defined(LOCALPREFIX)
61 #define LOCAL_DRIVERS_INFO                                                     \
62     LOCALPREFIX "/" SYSCONFDIR VULKAN_DIR VULKAN_ICDCONF_DIR ":"               \
63     LOCALPREFIX "/" DATADIR    VULKAN_DIR VULKAN_ICDCONF_DIR ":"
64 #define LOCAL_ELAYERS_INFO                                                     \
65     LOCALPREFIX "/" SYSCONFDIR VULKAN_DIR VULKAN_ELAYERCONF_DIR ":"            \
66     LOCALPREFIX "/" DATADIR    VULKAN_DIR VULKAN_ELAYERCONF_DIR ":"
67 #define LOCAL_ILAYERS_INFO                                                     \
68     LOCALPREFIX "/" SYSCONFDIR VULKAN_DIR VULKAN_ILAYERCONF_DIR ":"            \
69     LOCALPREFIX "/" DATADIR    VULKAN_DIR VULKAN_ILAYERCONF_DIR ":"
70 #else
71 #define LOCAL_DRIVERS_INFO
72 #define LOCAL_ELAYERS_INFO
73 #define LOCAL_ILAYERS_INFO
74 #endif
75 
76 #define DEFAULT_VK_DRIVERS_INFO                                                \
77     LOCAL_DRIVERS_INFO                                                         \
78     "/"  SYSCONFDIR VULKAN_DIR VULKAN_ICDCONF_DIR ":"                          \
79     "/usr/" DATADIR VULKAN_DIR VULKAN_ICDCONF_DIR
80 #define DEFAULT_VK_DRIVERS_PATH ""
81 #define DEFAULT_VK_ELAYERS_INFO                                                \
82     LOCAL_ELAYERS_INFO                                                         \
83     "/"  SYSCONFDIR VULKAN_DIR VULKAN_ELAYERCONF_DIR ":"                       \
84     "/usr/" DATADIR VULKAN_DIR VULKAN_ELAYERCONF_DIR
85 #define DEFAULT_VK_ILAYERS_INFO                                                \
86     LOCAL_ILAYERS_INFO                                                         \
87     "/"  SYSCONFDIR VULKAN_DIR VULKAN_ILAYERCONF_DIR ":"                       \
88     "/usr/" DATADIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
89 #define DEFAULT_VK_LAYERS_PATH ""
90 #if !defined(LAYERS_SOURCE_PATH)
91 #define LAYERS_SOURCE_PATH NULL
92 #endif
93 #define LAYERS_PATH_ENV "VK_LAYER_PATH"
94 #define HOME_VK_DRIVERS_INFO VULKAN_DIR VULKAN_ICDCONF_DIR
95 #define HOME_VK_ELAYERS_INFO VULKAN_DIR VULKAN_ELAYERCONF_DIR
96 #define HOME_VK_ILAYERS_INFO VULKAN_DIR VULKAN_ILAYERCONF_DIR
97 
98 // C99:
99 #define PRINTF_SIZE_T_SPECIFIER "%zu"
100 
101 // File IO
loader_platform_file_exists(const char * path)102 static inline bool loader_platform_file_exists(const char *path) {
103     if (access(path, F_OK))
104         return false;
105     else
106         return true;
107 }
108 
loader_platform_is_path_absolute(const char * path)109 static inline bool loader_platform_is_path_absolute(const char *path) {
110     if (path[0] == '/')
111         return true;
112     else
113         return false;
114 }
115 
loader_platform_dirname(char * path)116 static inline char *loader_platform_dirname(char *path) {
117     return dirname(path);
118 }
119 
120 // Dynamic Loading of libraries:
121 typedef void *loader_platform_dl_handle;
122 static inline loader_platform_dl_handle
loader_platform_open_library(const char * libPath)123 loader_platform_open_library(const char *libPath) {
124     return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
125 }
126 static inline const char *
loader_platform_open_library_error(const char * libPath)127 loader_platform_open_library_error(const char *libPath) {
128     return dlerror();
129 }
130 static inline void
loader_platform_close_library(loader_platform_dl_handle library)131 loader_platform_close_library(loader_platform_dl_handle library) {
132     dlclose(library);
133 }
134 static inline void *
loader_platform_get_proc_address(loader_platform_dl_handle library,const char * name)135 loader_platform_get_proc_address(loader_platform_dl_handle library,
136                                  const char *name) {
137     assert(library);
138     assert(name);
139     return dlsym(library, name);
140 }
141 static inline const char *
loader_platform_get_proc_address_error(const char * name)142 loader_platform_get_proc_address_error(const char *name) {
143     return dlerror();
144 }
145 
146 // Threads:
147 typedef pthread_t loader_platform_thread;
148 #define THREAD_LOCAL_DECL __thread
149 #define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)                           \
150     pthread_once_t var = PTHREAD_ONCE_INIT;
151 #define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) pthread_once_t var;
loader_platform_thread_once(pthread_once_t * ctl,void (* func)(void))152 static inline void loader_platform_thread_once(pthread_once_t *ctl,
153                                                void (*func)(void)) {
154     assert(func != NULL);
155     assert(ctl != NULL);
156     pthread_once(ctl, func);
157 }
158 
159 // Thread IDs:
160 typedef pthread_t loader_platform_thread_id;
loader_platform_get_thread_id()161 static inline loader_platform_thread_id loader_platform_get_thread_id() {
162     return pthread_self();
163 }
164 
165 // Thread mutex:
166 typedef pthread_mutex_t loader_platform_thread_mutex;
167 static inline void
loader_platform_thread_create_mutex(loader_platform_thread_mutex * pMutex)168 loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
169     pthread_mutex_init(pMutex, NULL);
170 }
171 static inline void
loader_platform_thread_lock_mutex(loader_platform_thread_mutex * pMutex)172 loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) {
173     pthread_mutex_lock(pMutex);
174 }
175 static inline void
loader_platform_thread_unlock_mutex(loader_platform_thread_mutex * pMutex)176 loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) {
177     pthread_mutex_unlock(pMutex);
178 }
179 static inline void
loader_platform_thread_delete_mutex(loader_platform_thread_mutex * pMutex)180 loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) {
181     pthread_mutex_destroy(pMutex);
182 }
183 typedef pthread_cond_t loader_platform_thread_cond;
184 static inline void
loader_platform_thread_init_cond(loader_platform_thread_cond * pCond)185 loader_platform_thread_init_cond(loader_platform_thread_cond *pCond) {
186     pthread_cond_init(pCond, NULL);
187 }
188 static inline void
loader_platform_thread_cond_wait(loader_platform_thread_cond * pCond,loader_platform_thread_mutex * pMutex)189 loader_platform_thread_cond_wait(loader_platform_thread_cond *pCond,
190                                  loader_platform_thread_mutex *pMutex) {
191     pthread_cond_wait(pCond, pMutex);
192 }
193 static inline void
loader_platform_thread_cond_broadcast(loader_platform_thread_cond * pCond)194 loader_platform_thread_cond_broadcast(loader_platform_thread_cond *pCond) {
195     pthread_cond_broadcast(pCond);
196 }
197 
198 #define loader_stack_alloc(size) alloca(size)
199 
200 #elif defined(_WIN32) // defined(__linux__)
201 /* Windows-specific common code: */
202 // WinBase.h defines CreateSemaphore and synchapi.h defines CreateEvent
203 //  undefine them to avoid conflicts with VkLayerDispatchTable struct members.
204 #ifdef CreateSemaphore
205 #undef CreateSemaphore
206 #endif
207 #ifdef CreateEvent
208 #undef CreateEvent
209 #endif
210 #include <assert.h>
211 #include <stdio.h>
212 #include <string.h>
213 #include <io.h>
214 #include <stdbool.h>
215 #include <shlwapi.h>
216 #ifdef __cplusplus
217 #include <iostream>
218 #include <string>
219 using namespace std;
220 #endif // __cplusplus
221 
222 // VK Library Filenames, Paths, etc.:
223 #define PATH_SEPERATOR ';'
224 #define DIRECTORY_SYMBOL '\\'
225 #define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
226 #define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\Vulkan\\Drivers"
227 // TODO: Are these the correct paths
228 #define DEFAULT_VK_DRIVERS_PATH ""
229 #define DEFAULT_VK_ELAYERS_INFO "SOFTWARE\\Khronos\\Vulkan\\ExplicitLayers"
230 #define DEFAULT_VK_ILAYERS_INFO "SOFTWARE\\Khronos\\Vulkan\\ImplicitLayers"
231 #if !defined(DEFAULT_VK_LAYERS_PATH)
232 #define DEFAULT_VK_LAYERS_PATH ""
233 #endif
234 #if !defined(LAYERS_SOURCE_PATH)
235 #define LAYERS_SOURCE_PATH NULL
236 #endif
237 #define LAYERS_PATH_ENV "VK_LAYER_PATH"
238 #define HOME_VK_DRIVERS_INFO ""
239 #define HOME_VK_ELAYERS_INFO ""
240 #define HOME_VK_ILAYERS_INFO ""
241 #define PRINTF_SIZE_T_SPECIFIER "%Iu"
242 
243 // File IO
loader_platform_file_exists(const char * path)244 static bool loader_platform_file_exists(const char *path) {
245     if ((_access(path, 0)) == -1)
246         return false;
247     else
248         return true;
249 }
250 
loader_platform_is_path_absolute(const char * path)251 static bool loader_platform_is_path_absolute(const char *path) {
252     return !PathIsRelative(path);
253 }
254 
255 // WIN32 runtime doesn't have dirname().
loader_platform_dirname(char * path)256 static inline char *loader_platform_dirname(char *path) {
257     char *current, *next;
258 
259     // TODO/TBD: Do we need to deal with the Windows's ":" character?
260 
261     for (current = path; *current != '\0'; current = next) {
262         next = strchr(current, DIRECTORY_SYMBOL);
263         if (next == NULL) {
264             if (current != path)
265                 *(current - 1) = '\0';
266             return path;
267         } else {
268             // Point one character past the DIRECTORY_SYMBOL:
269             next++;
270         }
271     }
272     return path;
273 }
274 
275 // WIN32 runtime doesn't have basename().
276 // Microsoft also doesn't have basename().  Paths are different on Windows, and
277 // so this is just a temporary solution in order to get us compiling, so that we
278 // can test some scenarios, and develop the correct solution for Windows.
279 // TODO: Develop a better, permanent solution for Windows, to replace this
280 // temporary code:
loader_platform_basename(char * pathname)281 static char *loader_platform_basename(char *pathname) {
282     char *current, *next;
283 
284     // TODO/TBD: Do we need to deal with the Windows's ":" character?
285 
286     for (current = pathname; *current != '\0'; current = next) {
287         next = strchr(current, DIRECTORY_SYMBOL);
288         if (next == NULL) {
289             // No more DIRECTORY_SYMBOL's so return p:
290             return current;
291         } else {
292             // Point one character past the DIRECTORY_SYMBOL:
293             next++;
294         }
295     }
296     // We shouldn't get to here, but this makes the compiler happy:
297     return current;
298 }
299 
300 // Dynamic Loading:
301 typedef HMODULE loader_platform_dl_handle;
302 static loader_platform_dl_handle
loader_platform_open_library(const char * libPath)303 loader_platform_open_library(const char *libPath) {
304     return LoadLibrary(libPath);
305 }
loader_platform_open_library_error(const char * libPath)306 static char *loader_platform_open_library_error(const char *libPath) {
307     static char errorMsg[164];
308     snprintf(errorMsg, 163, "Failed to open dynamic library \"%s\"", libPath);
309     return errorMsg;
310 }
loader_platform_close_library(loader_platform_dl_handle library)311 static void loader_platform_close_library(loader_platform_dl_handle library) {
312     FreeLibrary(library);
313 }
loader_platform_get_proc_address(loader_platform_dl_handle library,const char * name)314 static void *loader_platform_get_proc_address(loader_platform_dl_handle library,
315                                               const char *name) {
316     assert(library);
317     assert(name);
318     return GetProcAddress(library, name);
319 }
loader_platform_get_proc_address_error(const char * name)320 static char *loader_platform_get_proc_address_error(const char *name) {
321     static char errorMsg[120];
322     snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library",
323              name);
324     return errorMsg;
325 }
326 
327 // Threads:
328 typedef HANDLE loader_platform_thread;
329 #define THREAD_LOCAL_DECL __declspec(thread)
330 #define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var)                           \
331     INIT_ONCE var = INIT_ONCE_STATIC_INIT;
332 #define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) INIT_ONCE var;
333 static BOOL CALLBACK
InitFuncWrapper(PINIT_ONCE InitOnce,PVOID Parameter,PVOID * Context)334 InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context) {
335     void (*func)(void) = (void (*)(void))Parameter;
336     func();
337     return TRUE;
338 }
339 
loader_platform_thread_once(void * ctl,void (* func)(void))340 static void loader_platform_thread_once(void *ctl, void (*func)(void)) {
341     assert(func != NULL);
342     assert(ctl != NULL);
343     InitOnceExecuteOnce((PINIT_ONCE)ctl, InitFuncWrapper, func, NULL);
344 }
345 
346 // Thread IDs:
347 typedef DWORD loader_platform_thread_id;
loader_platform_get_thread_id()348 static loader_platform_thread_id loader_platform_get_thread_id() {
349     return GetCurrentThreadId();
350 }
351 
352 // Thread mutex:
353 typedef CRITICAL_SECTION loader_platform_thread_mutex;
354 static void
loader_platform_thread_create_mutex(loader_platform_thread_mutex * pMutex)355 loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) {
356     InitializeCriticalSection(pMutex);
357 }
358 static void
loader_platform_thread_lock_mutex(loader_platform_thread_mutex * pMutex)359 loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) {
360     EnterCriticalSection(pMutex);
361 }
362 static void
loader_platform_thread_unlock_mutex(loader_platform_thread_mutex * pMutex)363 loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) {
364     LeaveCriticalSection(pMutex);
365 }
366 static void
loader_platform_thread_delete_mutex(loader_platform_thread_mutex * pMutex)367 loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) {
368     DeleteCriticalSection(pMutex);
369 }
370 typedef CONDITION_VARIABLE loader_platform_thread_cond;
371 static void
loader_platform_thread_init_cond(loader_platform_thread_cond * pCond)372 loader_platform_thread_init_cond(loader_platform_thread_cond *pCond) {
373     InitializeConditionVariable(pCond);
374 }
375 static void
loader_platform_thread_cond_wait(loader_platform_thread_cond * pCond,loader_platform_thread_mutex * pMutex)376 loader_platform_thread_cond_wait(loader_platform_thread_cond *pCond,
377                                  loader_platform_thread_mutex *pMutex) {
378     SleepConditionVariableCS(pCond, pMutex, INFINITE);
379 }
380 static void
loader_platform_thread_cond_broadcast(loader_platform_thread_cond * pCond)381 loader_platform_thread_cond_broadcast(loader_platform_thread_cond *pCond) {
382     WakeAllConditionVariable(pCond);
383 }
384 
385 // Windows Registry:
386 char *loader_get_registry_string(const HKEY hive, const LPCTSTR sub_key,
387                                  const char *value);
388 
389 #define loader_stack_alloc(size) _alloca(size)
390 #else // defined(_WIN32)
391 
392 #error The "loader_platform.h" file must be modified for this OS.
393 
394 // NOTE: In order to support another OS, an #elif needs to be added (above the
395 // "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
396 // contents of this file must be created.
397 
398 // NOTE: Other OS-specific changes are also needed for this OS.  Search for
399 // files with "WIN32" in it, as a quick way to find files that must be changed.
400 
401 #endif // defined(_WIN32)
402 
403 // returns true if the given string appears to be a relative or absolute
404 // path, as opposed to a bare filename.
loader_platform_is_path(const char * path)405 static inline bool loader_platform_is_path(const char *path) {
406     return strchr(path, DIRECTORY_SYMBOL) != NULL;
407 }
408