blob: 4e586075cbd7b668ea566161e364700609a168d8 [file] [log] [blame]
Ian Elliott81ac44c2015-01-13 17:52:38 -07001/*
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -06002 * Vulkan
Ian Elliott81ac44c2015-01-13 17:52:38 -07003 *
4 * Copyright (C) 2015 LunarG, Inc.
5 * Copyright 2014 Valve Software
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
Jon Ashburnffd5d672015-06-29 11:25:34 -060027 * Jon Ashburn <jon@luanrg.com>
Ian Elliott81ac44c2015-01-13 17:52:38 -070028 * Ian Elliott <ian@lunarg.com>
29 */
30
31#ifndef LOADER_PLATFORM_H
32#define LOADER_PLATFORM_H
33
Cody Northrop62ac1c52015-07-08 16:48:37 -060034#include "vk_platform.h"
35
Ian Elliott81ac44c2015-01-13 17:52:38 -070036#if defined(__linux__)
37/* Linux-specific common code: */
38
39// Headers:
40//#define _GNU_SOURCE 1
41// TBD: Are the contents of the following file used?
42#include <unistd.h>
43// Note: The following file is for dynamic loading:
44#include <dlfcn.h>
45#include <pthread.h>
46#include <assert.h>
Jon Ashburnffd5d672015-06-29 11:25:34 -060047#include <stdbool.h>
Jon Ashburn38144502015-07-07 15:06:25 -060048#include <libgen.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -070049
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060050// VK Library Filenames, Paths, etc.:
Ian Elliott665c5632015-02-04 11:22:39 -070051#define PATH_SEPERATOR ':'
Jon Ashburnffd5d672015-06-29 11:25:34 -060052#define DIRECTORY_SYMBOL '/'
53
54// TODO: Need to handle different Linux distros
Adam Jackson333fe8e2015-07-20 13:15:43 -040055#define DEFAULT_VK_DRIVERS_INFO "/etc/vulkan/icd.d:/usr/share/vulkan/icd.d"
Jon Ashburnffd5d672015-06-29 11:25:34 -060056#define DEFAULT_VK_DRIVERS_PATH "/usr/lib/i386-linux-gnu/vulkan/icd:/usr/lib/x86_64-linux-gnu/vulkan/icd"
Adam Jackson333fe8e2015-07-20 13:15:43 -040057#define DEFAULT_VK_LAYERS_INFO "/etc/vulkan/explicit_layer.d:/etc/vulkan/implicit_layer.d:/usr/share/vulkan/explicit_layer.d:/usr/share/vulkan/implicit_layer.d"
Jon Ashburn38144502015-07-07 15:06:25 -060058#define DEFAULT_VK_LAYERS_PATH "/usr/lib/i386-linux-gnu/vulkan/layer:/usr/lib/x86_64-linux-gnu/vulkan/layer"
Jon Ashburn1b111de2015-07-06 15:40:35 -060059#define LAYERS_PATH_ENV "VK_LAYER_DIRS"
Ian Elliott665c5632015-02-04 11:22:39 -070060
Ian Elliottecb60ec2015-02-12 16:44:56 -070061// C99:
Tobin Ehlisbf0146e2015-02-11 14:24:02 -070062#define PRINTF_SIZE_T_SPECIFIER "%zu"
63
Jon Ashburnffd5d672015-06-29 11:25:34 -060064// File IO
65static inline bool loader_platform_file_exists(const char *path)
66{
67 if (access(path, F_OK))
68 return false;
69 else
70 return true;
71}
72
Jon Ashburn38144502015-07-07 15:06:25 -060073static inline bool loader_platform_is_path_absolute(const char *path)
74{
75 if (path[0] == '/')
76 return true;
77 else
78 return false;
79}
80
81static inline char *loader_platform_dirname(char *path)
82{
83 return dirname(path);
84}
85
Jon Ashburnffd5d672015-06-29 11:25:34 -060086// Dynamic Loading of libraries:
Ian Elliott81ac44c2015-01-13 17:52:38 -070087typedef void * loader_platform_dl_handle;
88static inline loader_platform_dl_handle loader_platform_open_library(const char* libPath)
89{
Chia-I Wu7397c432015-02-18 14:39:54 -070090 return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
Ian Elliott81ac44c2015-01-13 17:52:38 -070091}
92static inline char * loader_platform_open_library_error(const char* libPath)
93{
94 return dlerror();
95}
96static inline void loader_platform_close_library(loader_platform_dl_handle library)
97{
98 dlclose(library);
99}
100static inline void * loader_platform_get_proc_address(loader_platform_dl_handle library,
101 const char *name)
102{
103 assert(library);
104 assert(name);
105 return dlsym(library, name);
106}
107static inline char * loader_platform_get_proc_address_error(const char *name)
108{
109 return dlerror();
110}
111
112// Threads:
113typedef pthread_t loader_platform_thread;
114#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
115 pthread_once_t var = PTHREAD_ONCE_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600116#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
117 pthread_once_t var;
Ian Elliott81ac44c2015-01-13 17:52:38 -0700118static inline void loader_platform_thread_once(void *ctl, void (* func) (void))
119{
120 assert(func != NULL);
121 assert(ctl != NULL);
122 pthread_once((pthread_once_t *) ctl, func);
123}
124
125// Thread IDs:
126typedef pthread_t loader_platform_thread_id;
127static inline loader_platform_thread_id loader_platform_get_thread_id()
128{
129 return pthread_self();
130}
131
132// Thread mutex:
133typedef pthread_mutex_t loader_platform_thread_mutex;
134static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
135{
136 pthread_mutex_init(pMutex, NULL);
137}
138static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
139{
140 pthread_mutex_lock(pMutex);
141}
142static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
143{
144 pthread_mutex_unlock(pMutex);
145}
146static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
147{
148 pthread_mutex_destroy(pMutex);
149}
Mike Stroyan354ed672015-05-15 08:50:57 -0600150typedef pthread_cond_t loader_platform_thread_cond;
151static inline void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
152{
153 pthread_cond_init(pCond, NULL);
154}
155static inline void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
156{
157 pthread_cond_wait(pCond, pMutex);
158}
159static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
160{
161 pthread_cond_broadcast(pCond);
162}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700163
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600164#define loader_stack_alloc(size) alloca(size)
165static inline void *loader_aligned_alloc(size_t alignment, size_t size) { return aligned_alloc(alignment, size); }
Ian Elliott81ac44c2015-01-13 17:52:38 -0700166
167#elif defined(_WIN32) // defined(__linux__)
168/* Windows-specific common code: */
169
170// Headers:
Piers Danielle2bca482015-02-24 13:58:47 -0700171#include <WinSock2.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700172#include <windows.h>
173#include <assert.h>
Tony Barbour69698512015-06-18 16:29:32 -0600174#include <stdio.h>
Jon Ashburnee33ae72015-06-30 14:46:22 -0700175#include <io.h>
176#include <stdbool.h>
Cody Northrop62ac1c52015-07-08 16:48:37 -0600177#include <shlwapi.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700178#ifdef __cplusplus
179#include <iostream>
180#include <string>
181using namespace std;
182#endif // __cplusplus
183
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600184// VK Library Filenames, Paths, etc.:
Ian Elliott665c5632015-02-04 11:22:39 -0700185#define PATH_SEPERATOR ';'
Jon Ashburnffd5d672015-06-29 11:25:34 -0600186#define DIRECTORY_SYMBOL '\\'
Jon Ashburnee33ae72015-06-30 14:46:22 -0700187#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
188#define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\Vulkan\\Drivers"
Jon Ashburnffd5d672015-06-29 11:25:34 -0600189// TODO: Are these the correct paths
scygan8420b4c2015-06-01 19:47:08 +0200190#define DEFAULT_VK_DRIVERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn1b111de2015-07-06 15:40:35 -0600191#define DEFAULT_VK_LAYERS_INFO "SOFTWARE\\Khronos\\Vulkan\\ExplicitLayers;SOFTWARE\\Khronos\\Vulkan\\ImplicitLayers"
Jon Ashburn38144502015-07-07 15:06:25 -0600192#define DEFAULT_VK_LAYERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburncfcd6132015-07-23 18:58:21 -0600193#define LAYERS_PATH_ENV "VK_LAYER_FOLDERS"
Ian Elliott665c5632015-02-04 11:22:39 -0700194
Ian Elliott81ac44c2015-01-13 17:52:38 -0700195// C99:
196// Microsoft didn't implement C99 in Visual Studio; but started adding it with
197// VS2013. However, VS2013 still didn't have snprintf(). The following is a
Ian Elliott64f74a82015-02-04 12:06:46 -0700198// work-around (Note: The _CRT_SECURE_NO_WARNINGS macro must be set in the
199// "CMakeLists.txt" file).
Ian Elliott81ac44c2015-01-13 17:52:38 -0700200#define snprintf _snprintf
Jon Ashburn38144502015-07-07 15:06:25 -0600201#define strdup _strdup
Tobin Ehlisbf0146e2015-02-11 14:24:02 -0700202#define PRINTF_SIZE_T_SPECIFIER "%Iu"
David Pinedo3053c672015-07-02 09:04:37 -0600203
David Pinedo3053c672015-07-02 09:04:37 -0600204
Jon Ashburnffd5d672015-06-29 11:25:34 -0600205// File IO
Jon Ashburnee33ae72015-06-30 14:46:22 -0700206static bool loader_platform_file_exists(const char *path)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600207{
Jon Ashburnee33ae72015-06-30 14:46:22 -0700208 if ((_access(path, 0)) == -1)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600209 return false;
210 else
211 return true;
212}
213
Cody Northrop62ac1c52015-07-08 16:48:37 -0600214static bool loader_platform_is_path_absolute(const char *path)
Jon Ashburn38144502015-07-07 15:06:25 -0600215{
216 return !PathIsRelative(path);
217}
218
219// WIN32 runtime doesn't have dirname().
220static inline char *loader_platform_dirname(char *path)
221{
222 char *current, *next;
223
224 // TODO/TBD: Do we need to deal with the Windows's ":" character?
225
226 for (current = path; *current != '\0'; current = next) {
227 next = strchr(current, DIRECTORY_SYMBOL);
228 if (next == NULL) {
229 if (current != path)
230 *(current - 1) = '\0';
231 return path;
232 } else {
233 // Point one character past the DIRECTORY_SYMBOL:
234 next++;
235 }
236 }
237 return path;
238}
239
240// WIN32 runtime doesn't have basename().
241// Microsoft also doesn't have basename(). Paths are different on Windows, and
242// so this is just a temporary solution in order to get us compiling, so that we
243// can test some scenarios, and develop the correct solution for Windows.
244 // TODO: Develop a better, permanent solution for Windows, to replace this
245 // temporary code:
246static char *loader_platform_basename(char *pathname)
247{
248 char *current, *next;
249
250// TODO/TBD: Do we need to deal with the Windows's ":" character?
251
252 for (current = pathname; *current != '\0'; current = next) {
253 next = strchr(current, DIRECTORY_SYMBOL);
254 if (next == NULL) {
255 // No more DIRECTORY_SYMBOL's so return p:
256 return current;
257 } else {
258 // Point one character past the DIRECTORY_SYMBOL:
259 next++;
260 }
261 }
262 // We shouldn't get to here, but this makes the compiler happy:
263 return current;
264}
265
Ian Elliott81ac44c2015-01-13 17:52:38 -0700266// Dynamic Loading:
267typedef HMODULE loader_platform_dl_handle;
268static loader_platform_dl_handle loader_platform_open_library(const char* libPath)
269{
270 return LoadLibrary(libPath);
271}
272static char * loader_platform_open_library_error(const char* libPath)
273{
274 static char errorMsg[120];
275 snprintf(errorMsg, 119, "Failed to open dynamic library \"%s\"", libPath);
276 return errorMsg;
277}
278static void loader_platform_close_library(loader_platform_dl_handle library)
279{
280 FreeLibrary(library);
281}
282static void * loader_platform_get_proc_address(loader_platform_dl_handle library,
283 const char *name)
284{
285 assert(library);
286 assert(name);
287 return GetProcAddress(library, name);
288}
289static char * loader_platform_get_proc_address_error(const char *name)
290{
291 static char errorMsg[120];
292 snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
293 return errorMsg;
294}
295
296// Threads:
297typedef HANDLE loader_platform_thread;
298#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
299 INIT_ONCE var = INIT_ONCE_STATIC_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600300#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
301 INIT_ONCE var;
Piers Daniell886be472015-02-23 16:23:13 -0700302static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
303{
304 void (*func)(void) = (void (*)(void))Parameter;
305 func();
306 return TRUE;
307}
308
Ian Elliott81ac44c2015-01-13 17:52:38 -0700309static void loader_platform_thread_once(void *ctl, void (* func) (void))
310{
311 assert(func != NULL);
312 assert(ctl != NULL);
Piers Daniell886be472015-02-23 16:23:13 -0700313 InitOnceExecuteOnce((PINIT_ONCE) ctl, InitFuncWrapper, func, NULL);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700314}
315
316// Thread IDs:
317typedef DWORD loader_platform_thread_id;
318static loader_platform_thread_id loader_platform_get_thread_id()
319{
320 return GetCurrentThreadId();
321}
322
323// Thread mutex:
324typedef CRITICAL_SECTION loader_platform_thread_mutex;
325static void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
326{
327 InitializeCriticalSection(pMutex);
328}
329static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
330{
331 EnterCriticalSection(pMutex);
332}
333static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
334{
335 LeaveCriticalSection(pMutex);
336}
337static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
338{
339 DeleteCriticalSection(pMutex);
340}
Mike Stroyan33053d02015-05-15 17:34:51 -0600341typedef CONDITION_VARIABLE loader_platform_thread_cond;
342static void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
343{
344 InitializeConditionVariable(pCond);
345}
346static void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
347{
348 SleepConditionVariableCS(pCond, pMutex, INFINITE);
349}
350static void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
351{
352 WakeAllConditionVariable(pCond);
353}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700354
Ian Elliott76005132015-03-31 15:32:41 -0600355// Windows Registry:
356char *loader_get_registry_string(const HKEY hive,
357 const LPCTSTR sub_key,
358 const char *value);
359
Ian Elliott81ac44c2015-01-13 17:52:38 -0700360#else // defined(_WIN32)
361
362#error The "loader_platform.h" file must be modified for this OS.
363
364// NOTE: In order to support another OS, an #elif needs to be added (above the
365// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
366// contents of this file must be created.
367
368// NOTE: Other OS-specific changes are also needed for this OS. Search for
369// files with "WIN32" in it, as a quick way to find files that must be changed.
370
371#endif // defined(_WIN32)
372
Ian Elliott20f06872015-02-12 17:08:34 -0700373#else /* LOADER_PLATFORM_H */
374#ifndef LOADER_PLATFORM_H_TEMP
375#define LOADER_PLATFORM_H_TEMP
376
377// NOTE: The following are hopefully-temporary macros to ensure that people
378// don't forget to use the loader_platform_*() functions above:
379
380#if defined(__linux__)
381/* Linux-specific common code: */
382
383// Dynamic Loading:
384#define dlopen PLEASE USE THE loader_platform_open_library() FUNCTION
385#define dlerror PLEASE DO NOT USE THE dlerror() FUNCTION DIRECTLY
386#define dlclose PLEASE USE THE loader_platform_close_library() FUNCTION
387#define dlsym PLEASE USE THE loader_platform_get_proc_address() FUNCTION
388
389// Threads:
390#define pthread_once PLEASE USE THE loader_platform_thread_once() FUNCTION
391#define pthread_self PLEASE USE THE loader_platform_get_thread_id() FUNCTION
392
393// Thread mutex:
394#define pthread_mutex_init PLEASE USE THE loader_platform_thread_create_mutex() FUNCTION
395#define pthread_mutex_lock PLEASE USE THE loader_platform_thread_lock_mutex() FUNCTION
396#define pthread_mutex_unlock PLEASE USE THE loader_platform_thread_unlock_mutex() FUNCTION
397#define pthread_mutex_destroy PLEASE USE THE loader_platform_thread_delete_mutex() FUNCTION
398
399
400#elif defined(_WIN32) // defined(__linux__)
401/* Windows-specific common code: */
402
403// Dynamic Loading:
404//#define LoadLibrary PLEASE USE THE loader_platform_open_library() FUNCTION
405#define FreeLibrary PLEASE USE THE loader_platform_close_library() FUNCTION
406#define GetProcAddress PLEASE USE THE loader_platform_get_proc_address() FUNCTION
407
408// Threads:
409#define InitOnceExecuteOnce PLEASE USE THE loader_platform_thread_once() FUNCTION
410#define GetCurrentThreadId PLEASE USE THE loader_platform_get_thread_id() FUNCTION
411
412// Thread mutex:
413#define InitializeCriticalSection PLEASE USE THE loader_platform_thread_create_mutex() FUNCTION
414#define EnterCriticalSection PLEASE USE THE loader_platform_thread_lock_mutex() FUNCTION
415#define LeaveCriticalSection PLEASE USE THE loader_platform_thread_unlock_mutex() FUNCTION
416#define DeleteCriticalSection PLEASE USE THE loader_platform_thread_delete_mutex() FUNCTION
417
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600418#define loader_stack_alloc(size) _alloca(size)
Cody Northrop62ac1c52015-07-08 16:48:37 -0600419static inline void *loader_aligned_alloc(size_t alignment, size_t size) { return _aligned_malloc(alignment, size); }
Ian Elliott20f06872015-02-12 17:08:34 -0700420
421#endif // defined(_WIN32)
422#endif /* LOADER_PLATFORM_H_TEMP */
Ian Elliott81ac44c2015-01-13 17:52:38 -0700423#endif /* LOADER_PLATFORM_H */