blob: 52d90a374a55b9b4fe35e140fb3e4499c7521084 [file] [log] [blame]
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07001/*
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07002 *
Courtney Goeltzenleuchterfcbe16f2015-10-29 13:50:34 -06003 * Copyright (C) 2015 Valve Corporation
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07004 * Copyright 2014 Valve Software
Michael Lentine695f2c22015-09-09 12:39:13 -07005 * Copyright (C) 2015 Google Inc.
Ian Elliott2d4ab1e2015-01-13 17:52:38 -07006 * 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 *
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060026 * Author: James Jones <jajones@nvidia.com>
27 * Author: Tobin Ehlis <tobin@lunarg.com>
28 *
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070029 */
Jon Ashburn3f8c3002015-10-15 13:47:58 -060030#pragma once
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070031
Mark Lobodzinski450e4632015-11-24 12:04:15 -070032#if defined(_WIN32)
33// WinSock2.h must be included *BEFORE* windows.h
Mark Lobodzinski450e4632015-11-24 12:04:15 -070034#include <WinSock2.h>
35#endif // _WIN32
36
David Pinedo9316d3b2015-11-06 12:54:48 -070037#include "vulkan/vk_platform.h"
38#include "vulkan/vk_sdk_platform.h"
Cody Northrop33fa0412015-07-08 16:48:37 -060039
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070040#if defined(__linux__)
41/* Linux-specific common code: */
42
43// Headers:
44//#define _GNU_SOURCE 1
45// TBD: Are the contents of the following file used?
46#include <unistd.h>
47// Note: The following file is for dynamic loading:
48#include <dlfcn.h>
49#include <pthread.h>
50#include <assert.h>
Jon Ashburnfc1031e2015-11-17 15:31:02 -070051#include <string.h>
Jon Ashburn2077e382015-06-29 11:25:34 -060052#include <stdbool.h>
Michael Lentine695f2c22015-09-09 12:39:13 -070053#include <stdlib.h>
Jon Ashburn15315172015-07-07 15:06:25 -060054#include <libgen.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -070055
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -060056// VK Library Filenames, Paths, etc.:
Ian Elliott457810e2015-02-04 11:22:39 -070057#define PATH_SEPERATOR ':'
Jon Ashburn2077e382015-06-29 11:25:34 -060058#define DIRECTORY_SYMBOL '/'
59
James Jonesc28b0a12015-07-23 17:39:37 -070060#define VULKAN_ICDCONF_DIR "/" "vulkan" "/" "icd.d"
61#define VULKAN_ICD_DIR "/" "vulkan" "/" "icd"
James Jones34c500b2015-07-24 11:35:16 -070062#define VULKAN_ELAYERCONF_DIR "/" "vulkan" "/" "explicit_layer.d"
James Jonesc28b0a12015-07-23 17:39:37 -070063#define VULKAN_ILAYERCONF_DIR "/" "vulkan" "/" "implicit_layer.d"
64#define VULKAN_LAYER_DIR "/" "vulkan" "/" "layer"
65
66#if defined(LOCALPREFIX)
67#define LOCAL_DRIVERS_INFO \
68 LOCALPREFIX "/" SYSCONFDIR VULKAN_ICDCONF_DIR ":" \
69 LOCALPREFIX "/" DATADIR VULKAN_ICDCONF_DIR ":"
Jon Ashburn075ce432015-12-17 17:38:24 -070070#define LOCAL_ELAYERS_INFO \
James Jonesc28b0a12015-07-23 17:39:37 -070071 LOCALPREFIX "/" SYSCONFDIR VULKAN_ELAYERCONF_DIR ":" \
Jon Ashburn075ce432015-12-17 17:38:24 -070072 LOCALPREFIX "/" DATADIR VULKAN_ELAYERCONF_DIR ":"
73#define LOCAL_ILAYERS_INFO \
James Jonesc28b0a12015-07-23 17:39:37 -070074 LOCALPREFIX "/" SYSCONFDIR VULKAN_ILAYERCONF_DIR ":" \
James Jonesc28b0a12015-07-23 17:39:37 -070075 LOCALPREFIX "/" DATADIR VULKAN_ILAYERCONF_DIR ":"
James Jonesc28b0a12015-07-23 17:39:37 -070076#else
77#define LOCAL_DRIVERS_INFO
Jon Ashburn075ce432015-12-17 17:38:24 -070078#define LOCAL_ELAYERS_INFO
79#define LOCAL_ILAYERS_INFO
James Jonesc28b0a12015-07-23 17:39:37 -070080#endif
81
Adam Jackson3869f412015-07-23 16:29:26 -040082#define DEFAULT_VK_DRIVERS_INFO \
James Jonesc28b0a12015-07-23 17:39:37 -070083 LOCAL_DRIVERS_INFO \
James Jones09a436f2015-07-24 09:47:37 -070084 "/" SYSCONFDIR VULKAN_ICDCONF_DIR ":" \
James Jonesc28b0a12015-07-23 17:39:37 -070085 "/usr/" DATADIR VULKAN_ICDCONF_DIR
Daniel Dadap6e626842015-09-30 12:09:49 -050086#define DEFAULT_VK_DRIVERS_PATH ""
Jon Ashburn075ce432015-12-17 17:38:24 -070087#define DEFAULT_VK_ELAYERS_INFO \
88 LOCAL_ELAYERS_INFO \
James Jones09a436f2015-07-24 09:47:37 -070089 "/" SYSCONFDIR VULKAN_ELAYERCONF_DIR ":" \
Jon Ashburn075ce432015-12-17 17:38:24 -070090 "/usr/" DATADIR VULKAN_ELAYERCONF_DIR ":"
91#define DEFAULT_VK_ILAYERS_INFO \
92 LOCAL_ILAYERS_INFO \
James Jones09a436f2015-07-24 09:47:37 -070093 "/" SYSCONFDIR VULKAN_ILAYERCONF_DIR ":" \
James Jonesc28b0a12015-07-23 17:39:37 -070094 "/usr/" DATADIR VULKAN_ILAYERCONF_DIR
Daniel Dadap6e626842015-09-30 12:09:49 -050095#define DEFAULT_VK_LAYERS_PATH ""
Jon Ashburn1b958222015-08-06 11:22:33 -060096#define LAYERS_PATH_ENV "VK_LAYER_PATH"
Ian Elliott457810e2015-02-04 11:22:39 -070097
Ian Elliotte5369462015-02-12 16:44:56 -070098// C99:
Tobin Ehlisb0497852015-02-11 14:24:02 -070099#define PRINTF_SIZE_T_SPECIFIER "%zu"
100
Jon Ashburn2077e382015-06-29 11:25:34 -0600101// File IO
102static inline bool loader_platform_file_exists(const char *path)
103{
104 if (access(path, F_OK))
105 return false;
106 else
107 return true;
108}
109
Jon Ashburn15315172015-07-07 15:06:25 -0600110static inline bool loader_platform_is_path_absolute(const char *path)
111{
112 if (path[0] == '/')
113 return true;
114 else
115 return false;
116}
117
118static inline char *loader_platform_dirname(char *path)
119{
120 return dirname(path);
121}
122
Jon Ashburn38a497f2016-01-04 14:01:38 -0700123// Environment variables
124
125static inline char *loader_getenv(const char *name)
126{
127 return getenv(name);
128}
129
130static inline void loader_free_getenv(const char *val)
131{
132}
133
Jon Ashburn2077e382015-06-29 11:25:34 -0600134// Dynamic Loading of libraries:
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700135typedef void * loader_platform_dl_handle;
136static inline loader_platform_dl_handle loader_platform_open_library(const char* libPath)
137{
Chia-I Wu6a218342015-02-18 14:39:54 -0700138 return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700139}
Michael Lentine695f2c22015-09-09 12:39:13 -0700140static inline const char * loader_platform_open_library_error(const char* libPath)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700141{
142 return dlerror();
143}
144static inline void loader_platform_close_library(loader_platform_dl_handle library)
145{
146 dlclose(library);
147}
148static inline void * loader_platform_get_proc_address(loader_platform_dl_handle library,
149 const char *name)
150{
151 assert(library);
152 assert(name);
153 return dlsym(library, name);
154}
Michael Lentine695f2c22015-09-09 12:39:13 -0700155static inline const char * loader_platform_get_proc_address_error(const char *name)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700156{
157 return dlerror();
158}
159
160// Threads:
161typedef pthread_t loader_platform_thread;
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600162#define THREAD_LOCAL_DECL __thread
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700163#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
164 pthread_once_t var = PTHREAD_ONCE_INIT;
Jon Ashburn27cd5842015-05-12 17:26:48 -0600165#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
166 pthread_once_t var;
Michael Lentine695f2c22015-09-09 12:39:13 -0700167static inline void loader_platform_thread_once(pthread_once_t *ctl, void (* func) (void))
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700168{
169 assert(func != NULL);
170 assert(ctl != NULL);
Michael Lentine695f2c22015-09-09 12:39:13 -0700171 pthread_once(ctl, func);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700172}
173
174// Thread IDs:
175typedef pthread_t loader_platform_thread_id;
176static inline loader_platform_thread_id loader_platform_get_thread_id()
177{
178 return pthread_self();
179}
180
181// Thread mutex:
182typedef pthread_mutex_t loader_platform_thread_mutex;
183static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
184{
185 pthread_mutex_init(pMutex, NULL);
186}
187static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
188{
189 pthread_mutex_lock(pMutex);
190}
191static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
192{
193 pthread_mutex_unlock(pMutex);
194}
195static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
196{
197 pthread_mutex_destroy(pMutex);
198}
Mike Stroyaned238bb2015-05-15 08:50:57 -0600199typedef pthread_cond_t loader_platform_thread_cond;
200static inline void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
201{
202 pthread_cond_init(pCond, NULL);
203}
204static inline void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
205{
206 pthread_cond_wait(pCond, pMutex);
207}
208static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
209{
210 pthread_cond_broadcast(pCond);
211}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700212
Courtney Goeltzenleuchter7f5aafc2015-07-05 11:28:29 -0600213#define loader_stack_alloc(size) alloca(size)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700214
215#elif defined(_WIN32) // defined(__linux__)
216/* Windows-specific common code: */
Tobin Ehlis890adf12015-11-02 15:45:19 -0700217// WinBase.h defines CreateSemaphore and synchapi.h defines CreateEvent
218// undefine them to avoid conflicts with VkLayerDispatchTable struct members.
219#ifdef CreateSemaphore
220#undef CreateSemaphore
221#endif
222#ifdef CreateEvent
223#undef CreateEvent
224#endif
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700225#include <assert.h>
Tony Barbour1d825c72015-06-18 16:29:32 -0600226#include <stdio.h>
Jon Ashburnfc1031e2015-11-17 15:31:02 -0700227#include <string.h>
Jon Ashburnffad94d2015-06-30 14:46:22 -0700228#include <io.h>
229#include <stdbool.h>
Cody Northrop33fa0412015-07-08 16:48:37 -0600230#include <shlwapi.h>
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700231#ifdef __cplusplus
232#include <iostream>
233#include <string>
234using namespace std;
235#endif // __cplusplus
236
Courtney Goeltzenleuchterd8e229c2015-04-08 15:36:08 -0600237// VK Library Filenames, Paths, etc.:
Ian Elliott457810e2015-02-04 11:22:39 -0700238#define PATH_SEPERATOR ';'
Jon Ashburn2077e382015-06-29 11:25:34 -0600239#define DIRECTORY_SYMBOL '\\'
Jon Ashburnffad94d2015-06-30 14:46:22 -0700240#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
241#define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\Vulkan\\Drivers"
Jon Ashburn2077e382015-06-29 11:25:34 -0600242// TODO: Are these the correct paths
scygan713b1b02015-06-01 19:47:08 +0200243#define DEFAULT_VK_DRIVERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn075ce432015-12-17 17:38:24 -0700244#define DEFAULT_VK_ELAYERS_INFO "SOFTWARE\\Khronos\\Vulkan\\ExplicitLayers"
245#define DEFAULT_VK_ILAYERS_INFO "SOFTWARE\\Khronos\\Vulkan\\ImplicitLayers"
Jon Ashburn15315172015-07-07 15:06:25 -0600246#define DEFAULT_VK_LAYERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn1b958222015-08-06 11:22:33 -0600247#define LAYERS_PATH_ENV "VK_LAYER_PATH"
Ian Elliott457810e2015-02-04 11:22:39 -0700248
Courtney Goeltzenleuchter22d8d792015-10-07 17:03:42 -0600249#define PRINTF_SIZE_T_SPECIFIER "%Iu"
250
Jon Ashburn2077e382015-06-29 11:25:34 -0600251// File IO
Jon Ashburnffad94d2015-06-30 14:46:22 -0700252static bool loader_platform_file_exists(const char *path)
Jon Ashburn2077e382015-06-29 11:25:34 -0600253{
Jon Ashburnffad94d2015-06-30 14:46:22 -0700254 if ((_access(path, 0)) == -1)
Jon Ashburn2077e382015-06-29 11:25:34 -0600255 return false;
256 else
257 return true;
258}
259
Cody Northrop33fa0412015-07-08 16:48:37 -0600260static bool loader_platform_is_path_absolute(const char *path)
Jon Ashburn15315172015-07-07 15:06:25 -0600261{
262 return !PathIsRelative(path);
263}
264
265// WIN32 runtime doesn't have dirname().
266static inline char *loader_platform_dirname(char *path)
267{
268 char *current, *next;
269
270 // TODO/TBD: Do we need to deal with the Windows's ":" character?
271
272 for (current = path; *current != '\0'; current = next) {
273 next = strchr(current, DIRECTORY_SYMBOL);
274 if (next == NULL) {
275 if (current != path)
276 *(current - 1) = '\0';
277 return path;
278 } else {
279 // Point one character past the DIRECTORY_SYMBOL:
280 next++;
281 }
282 }
283 return path;
284}
285
286// WIN32 runtime doesn't have basename().
287// Microsoft also doesn't have basename(). Paths are different on Windows, and
288// so this is just a temporary solution in order to get us compiling, so that we
289// can test some scenarios, and develop the correct solution for Windows.
290 // TODO: Develop a better, permanent solution for Windows, to replace this
291 // temporary code:
292static char *loader_platform_basename(char *pathname)
293{
294 char *current, *next;
295
296// TODO/TBD: Do we need to deal with the Windows's ":" character?
297
298 for (current = pathname; *current != '\0'; current = next) {
299 next = strchr(current, DIRECTORY_SYMBOL);
300 if (next == NULL) {
301 // No more DIRECTORY_SYMBOL's so return p:
302 return current;
303 } else {
304 // Point one character past the DIRECTORY_SYMBOL:
305 next++;
306 }
307 }
308 // We shouldn't get to here, but this makes the compiler happy:
309 return current;
310}
311
Jon Ashburn38a497f2016-01-04 14:01:38 -0700312// Environment variables
313
314static inline char *loader_getenv(const char *name)
315{
316 char *retVal;
317 DWORD valSize;
318
319 valSize = GetEnvironmentVariableA(name, NULL, 0);
320
321 // valSize DOES include the null terminator, so for any set variable
322 // will always be at least 1. If it's 0, the variable wasn't set.
323 if (valSize == 0)
324 return NULL;
325
326 //TODO; FIXME This should be using any app defined memory allocation
327 retVal = (char *)malloc(valSize);
328
329 GetEnvironmentVariableA(name, retVal, valSize);
330
331 return retVal;
332}
333
334static inline void loader_free_getenv(const char *val)
335{
336 free((void *)val);
337}
338
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700339// Dynamic Loading:
340typedef HMODULE loader_platform_dl_handle;
341static loader_platform_dl_handle loader_platform_open_library(const char* libPath)
342{
343 return LoadLibrary(libPath);
344}
345static char * loader_platform_open_library_error(const char* libPath)
346{
347 static char errorMsg[120];
348 snprintf(errorMsg, 119, "Failed to open dynamic library \"%s\"", libPath);
349 return errorMsg;
350}
351static void loader_platform_close_library(loader_platform_dl_handle library)
352{
353 FreeLibrary(library);
354}
355static void * loader_platform_get_proc_address(loader_platform_dl_handle library,
356 const char *name)
357{
358 assert(library);
359 assert(name);
360 return GetProcAddress(library, name);
361}
362static char * loader_platform_get_proc_address_error(const char *name)
363{
364 static char errorMsg[120];
365 snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
366 return errorMsg;
367}
368
369// Threads:
370typedef HANDLE loader_platform_thread;
Jon Ashburn87d6aa92015-08-28 15:19:27 -0600371#define THREAD_LOCAL_DECL __declspec(thread)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700372#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
373 INIT_ONCE var = INIT_ONCE_STATIC_INIT;
Jon Ashburn27cd5842015-05-12 17:26:48 -0600374#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
375 INIT_ONCE var;
Piers Daniell4da523a2015-02-23 16:23:13 -0700376static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
377{
378 void (*func)(void) = (void (*)(void))Parameter;
379 func();
380 return TRUE;
381}
382
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700383static void loader_platform_thread_once(void *ctl, void (* func) (void))
384{
385 assert(func != NULL);
386 assert(ctl != NULL);
Piers Daniell4da523a2015-02-23 16:23:13 -0700387 InitOnceExecuteOnce((PINIT_ONCE) ctl, InitFuncWrapper, func, NULL);
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700388}
389
390// Thread IDs:
391typedef DWORD loader_platform_thread_id;
392static loader_platform_thread_id loader_platform_get_thread_id()
393{
394 return GetCurrentThreadId();
395}
396
397// Thread mutex:
398typedef CRITICAL_SECTION loader_platform_thread_mutex;
399static void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
400{
401 InitializeCriticalSection(pMutex);
402}
403static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
404{
405 EnterCriticalSection(pMutex);
406}
407static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
408{
409 LeaveCriticalSection(pMutex);
410}
411static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
412{
413 DeleteCriticalSection(pMutex);
414}
Mike Stroyanc3d98332015-05-15 17:34:51 -0600415typedef CONDITION_VARIABLE loader_platform_thread_cond;
416static void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
417{
418 InitializeConditionVariable(pCond);
419}
420static void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
421{
422 SleepConditionVariableCS(pCond, pMutex, INFINITE);
423}
424static void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
425{
426 WakeAllConditionVariable(pCond);
427}
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700428
Ian Elliott5aa4ea22015-03-31 15:32:41 -0600429// Windows Registry:
430char *loader_get_registry_string(const HKEY hive,
431 const LPCTSTR sub_key,
432 const char *value);
433
Jon Ashburn3f8c3002015-10-15 13:47:58 -0600434#define loader_stack_alloc(size) _alloca(size)
Ian Elliott2d4ab1e2015-01-13 17:52:38 -0700435#else // defined(_WIN32)
436
437#error The "loader_platform.h" file must be modified for this OS.
438
439// NOTE: In order to support another OS, an #elif needs to be added (above the
440// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
441// contents of this file must be created.
442
443// NOTE: Other OS-specific changes are also needed for this OS. Search for
444// files with "WIN32" in it, as a quick way to find files that must be changed.
445
446#endif // defined(_WIN32)
447
jon547bbee2015-10-29 14:57:03 -0600448// returns true if the given string appears to be a relative or absolute
449// path, as opposed to a bare filename.
450static inline bool loader_platform_is_path(const char *path)
451{
452 return strchr(path, DIRECTORY_SYMBOL) != NULL;
453}