blob: b82c7ddc8369a0d2adc79d4f346462b24bf13643 [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
Michael Lentine92689442015-09-09 12:39:13 -07006 * Copyright (C) 2015 Google Inc.
Ian Elliott81ac44c2015-01-13 17:52:38 -07007 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * Authors:
Jon Ashburnffd5d672015-06-29 11:25:34 -060028 * Jon Ashburn <jon@luanrg.com>
Ian Elliott81ac44c2015-01-13 17:52:38 -070029 * Ian Elliott <ian@lunarg.com>
30 */
Jon Ashburnf6620c92015-10-15 13:47:58 -060031#pragma once
Ian Elliott81ac44c2015-01-13 17:52:38 -070032
Cody Northrop62ac1c52015-07-08 16:48:37 -060033#include "vk_platform.h"
Mark Lobodzinskieccbb372015-09-01 09:00:16 -060034#include "vk_sdk_platform.h"
Cody Northrop62ac1c52015-07-08 16:48:37 -060035
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>
Michael Lentine92689442015-09-09 12:39:13 -070048#include <stdlib.h>
Jon Ashburn38144502015-07-07 15:06:25 -060049#include <libgen.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -070050
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -060051// VK Library Filenames, Paths, etc.:
Ian Elliott665c5632015-02-04 11:22:39 -070052#define PATH_SEPERATOR ':'
Jon Ashburnffd5d672015-06-29 11:25:34 -060053#define DIRECTORY_SYMBOL '/'
54
James Jonesac945bc2015-07-23 17:39:37 -070055#define VULKAN_ICDCONF_DIR "/" "vulkan" "/" "icd.d"
56#define VULKAN_ICD_DIR "/" "vulkan" "/" "icd"
James Jones3f731442015-07-24 11:35:16 -070057#define VULKAN_ELAYERCONF_DIR "/" "vulkan" "/" "explicit_layer.d"
James Jonesac945bc2015-07-23 17:39:37 -070058#define VULKAN_ILAYERCONF_DIR "/" "vulkan" "/" "implicit_layer.d"
59#define VULKAN_LAYER_DIR "/" "vulkan" "/" "layer"
60
61#if defined(LOCALPREFIX)
62#define LOCAL_DRIVERS_INFO \
63 LOCALPREFIX "/" SYSCONFDIR VULKAN_ICDCONF_DIR ":" \
64 LOCALPREFIX "/" DATADIR VULKAN_ICDCONF_DIR ":"
65#define LOCAL_DRIVERS_PATH \
66 LOCALPREFIX "/" LIBDIR VULKAN_ICD_DIR ":"
67#define LOCAL_LAYERS_INFO \
68 LOCALPREFIX "/" SYSCONFDIR VULKAN_ELAYERCONF_DIR ":" \
69 LOCALPREFIX "/" SYSCONFDIR VULKAN_ILAYERCONF_DIR ":" \
70 LOCALPREFIX "/" DATADIR VULKAN_ELAYERCONF_DIR ":" \
71 LOCALPREFIX "/" DATADIR VULKAN_ILAYERCONF_DIR ":"
72#define LOCAL_LAYERS_PATH \
73 LOCALPREFIX "/" LIBDIR VULKAN_LAYER_DIR ":"
74#else
75#define LOCAL_DRIVERS_INFO
76#define LOCAL_DRIVERS_PATH
77#define LOCAL_LAYERS_INFO
78#define LOCAL_LAYERS_PATH
79#endif
80
Adam Jackson05487a22015-07-23 16:29:26 -040081#define DEFAULT_VK_DRIVERS_INFO \
James Jonesac945bc2015-07-23 17:39:37 -070082 LOCAL_DRIVERS_INFO \
James Jonesfb6b3b32015-07-24 09:47:37 -070083 "/" SYSCONFDIR VULKAN_ICDCONF_DIR ":" \
James Jonesac945bc2015-07-23 17:39:37 -070084 "/usr/" DATADIR VULKAN_ICDCONF_DIR
Adam Jackson05487a22015-07-23 16:29:26 -040085#define DEFAULT_VK_DRIVERS_PATH \
James Jonesac945bc2015-07-23 17:39:37 -070086 LOCAL_DRIVERS_PATH \
87 "/usr/" LIBDIR VULKAN_ICD_DIR
Adam Jackson05487a22015-07-23 16:29:26 -040088#define DEFAULT_VK_LAYERS_INFO \
James Jonesac945bc2015-07-23 17:39:37 -070089 LOCAL_LAYERS_INFO \
James Jonesfb6b3b32015-07-24 09:47:37 -070090 "/" SYSCONFDIR VULKAN_ELAYERCONF_DIR ":" \
91 "/" SYSCONFDIR VULKAN_ILAYERCONF_DIR ":" \
James Jonesac945bc2015-07-23 17:39:37 -070092 "/usr/" DATADIR VULKAN_ELAYERCONF_DIR ":" \
93 "/usr/" DATADIR VULKAN_ILAYERCONF_DIR
Adam Jackson05487a22015-07-23 16:29:26 -040094#define DEFAULT_VK_LAYERS_PATH \
James Jonesac945bc2015-07-23 17:39:37 -070095 LOCAL_LAYERS_PATH \
96 "/usr/" LIBDIR VULKAN_LAYER_DIR
Jon Ashburn68e2bef2015-08-06 11:22:33 -060097#define LAYERS_PATH_ENV "VK_LAYER_PATH"
Ian Elliott665c5632015-02-04 11:22:39 -070098
Ian Elliottecb60ec2015-02-12 16:44:56 -070099// C99:
Tobin Ehlisbf0146e2015-02-11 14:24:02 -0700100#define PRINTF_SIZE_T_SPECIFIER "%zu"
101
Jon Ashburnffd5d672015-06-29 11:25:34 -0600102// File IO
103static inline bool loader_platform_file_exists(const char *path)
104{
105 if (access(path, F_OK))
106 return false;
107 else
108 return true;
109}
110
Jon Ashburn38144502015-07-07 15:06:25 -0600111static inline bool loader_platform_is_path_absolute(const char *path)
112{
113 if (path[0] == '/')
114 return true;
115 else
116 return false;
117}
118
119static inline char *loader_platform_dirname(char *path)
120{
121 return dirname(path);
122}
123
Jon Ashburnffd5d672015-06-29 11:25:34 -0600124// Dynamic Loading of libraries:
Ian Elliott81ac44c2015-01-13 17:52:38 -0700125typedef void * loader_platform_dl_handle;
126static inline loader_platform_dl_handle loader_platform_open_library(const char* libPath)
127{
Chia-I Wu7397c432015-02-18 14:39:54 -0700128 return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700129}
Michael Lentine92689442015-09-09 12:39:13 -0700130static inline const char * loader_platform_open_library_error(const char* libPath)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700131{
132 return dlerror();
133}
134static inline void loader_platform_close_library(loader_platform_dl_handle library)
135{
136 dlclose(library);
137}
138static inline void * loader_platform_get_proc_address(loader_platform_dl_handle library,
139 const char *name)
140{
141 assert(library);
142 assert(name);
143 return dlsym(library, name);
144}
Michael Lentine92689442015-09-09 12:39:13 -0700145static inline const char * loader_platform_get_proc_address_error(const char *name)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700146{
147 return dlerror();
148}
149
150// Threads:
151typedef pthread_t loader_platform_thread;
Jon Ashburn413d6582015-08-28 15:19:27 -0600152#define THREAD_LOCAL_DECL __thread
Ian Elliott81ac44c2015-01-13 17:52:38 -0700153#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
154 pthread_once_t var = PTHREAD_ONCE_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600155#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
156 pthread_once_t var;
Michael Lentine92689442015-09-09 12:39:13 -0700157static inline void loader_platform_thread_once(pthread_once_t *ctl, void (* func) (void))
Ian Elliott81ac44c2015-01-13 17:52:38 -0700158{
159 assert(func != NULL);
160 assert(ctl != NULL);
Michael Lentine92689442015-09-09 12:39:13 -0700161 pthread_once(ctl, func);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700162}
163
164// Thread IDs:
165typedef pthread_t loader_platform_thread_id;
166static inline loader_platform_thread_id loader_platform_get_thread_id()
167{
168 return pthread_self();
169}
170
171// Thread mutex:
172typedef pthread_mutex_t loader_platform_thread_mutex;
173static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
174{
175 pthread_mutex_init(pMutex, NULL);
176}
177static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
178{
179 pthread_mutex_lock(pMutex);
180}
181static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
182{
183 pthread_mutex_unlock(pMutex);
184}
185static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
186{
187 pthread_mutex_destroy(pMutex);
188}
Mike Stroyan354ed672015-05-15 08:50:57 -0600189typedef pthread_cond_t loader_platform_thread_cond;
190static inline void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
191{
192 pthread_cond_init(pCond, NULL);
193}
194static inline void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
195{
196 pthread_cond_wait(pCond, pMutex);
197}
198static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
199{
200 pthread_cond_broadcast(pCond);
201}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700202
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600203#define loader_stack_alloc(size) alloca(size)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700204
205#elif defined(_WIN32) // defined(__linux__)
206/* Windows-specific common code: */
207
208// Headers:
Piers Danielle2bca482015-02-24 13:58:47 -0700209#include <WinSock2.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700210#include <windows.h>
211#include <assert.h>
Tony Barbour69698512015-06-18 16:29:32 -0600212#include <stdio.h>
Jon Ashburnee33ae72015-06-30 14:46:22 -0700213#include <io.h>
214#include <stdbool.h>
Cody Northrop62ac1c52015-07-08 16:48:37 -0600215#include <shlwapi.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700216#ifdef __cplusplus
217#include <iostream>
218#include <string>
219using namespace std;
220#endif // __cplusplus
221
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600222// VK Library Filenames, Paths, etc.:
Ian Elliott665c5632015-02-04 11:22:39 -0700223#define PATH_SEPERATOR ';'
Jon Ashburnffd5d672015-06-29 11:25:34 -0600224#define DIRECTORY_SYMBOL '\\'
Jon Ashburnee33ae72015-06-30 14:46:22 -0700225#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
226#define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\Vulkan\\Drivers"
Jon Ashburnffd5d672015-06-29 11:25:34 -0600227// TODO: Are these the correct paths
scygan8420b4c2015-06-01 19:47:08 +0200228#define DEFAULT_VK_DRIVERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn1b111de2015-07-06 15:40:35 -0600229#define DEFAULT_VK_LAYERS_INFO "SOFTWARE\\Khronos\\Vulkan\\ExplicitLayers;SOFTWARE\\Khronos\\Vulkan\\ImplicitLayers"
Jon Ashburn38144502015-07-07 15:06:25 -0600230#define DEFAULT_VK_LAYERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn68e2bef2015-08-06 11:22:33 -0600231#define LAYERS_PATH_ENV "VK_LAYER_PATH"
Ian Elliott665c5632015-02-04 11:22:39 -0700232
Courtney Goeltzenleuchterb5738ca2015-10-07 17:03:42 -0600233#define PRINTF_SIZE_T_SPECIFIER "%Iu"
234
Jon Ashburnffd5d672015-06-29 11:25:34 -0600235// File IO
Jon Ashburnee33ae72015-06-30 14:46:22 -0700236static bool loader_platform_file_exists(const char *path)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600237{
Jon Ashburnee33ae72015-06-30 14:46:22 -0700238 if ((_access(path, 0)) == -1)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600239 return false;
240 else
241 return true;
242}
243
Cody Northrop62ac1c52015-07-08 16:48:37 -0600244static bool loader_platform_is_path_absolute(const char *path)
Jon Ashburn38144502015-07-07 15:06:25 -0600245{
246 return !PathIsRelative(path);
247}
248
249// WIN32 runtime doesn't have dirname().
250static inline char *loader_platform_dirname(char *path)
251{
252 char *current, *next;
253
254 // TODO/TBD: Do we need to deal with the Windows's ":" character?
255
256 for (current = path; *current != '\0'; current = next) {
257 next = strchr(current, DIRECTORY_SYMBOL);
258 if (next == NULL) {
259 if (current != path)
260 *(current - 1) = '\0';
261 return path;
262 } else {
263 // Point one character past the DIRECTORY_SYMBOL:
264 next++;
265 }
266 }
267 return path;
268}
269
270// WIN32 runtime doesn't have basename().
271// Microsoft also doesn't have basename(). Paths are different on Windows, and
272// so this is just a temporary solution in order to get us compiling, so that we
273// can test some scenarios, and develop the correct solution for Windows.
274 // TODO: Develop a better, permanent solution for Windows, to replace this
275 // temporary code:
276static char *loader_platform_basename(char *pathname)
277{
278 char *current, *next;
279
280// TODO/TBD: Do we need to deal with the Windows's ":" character?
281
282 for (current = pathname; *current != '\0'; current = next) {
283 next = strchr(current, DIRECTORY_SYMBOL);
284 if (next == NULL) {
285 // No more DIRECTORY_SYMBOL's so return p:
286 return current;
287 } else {
288 // Point one character past the DIRECTORY_SYMBOL:
289 next++;
290 }
291 }
292 // We shouldn't get to here, but this makes the compiler happy:
293 return current;
294}
295
Ian Elliott81ac44c2015-01-13 17:52:38 -0700296// Dynamic Loading:
297typedef HMODULE loader_platform_dl_handle;
298static loader_platform_dl_handle loader_platform_open_library(const char* libPath)
299{
300 return LoadLibrary(libPath);
301}
302static char * loader_platform_open_library_error(const char* libPath)
303{
304 static char errorMsg[120];
305 snprintf(errorMsg, 119, "Failed to open dynamic library \"%s\"", libPath);
306 return errorMsg;
307}
308static void loader_platform_close_library(loader_platform_dl_handle library)
309{
310 FreeLibrary(library);
311}
312static void * loader_platform_get_proc_address(loader_platform_dl_handle library,
313 const char *name)
314{
315 assert(library);
316 assert(name);
317 return GetProcAddress(library, name);
318}
319static char * loader_platform_get_proc_address_error(const char *name)
320{
321 static char errorMsg[120];
322 snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
323 return errorMsg;
324}
325
326// Threads:
327typedef HANDLE loader_platform_thread;
Jon Ashburn413d6582015-08-28 15:19:27 -0600328#define THREAD_LOCAL_DECL __declspec(thread)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700329#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
330 INIT_ONCE var = INIT_ONCE_STATIC_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600331#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
332 INIT_ONCE var;
Piers Daniell886be472015-02-23 16:23:13 -0700333static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
334{
335 void (*func)(void) = (void (*)(void))Parameter;
336 func();
337 return TRUE;
338}
339
Ian Elliott81ac44c2015-01-13 17:52:38 -0700340static void loader_platform_thread_once(void *ctl, void (* func) (void))
341{
342 assert(func != NULL);
343 assert(ctl != NULL);
Piers Daniell886be472015-02-23 16:23:13 -0700344 InitOnceExecuteOnce((PINIT_ONCE) ctl, InitFuncWrapper, func, NULL);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700345}
346
347// Thread IDs:
348typedef DWORD loader_platform_thread_id;
349static loader_platform_thread_id loader_platform_get_thread_id()
350{
351 return GetCurrentThreadId();
352}
353
354// Thread mutex:
355typedef CRITICAL_SECTION loader_platform_thread_mutex;
356static void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
357{
358 InitializeCriticalSection(pMutex);
359}
360static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
361{
362 EnterCriticalSection(pMutex);
363}
364static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
365{
366 LeaveCriticalSection(pMutex);
367}
368static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
369{
370 DeleteCriticalSection(pMutex);
371}
Mike Stroyan33053d02015-05-15 17:34:51 -0600372typedef CONDITION_VARIABLE loader_platform_thread_cond;
373static void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
374{
375 InitializeConditionVariable(pCond);
376}
377static void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
378{
379 SleepConditionVariableCS(pCond, pMutex, INFINITE);
380}
381static void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
382{
383 WakeAllConditionVariable(pCond);
384}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700385
Ian Elliott76005132015-03-31 15:32:41 -0600386// Windows Registry:
387char *loader_get_registry_string(const HKEY hive,
388 const LPCTSTR sub_key,
389 const char *value);
390
Jon Ashburnf6620c92015-10-15 13:47:58 -0600391#define loader_stack_alloc(size) _alloca(size)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700392#else // defined(_WIN32)
393
394#error The "loader_platform.h" file must be modified for this OS.
395
396// NOTE: In order to support another OS, an #elif needs to be added (above the
397// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
398// contents of this file must be created.
399
400// NOTE: Other OS-specific changes are also needed for this OS. Search for
401// files with "WIN32" in it, as a quick way to find files that must be changed.
402
403#endif // defined(_WIN32)
404