blob: ced2fd28607f5712ee3c4d06dc0913cb222d2fb8 [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
Daniel Dadap2e13fca2015-09-30 11:50:51 -0500119// returns true if the given string appears to be a relative or absolute
120// path, as opposed to a bare filename.
121static inline bool loader_platform_is_path(const char *path)
122{
123 return strchr(path, DIRECTORY_SYMBOL) != NULL;
124}
125
Jon Ashburn38144502015-07-07 15:06:25 -0600126static inline char *loader_platform_dirname(char *path)
127{
128 return dirname(path);
129}
130
Jon Ashburnffd5d672015-06-29 11:25:34 -0600131// Dynamic Loading of libraries:
Ian Elliott81ac44c2015-01-13 17:52:38 -0700132typedef void * loader_platform_dl_handle;
133static inline loader_platform_dl_handle loader_platform_open_library(const char* libPath)
134{
Chia-I Wu7397c432015-02-18 14:39:54 -0700135 return dlopen(libPath, RTLD_LAZY | RTLD_LOCAL);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700136}
Michael Lentine92689442015-09-09 12:39:13 -0700137static inline const char * loader_platform_open_library_error(const char* libPath)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700138{
139 return dlerror();
140}
141static inline void loader_platform_close_library(loader_platform_dl_handle library)
142{
143 dlclose(library);
144}
145static inline void * loader_platform_get_proc_address(loader_platform_dl_handle library,
146 const char *name)
147{
148 assert(library);
149 assert(name);
150 return dlsym(library, name);
151}
Michael Lentine92689442015-09-09 12:39:13 -0700152static inline const char * loader_platform_get_proc_address_error(const char *name)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700153{
154 return dlerror();
155}
156
157// Threads:
158typedef pthread_t loader_platform_thread;
Jon Ashburn413d6582015-08-28 15:19:27 -0600159#define THREAD_LOCAL_DECL __thread
Ian Elliott81ac44c2015-01-13 17:52:38 -0700160#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
161 pthread_once_t var = PTHREAD_ONCE_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600162#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
163 pthread_once_t var;
Michael Lentine92689442015-09-09 12:39:13 -0700164static inline void loader_platform_thread_once(pthread_once_t *ctl, void (* func) (void))
Ian Elliott81ac44c2015-01-13 17:52:38 -0700165{
166 assert(func != NULL);
167 assert(ctl != NULL);
Michael Lentine92689442015-09-09 12:39:13 -0700168 pthread_once(ctl, func);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700169}
170
171// Thread IDs:
172typedef pthread_t loader_platform_thread_id;
173static inline loader_platform_thread_id loader_platform_get_thread_id()
174{
175 return pthread_self();
176}
177
178// Thread mutex:
179typedef pthread_mutex_t loader_platform_thread_mutex;
180static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
181{
182 pthread_mutex_init(pMutex, NULL);
183}
184static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
185{
186 pthread_mutex_lock(pMutex);
187}
188static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
189{
190 pthread_mutex_unlock(pMutex);
191}
192static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
193{
194 pthread_mutex_destroy(pMutex);
195}
Mike Stroyan354ed672015-05-15 08:50:57 -0600196typedef pthread_cond_t loader_platform_thread_cond;
197static inline void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
198{
199 pthread_cond_init(pCond, NULL);
200}
201static inline void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
202{
203 pthread_cond_wait(pCond, pMutex);
204}
205static inline void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
206{
207 pthread_cond_broadcast(pCond);
208}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700209
Courtney Goeltzenleuchterb620ace2015-07-05 11:28:29 -0600210#define loader_stack_alloc(size) alloca(size)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700211
212#elif defined(_WIN32) // defined(__linux__)
213/* Windows-specific common code: */
214
215// Headers:
Piers Danielle2bca482015-02-24 13:58:47 -0700216#include <WinSock2.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700217#include <windows.h>
218#include <assert.h>
Tony Barbour69698512015-06-18 16:29:32 -0600219#include <stdio.h>
Jon Ashburnee33ae72015-06-30 14:46:22 -0700220#include <io.h>
221#include <stdbool.h>
Cody Northrop62ac1c52015-07-08 16:48:37 -0600222#include <shlwapi.h>
Ian Elliott81ac44c2015-01-13 17:52:38 -0700223#ifdef __cplusplus
224#include <iostream>
225#include <string>
226using namespace std;
227#endif // __cplusplus
228
Courtney Goeltzenleuchter9cc421e2015-04-08 15:36:08 -0600229// VK Library Filenames, Paths, etc.:
Ian Elliott665c5632015-02-04 11:22:39 -0700230#define PATH_SEPERATOR ';'
Jon Ashburnffd5d672015-06-29 11:25:34 -0600231#define DIRECTORY_SYMBOL '\\'
Jon Ashburnee33ae72015-06-30 14:46:22 -0700232#define DEFAULT_VK_REGISTRY_HIVE HKEY_LOCAL_MACHINE
233#define DEFAULT_VK_DRIVERS_INFO "SOFTWARE\\Khronos\\Vulkan\\Drivers"
Jon Ashburnffd5d672015-06-29 11:25:34 -0600234// TODO: Are these the correct paths
scygan8420b4c2015-06-01 19:47:08 +0200235#define DEFAULT_VK_DRIVERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn1b111de2015-07-06 15:40:35 -0600236#define DEFAULT_VK_LAYERS_INFO "SOFTWARE\\Khronos\\Vulkan\\ExplicitLayers;SOFTWARE\\Khronos\\Vulkan\\ImplicitLayers"
Jon Ashburn38144502015-07-07 15:06:25 -0600237#define DEFAULT_VK_LAYERS_PATH "C:\\Windows\\System32;C:\\Windows\\SysWow64"
Jon Ashburn68e2bef2015-08-06 11:22:33 -0600238#define LAYERS_PATH_ENV "VK_LAYER_PATH"
Ian Elliott665c5632015-02-04 11:22:39 -0700239
Courtney Goeltzenleuchterb5738ca2015-10-07 17:03:42 -0600240#define PRINTF_SIZE_T_SPECIFIER "%Iu"
241
Jon Ashburnffd5d672015-06-29 11:25:34 -0600242// File IO
Jon Ashburnee33ae72015-06-30 14:46:22 -0700243static bool loader_platform_file_exists(const char *path)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600244{
Jon Ashburnee33ae72015-06-30 14:46:22 -0700245 if ((_access(path, 0)) == -1)
Jon Ashburnffd5d672015-06-29 11:25:34 -0600246 return false;
247 else
248 return true;
249}
250
Cody Northrop62ac1c52015-07-08 16:48:37 -0600251static bool loader_platform_is_path_absolute(const char *path)
Jon Ashburn38144502015-07-07 15:06:25 -0600252{
253 return !PathIsRelative(path);
254}
255
256// WIN32 runtime doesn't have dirname().
257static inline char *loader_platform_dirname(char *path)
258{
259 char *current, *next;
260
261 // TODO/TBD: Do we need to deal with the Windows's ":" character?
262
263 for (current = path; *current != '\0'; current = next) {
264 next = strchr(current, DIRECTORY_SYMBOL);
265 if (next == NULL) {
266 if (current != path)
267 *(current - 1) = '\0';
268 return path;
269 } else {
270 // Point one character past the DIRECTORY_SYMBOL:
271 next++;
272 }
273 }
274 return path;
275}
276
277// WIN32 runtime doesn't have basename().
278// Microsoft also doesn't have basename(). Paths are different on Windows, and
279// so this is just a temporary solution in order to get us compiling, so that we
280// can test some scenarios, and develop the correct solution for Windows.
281 // TODO: Develop a better, permanent solution for Windows, to replace this
282 // temporary code:
283static char *loader_platform_basename(char *pathname)
284{
285 char *current, *next;
286
287// TODO/TBD: Do we need to deal with the Windows's ":" character?
288
289 for (current = pathname; *current != '\0'; current = next) {
290 next = strchr(current, DIRECTORY_SYMBOL);
291 if (next == NULL) {
292 // No more DIRECTORY_SYMBOL's so return p:
293 return current;
294 } else {
295 // Point one character past the DIRECTORY_SYMBOL:
296 next++;
297 }
298 }
299 // We shouldn't get to here, but this makes the compiler happy:
300 return current;
301}
302
Ian Elliott81ac44c2015-01-13 17:52:38 -0700303// Dynamic Loading:
304typedef HMODULE loader_platform_dl_handle;
305static loader_platform_dl_handle loader_platform_open_library(const char* libPath)
306{
307 return LoadLibrary(libPath);
308}
309static char * loader_platform_open_library_error(const char* libPath)
310{
311 static char errorMsg[120];
312 snprintf(errorMsg, 119, "Failed to open dynamic library \"%s\"", libPath);
313 return errorMsg;
314}
315static void loader_platform_close_library(loader_platform_dl_handle library)
316{
317 FreeLibrary(library);
318}
319static void * loader_platform_get_proc_address(loader_platform_dl_handle library,
320 const char *name)
321{
322 assert(library);
323 assert(name);
324 return GetProcAddress(library, name);
325}
326static char * loader_platform_get_proc_address_error(const char *name)
327{
328 static char errorMsg[120];
329 snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
330 return errorMsg;
331}
332
333// Threads:
334typedef HANDLE loader_platform_thread;
Jon Ashburn413d6582015-08-28 15:19:27 -0600335#define THREAD_LOCAL_DECL __declspec(thread)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700336#define LOADER_PLATFORM_THREAD_ONCE_DECLARATION(var) \
337 INIT_ONCE var = INIT_ONCE_STATIC_INIT;
Jon Ashburnfce93d92015-05-12 17:26:48 -0600338#define LOADER_PLATFORM_THREAD_ONCE_DEFINITION(var) \
339 INIT_ONCE var;
Piers Daniell886be472015-02-23 16:23:13 -0700340static BOOL CALLBACK InitFuncWrapper(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
341{
342 void (*func)(void) = (void (*)(void))Parameter;
343 func();
344 return TRUE;
345}
346
Ian Elliott81ac44c2015-01-13 17:52:38 -0700347static void loader_platform_thread_once(void *ctl, void (* func) (void))
348{
349 assert(func != NULL);
350 assert(ctl != NULL);
Piers Daniell886be472015-02-23 16:23:13 -0700351 InitOnceExecuteOnce((PINIT_ONCE) ctl, InitFuncWrapper, func, NULL);
Ian Elliott81ac44c2015-01-13 17:52:38 -0700352}
353
354// Thread IDs:
355typedef DWORD loader_platform_thread_id;
356static loader_platform_thread_id loader_platform_get_thread_id()
357{
358 return GetCurrentThreadId();
359}
360
361// Thread mutex:
362typedef CRITICAL_SECTION loader_platform_thread_mutex;
363static void loader_platform_thread_create_mutex(loader_platform_thread_mutex* pMutex)
364{
365 InitializeCriticalSection(pMutex);
366}
367static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex* pMutex)
368{
369 EnterCriticalSection(pMutex);
370}
371static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex* pMutex)
372{
373 LeaveCriticalSection(pMutex);
374}
375static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex* pMutex)
376{
377 DeleteCriticalSection(pMutex);
378}
Mike Stroyan33053d02015-05-15 17:34:51 -0600379typedef CONDITION_VARIABLE loader_platform_thread_cond;
380static void loader_platform_thread_init_cond(loader_platform_thread_cond* pCond)
381{
382 InitializeConditionVariable(pCond);
383}
384static void loader_platform_thread_cond_wait(loader_platform_thread_cond* pCond, loader_platform_thread_mutex* pMutex)
385{
386 SleepConditionVariableCS(pCond, pMutex, INFINITE);
387}
388static void loader_platform_thread_cond_broadcast(loader_platform_thread_cond* pCond)
389{
390 WakeAllConditionVariable(pCond);
391}
Ian Elliott81ac44c2015-01-13 17:52:38 -0700392
Ian Elliott76005132015-03-31 15:32:41 -0600393// Windows Registry:
394char *loader_get_registry_string(const HKEY hive,
395 const LPCTSTR sub_key,
396 const char *value);
397
Jon Ashburnf6620c92015-10-15 13:47:58 -0600398#define loader_stack_alloc(size) _alloca(size)
Ian Elliott81ac44c2015-01-13 17:52:38 -0700399#else // defined(_WIN32)
400
401#error The "loader_platform.h" file must be modified for this OS.
402
403// NOTE: In order to support another OS, an #elif needs to be added (above the
404// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
405// contents of this file must be created.
406
407// NOTE: Other OS-specific changes are also needed for this OS. Search for
408// files with "WIN32" in it, as a quick way to find files that must be changed.
409
410#endif // defined(_WIN32)
411