blob: ef5a19f1bcfaae0958a04382e491085067591345 [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 ":"
James Jonesac945bc2015-07-23 17:39:37 -070065#define LOCAL_LAYERS_INFO \
66 LOCALPREFIX "/" SYSCONFDIR VULKAN_ELAYERCONF_DIR ":" \
67 LOCALPREFIX "/" SYSCONFDIR VULKAN_ILAYERCONF_DIR ":" \
68 LOCALPREFIX "/" DATADIR VULKAN_ELAYERCONF_DIR ":" \
69 LOCALPREFIX "/" DATADIR VULKAN_ILAYERCONF_DIR ":"
James Jonesac945bc2015-07-23 17:39:37 -070070#else
71#define LOCAL_DRIVERS_INFO
James Jonesac945bc2015-07-23 17:39:37 -070072#define LOCAL_LAYERS_INFO
James Jonesac945bc2015-07-23 17:39:37 -070073#endif
74
Adam Jackson05487a22015-07-23 16:29:26 -040075#define DEFAULT_VK_DRIVERS_INFO \
James Jonesac945bc2015-07-23 17:39:37 -070076 LOCAL_DRIVERS_INFO \
James Jonesfb6b3b32015-07-24 09:47:37 -070077 "/" SYSCONFDIR VULKAN_ICDCONF_DIR ":" \
James Jonesac945bc2015-07-23 17:39:37 -070078 "/usr/" DATADIR VULKAN_ICDCONF_DIR
Daniel Dadap7bb2c232015-09-30 12:09:49 -050079#define DEFAULT_VK_DRIVERS_PATH ""
Adam Jackson05487a22015-07-23 16:29:26 -040080#define DEFAULT_VK_LAYERS_INFO \
James Jonesac945bc2015-07-23 17:39:37 -070081 LOCAL_LAYERS_INFO \
James Jonesfb6b3b32015-07-24 09:47:37 -070082 "/" SYSCONFDIR VULKAN_ELAYERCONF_DIR ":" \
83 "/" SYSCONFDIR VULKAN_ILAYERCONF_DIR ":" \
James Jonesac945bc2015-07-23 17:39:37 -070084 "/usr/" DATADIR VULKAN_ELAYERCONF_DIR ":" \
85 "/usr/" DATADIR VULKAN_ILAYERCONF_DIR
Daniel Dadap7bb2c232015-09-30 12:09:49 -050086#define DEFAULT_VK_LAYERS_PATH ""
Jon Ashburn68e2bef2015-08-06 11:22:33 -060087#define LAYERS_PATH_ENV "VK_LAYER_PATH"
Ian Elliott665c5632015-02-04 11:22:39 -070088
Ian Elliottecb60ec2015-02-12 16:44:56 -070089// C99:
Tobin Ehlisbf0146e2015-02-11 14:24:02 -070090#define PRINTF_SIZE_T_SPECIFIER "%zu"
91
Jon Ashburnffd5d672015-06-29 11:25:34 -060092// File IO
93static inline bool loader_platform_file_exists(const char *path)
94{
95 if (access(path, F_OK))
96 return false;
97 else
98 return true;
99}
100
Jon Ashburn38144502015-07-07 15:06:25 -0600101static inline bool loader_platform_is_path_absolute(const char *path)
102{
103 if (path[0] == '/')
104 return true;
105 else
106 return false;
107}
108
Daniel Dadap2e13fca2015-09-30 11:50:51 -0500109// returns true if the given string appears to be a relative or absolute
110// path, as opposed to a bare filename.
111static inline bool loader_platform_is_path(const char *path)
112{
113 return strchr(path, DIRECTORY_SYMBOL) != NULL;
114}
115
Jon Ashburn38144502015-07-07 15:06:25 -0600116static inline char *loader_platform_dirname(char *path)
117{
118 return dirname(path);
119}
120
Jon Ashburnffd5d672015-06-29 11:25:34 -0600121// Dynamic Loading of libraries:
Ian Elliott81ac44c2015-01-13 17:52:38 -0700122typedef void * loader_platform_dl_handle;
123static inline loader_platform_dl_handle loader_platform_open_library(const char* libPath)
124{
Chia-I Wu7397c432015-02-18 14:39:54 -0700125 return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700126}
Michael Lentine92689442015-09-09 12:39:13 -0700127static inline const char * loader_platform_open_library_error(const char* libPath)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700128{
129 return dlerror();
130}
131static inline void loader_platform_close_library(loader_platform_dl_handle library)
132{
133 dlclose(library);
134}
135static inline void * loader_platform_get_proc_address(loader_platform_dl_handle library,
136 const char *name)
137{
138 assert(library);
139 assert(name);
140 return dlsym(library, name);
141}
Michael Lentine92689442015-09-09 12:39:13 -0700142static inline const char * loader_platform_get_proc_address_error(const char *name)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700143{
144 return dlerror();
145}
146
147// Threads:
148typedef pthread_t loader_platform_thread;
Jon Ashburn413d6582015-08-28 15:19:27 -0600149#define THREAD_LOCAL_DECL __thread
Ian Elliott81ac44c2015-01-13 17:52:38 -0700150#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
151 pthread_once_t var = PTHREAD_ONCE_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600152#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
153 pthread_once_t var;
Michael Lentine92689442015-09-09 12:39:13 -0700154static inline void loader_platform_thread_once(pthread_once_t *ctl, void (* func) (void))
Ian Elliott81ac44c2015-01-13 17:52:38 -0700155{
156 assert(func != NULL);
157 assert(ctl != NULL);
Michael Lentine92689442015-09-09 12:39:13 -0700158 pthread_once(ctl, func);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700159}
160
161// Thread IDs:
162typedef pthread_t loader_platform_thread_id;
163static inline loader_platform_thread_id loader_platform_get_thread_id()
164{
165 return pthread_self();
166}
167
168// Thread mutex:
169typedef pthread_mutex_t loader_platform_thread_mutex;
170static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
171{
172 pthread_mutex_init(pMutex, NULL);
173}
174static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
175{
176 pthread_mutex_lock(pMutex);
177}
178static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
179{
180 pthread_mutex_unlock(pMutex);
181}
182static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
183{
184 pthread_mutex_destroy(pMutex);
185}
Mike Stroyan354ed672015-05-15 08:50:57 -0600186typedef pthread_cond_t loader_platform_thread_cond;
187static inline void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
188{
189 pthread_cond_init(pCond, NULL);
190}
191static inline void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
192{
193 pthread_cond_wait(pCond, pMutex);
194}
195static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
196{
197 pthread_cond_broadcast(pCond);
198}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700199
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600200#define loader_stack_alloc(size) alloca(size)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700201
202#elif defined(_WIN32) // defined(__linux__)
203/* Windows-specific common code: */
204
205// Headers:
Piers Danielle2bca482015-02-24 13:58:47 -0700206#include <WinSock2.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700207#include <windows.h>
208#include <assert.h>
Tony Barbour69698512015-06-18 16:29:32 -0600209#include <stdio.h>
Jon Ashburnee33ae72015-06-30 14:46:22 -0700210#include <io.h>
211#include <stdbool.h>
Cody Northrop62ac1c52015-07-08 16:48:37 -0600212#include <shlwapi.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700213#ifdef __cplusplus
214#include <iostream>
215#include <string>
216using namespace std;
217#endif // __cplusplus
218
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600219// VK Library Filenames, Paths, etc.:
Ian Elliott665c5632015-02-04 11:22:39 -0700220#define PATH_SEPERATOR ';'
Jon Ashburnffd5d672015-06-29 11:25:34 -0600221#define DIRECTORY_SYMBOL '\\'
Jon Ashburnee33ae72015-06-30 14:46:22 -0700222#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
223#define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\Vulkan\\Drivers"
Jon Ashburnffd5d672015-06-29 11:25:34 -0600224// TODO: Are these the correct paths
scygan8420b4c2015-06-01 19:47:08 +0200225#define DEFAULT_VK_DRIVERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn1b111de2015-07-06 15:40:35 -0600226#define DEFAULT_VK_LAYERS_INFO "SOFTWARE\\Khronos\\Vulkan\\ExplicitLayers;SOFTWARE\\Khronos\\Vulkan\\ImplicitLayers"
Jon Ashburn38144502015-07-07 15:06:25 -0600227#define DEFAULT_VK_LAYERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn68e2bef2015-08-06 11:22:33 -0600228#define LAYERS_PATH_ENV "VK_LAYER_PATH"
Ian Elliott665c5632015-02-04 11:22:39 -0700229
Courtney Goeltzenleuchterb5738ca2015-10-07 17:03:42 -0600230#define PRINTF_SIZE_T_SPECIFIER "%Iu"
231
Jon Ashburnffd5d672015-06-29 11:25:34 -0600232// File IO
Jon Ashburnee33ae72015-06-30 14:46:22 -0700233static bool loader_platform_file_exists(const char *path)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600234{
Jon Ashburnee33ae72015-06-30 14:46:22 -0700235 if ((_access(path, 0)) == -1)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600236 return false;
237 else
238 return true;
239}
240
Cody Northrop62ac1c52015-07-08 16:48:37 -0600241static bool loader_platform_is_path_absolute(const char *path)
Jon Ashburn38144502015-07-07 15:06:25 -0600242{
243 return !PathIsRelative(path);
244}
245
246// WIN32 runtime doesn't have dirname().
247static inline char *loader_platform_dirname(char *path)
248{
249 char *current, *next;
250
251 // TODO/TBD: Do we need to deal with the Windows's ":" character?
252
253 for (current = path; *current != '\0'; current = next) {
254 next = strchr(current, DIRECTORY_SYMBOL);
255 if (next == NULL) {
256 if (current != path)
257 *(current - 1) = '\0';
258 return path;
259 } else {
260 // Point one character past the DIRECTORY_SYMBOL:
261 next++;
262 }
263 }
264 return path;
265}
266
267// WIN32 runtime doesn't have basename().
268// Microsoft also doesn't have basename(). Paths are different on Windows, and
269// so this is just a temporary solution in order to get us compiling, so that we
270// can test some scenarios, and develop the correct solution for Windows.
271 // TODO: Develop a better, permanent solution for Windows, to replace this
272 // temporary code:
273static char *loader_platform_basename(char *pathname)
274{
275 char *current, *next;
276
277// TODO/TBD: Do we need to deal with the Windows's ":" character?
278
279 for (current = pathname; *current != '\0'; current = next) {
280 next = strchr(current, DIRECTORY_SYMBOL);
281 if (next == NULL) {
282 // No more DIRECTORY_SYMBOL's so return p:
283 return current;
284 } else {
285 // Point one character past the DIRECTORY_SYMBOL:
286 next++;
287 }
288 }
289 // We shouldn't get to here, but this makes the compiler happy:
290 return current;
291}
292
Ian Elliott81ac44c2015-01-13 17:52:38 -0700293// Dynamic Loading:
294typedef HMODULE loader_platform_dl_handle;
295static loader_platform_dl_handle loader_platform_open_library(const char* libPath)
296{
297 return LoadLibrary(libPath);
298}
299static char * loader_platform_open_library_error(const char* libPath)
300{
301 static char errorMsg[120];
302 snprintf(errorMsg, 119, "Failed to open dynamic library \"%s\"", libPath);
303 return errorMsg;
304}
305static void loader_platform_close_library(loader_platform_dl_handle library)
306{
307 FreeLibrary(library);
308}
309static void * loader_platform_get_proc_address(loader_platform_dl_handle library,
310 const char *name)
311{
312 assert(library);
313 assert(name);
314 return GetProcAddress(library, name);
315}
316static char * loader_platform_get_proc_address_error(const char *name)
317{
318 static char errorMsg[120];
319 snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
320 return errorMsg;
321}
322
323// Threads:
324typedef HANDLE loader_platform_thread;
Jon Ashburn413d6582015-08-28 15:19:27 -0600325#define THREAD_LOCAL_DECL __declspec(thread)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700326#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
327 INIT_ONCE var = INIT_ONCE_STATIC_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600328#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
329 INIT_ONCE var;
Piers Daniell886be472015-02-23 16:23:13 -0700330static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
331{
332 void (*func)(void) = (void (*)(void))Parameter;
333 func();
334 return TRUE;
335}
336
Ian Elliott81ac44c2015-01-13 17:52:38 -0700337static void loader_platform_thread_once(void *ctl, void (* func) (void))
338{
339 assert(func != NULL);
340 assert(ctl != NULL);
Piers Daniell886be472015-02-23 16:23:13 -0700341 InitOnceExecuteOnce((PINIT_ONCE) ctl, InitFuncWrapper, func, NULL);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700342}
343
344// Thread IDs:
345typedef DWORD loader_platform_thread_id;
346static loader_platform_thread_id loader_platform_get_thread_id()
347{
348 return GetCurrentThreadId();
349}
350
351// Thread mutex:
352typedef CRITICAL_SECTION loader_platform_thread_mutex;
353static void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
354{
355 InitializeCriticalSection(pMutex);
356}
357static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
358{
359 EnterCriticalSection(pMutex);
360}
361static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
362{
363 LeaveCriticalSection(pMutex);
364}
365static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
366{
367 DeleteCriticalSection(pMutex);
368}
Mike Stroyan33053d02015-05-15 17:34:51 -0600369typedef CONDITION_VARIABLE loader_platform_thread_cond;
370static void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
371{
372 InitializeConditionVariable(pCond);
373}
374static void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
375{
376 SleepConditionVariableCS(pCond, pMutex, INFINITE);
377}
378static void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
379{
380 WakeAllConditionVariable(pCond);
381}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700382
Ian Elliott76005132015-03-31 15:32:41 -0600383// Windows Registry:
384char *loader_get_registry_string(const HKEY hive,
385 const LPCTSTR sub_key,
386 const char *value);
387
Jon Ashburnf6620c92015-10-15 13:47:58 -0600388#define loader_stack_alloc(size) _alloca(size)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700389#else // defined(_WIN32)
390
391#error The "loader_platform.h" file must be modified for this OS.
392
393// NOTE: In order to support another OS, an #elif needs to be added (above the
394// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
395// contents of this file must be created.
396
397// NOTE: Other OS-specific changes are also needed for this OS. Search for
398// files with "WIN32" in it, as a quick way to find files that must be changed.
399
400#endif // defined(_WIN32)
401