Signed-off-by: Hans-Kristian Arntzen post@arntzen-software.no --- include/private/vkd3d_threads.h | 167 ++++++++++++++++++++++++++++++++ libs/vkd3d/device.c | 2 +- libs/vkd3d/utils.c | 8 +- libs/vkd3d/vkd3d_private.h | 17 ++-- 4 files changed, 179 insertions(+), 15 deletions(-) create mode 100644 include/private/vkd3d_threads.h
diff --git a/include/private/vkd3d_threads.h b/include/private/vkd3d_threads.h new file mode 100644 index 0000000..736bf6e --- /dev/null +++ b/include/private/vkd3d_threads.h @@ -0,0 +1,167 @@ +/* + * Copyright 2019 Hans-Kristian Arntzen for Valve + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __VKD3D_THREADS_H +#define __VKD3D_THREADS_H + +#include "config.h" +#include "vkd3d_memory.h" + +#if defined(HAVE_PTHREAD_H) +#include <pthread.h> + +#elif defined(_WIN32) /* HAVE_PTHREAD_H */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +/* pthread_t is passed by value in some functions, + * which implies we need pthread_t to be a pointer type here. */ +struct pthread +{ + HANDLE thread; + DWORD id; + void * (*routine)(void *); + void *arg; +}; +typedef struct pthread *pthread_t; + +/* pthread_mutex_t is not copyable, so embed CS inline. */ +typedef struct pthread_mutex +{ + CRITICAL_SECTION lock; +} pthread_mutex_t; + +/* pthread_cond_t is not copyable, so embed CV inline. */ +typedef struct pthread_cond +{ + CONDITION_VARIABLE cond; +} pthread_cond_t; + +static DWORD WINAPI win32_thread_wrapper_routine(void *arg) +{ + pthread_t thread = arg; + thread->routine(thread->arg); + return 0; +} + +static inline int pthread_create(pthread_t *out_thread, void *attr, void * (*thread_fun)(void *), void *arg) +{ + pthread_t thread = vkd3d_calloc(1, sizeof(*thread)); + if (!thread) + return -1; + + (void)attr; + thread->routine = thread_fun; + thread->arg = arg; + thread->thread = CreateThread(NULL, 0, win32_thread_wrapper_routine, thread, 0, &thread->id); + if (!thread->thread) + { + vkd3d_free(thread); + return -1; + } + *out_thread = thread; + return 0; +} + +static inline int pthread_join(pthread_t thread, void **ret) +{ + (void)ret; + int success = WaitForSingleObject(thread->thread, INFINITE) == WAIT_OBJECT_0; + if (success) + { + CloseHandle(thread->thread); + vkd3d_free(thread); + } + return success ? 0 : -1; +} + +static inline int pthread_mutex_init(pthread_mutex_t *lock, void *attr) +{ + (void)attr; + InitializeCriticalSection(&lock->lock); + return 0; +} + +static inline int pthread_mutex_lock(pthread_mutex_t *lock) +{ + EnterCriticalSection(&lock->lock); + return 0; +} + +static inline int pthread_mutex_unlock(pthread_mutex_t *lock) +{ + LeaveCriticalSection(&lock->lock); + return 0; +} + +static inline int pthread_mutex_destroy(pthread_mutex_t *lock) +{ + DeleteCriticalSection(&lock->lock); + return 0; +} + +static inline int pthread_cond_init(pthread_cond_t *cond, void *attr) +{ + (void)attr; + InitializeConditionVariable(&cond->cond); + return 0; +} + +static inline int pthread_cond_destroy(pthread_cond_t *cond) +{ + (void)cond; + return 0; +} + +static inline int pthread_cond_signal(pthread_cond_t *cond) +{ + WakeConditionVariable(&cond->cond); + return 0; +} + +static inline int pthread_cond_broadcast(pthread_cond_t *cond) +{ + WakeAllConditionVariable(&cond->cond); + return 0; +} + +static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *lock) +{ + BOOL ret = SleepConditionVariableCS(&cond->cond, &lock->lock, INFINITE); + return ret ? 0 : -1; +} + +#else /* HAVE_PTHREAD_H */ +#error "Threads are not supported. Cannot build." +#endif /* HAVE_PTHREAD_H */ + +static inline void vkd3d_set_thread_name(const char *name) +{ +#if defined(_MSC_VER) + (void)name; +#elif defined(HAVE_PTHREAD_SETNAME_NP_2) + pthread_setname_np(pthread_self(), name); +#elif defined(HAVE_PTHREAD_SETNAME_NP_1) + pthread_setname_np(name); +#else + (void)name; +#endif +} + +#endif /* __VKD3D_THREADS_H */ diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 0624318..cc8e282 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -453,7 +453,7 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance, bool *user_extension_supported = NULL; VkApplicationInfo application_info; VkInstanceCreateInfo instance_info; - char application_name[PATH_MAX]; + char application_name[VKD3D_PATH_MAX]; uint32_t extension_count; const char **extensions; VkInstance vk_instance; diff --git a/libs/vkd3d/utils.c b/libs/vkd3d/utils.c index cf0448d..64eb845 100644 --- a/libs/vkd3d/utils.c +++ b/libs/vkd3d/utils.c @@ -830,7 +830,7 @@ HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs,
#if HAVE_DECL_PROGRAM_INVOCATION_NAME
-bool vkd3d_get_program_name(char program_name[PATH_MAX]) +bool vkd3d_get_program_name(char program_name[VKD3D_PATH_MAX]) { char *name, *p, *real_path = NULL;
@@ -856,15 +856,15 @@ bool vkd3d_get_program_name(char program_name[PATH_MAX]) name = program_invocation_name; }
- strncpy(program_name, name, PATH_MAX); - program_name[PATH_MAX - 1] = '\0'; + strncpy(program_name, name, VKD3D_PATH_MAX); + program_name[VKD3D_PATH_MAX - 1] = '\0'; free(real_path); return true; }
#else
-bool vkd3d_get_program_name(char program_name[PATH_MAX]) +bool vkd3d_get_program_name(char program_name[VKD3D_PATH_MAX]) { *program_name = '\0'; return false; diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 84b5ff2..76ce709 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -31,11 +31,11 @@
#include "vkd3d.h" #include "vkd3d_shader.h" +#include "vkd3d_threads.h"
#include <assert.h> #include <inttypes.h> #include <limits.h> -#include <pthread.h> #include <stdbool.h>
#define VK_CALL(f) (vk_procs->f) @@ -1271,16 +1271,13 @@ HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs,
extern const char vkd3d_build[];
-bool vkd3d_get_program_name(char program_name[PATH_MAX]) DECLSPEC_HIDDEN; - -static inline void vkd3d_set_thread_name(const char *name) -{ -#if defined(HAVE_PTHREAD_SETNAME_NP_2) - pthread_setname_np(pthread_self(), name); -#elif defined(HAVE_PTHREAD_SETNAME_NP_1) - pthread_setname_np(name); +#ifdef _WIN32 +/* This value isn't really used for anything useful on Windows, just need some kind of value. */ +#define VKD3D_PATH_MAX _MAX_PATH +#else +#define VKD3D_PATH_MAX PATH_MAX #endif -} +bool vkd3d_get_program_name(char program_name[VKD3D_PATH_MAX]) DECLSPEC_HIDDEN;
VkResult vkd3d_set_vk_object_name_utf8(struct d3d12_device *device, uint64_t vk_object, VkDebugReportObjectTypeEXT vk_object_type, const char *name) DECLSPEC_HIDDEN;