Tested on MSVC 2017. This patches makes it viable to build standalone and debuggable .dlls of vkd3d.
This commit fixes various compatibility issues with MSVC 2017.
The only non-trivial change is the addition of a trivial pthread wrapper. This requires Windows Vista and up due to condition variable support being non-existent in XP.
Signed-off-by: Hans-Kristian Arntzen post@arntzen-software.no --- include/private/vkd3d_common.h | 18 ++- include/private/vkd3d_debug.h | 4 +- include/private/vkd3d_threads.h | 166 +++++++++++++++++++++++ libs/vkd3d-shader/spirv.c | 2 +- libs/vkd3d-shader/vkd3d_shader_private.h | 1 - libs/vkd3d/device.c | 2 +- libs/vkd3d/resource.c | 2 +- libs/vkd3d/state.c | 2 +- libs/vkd3d/utils.c | 4 +- libs/vkd3d/vkd3d_private.h | 17 +-- libs/vkd3d/vulkan_procs.h | 4 +- 11 files changed, 197 insertions(+), 25 deletions(-) create mode 100644 include/private/vkd3d_threads.h
diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h index 1ac8a63..fab0cd4 100644 --- a/include/private/vkd3d_common.h +++ b/include/private/vkd3d_common.h @@ -26,6 +26,10 @@ #include <limits.h> #include <stdbool.h>
+#ifdef _MSC_VER +#include <intrin.h> +#endif + #ifndef ARRAY_SIZE # define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) #endif @@ -51,7 +55,9 @@ static inline size_t align(size_t addr, size_t alignment)
static inline unsigned int vkd3d_popcount(unsigned int v) { -#ifdef HAVE_BUILTIN_POPCOUNT +#ifdef _MSC_VER + return __popcnt(v); +#elif defined(HAVE_BUILTIN_POPCOUNT) return __builtin_popcount(v); #else v -= (v >> 1) & 0x55555555; @@ -78,7 +84,11 @@ static inline bool vkd3d_bitmask_is_contiguous(unsigned int mask) /* Undefined for x == 0. */ static inline unsigned int vkd3d_log2i(unsigned int x) { -#ifdef HAVE_BUILTIN_CLZ +#ifdef _MSC_VER + unsigned long result; + _BitScanReverse(&result, x); + return (unsigned int)x; +#elif defined(HAVE_BUILTIN_CLZ) return __builtin_clz(x) ^ 0x1f; #else static const unsigned int l[] = @@ -152,8 +162,8 @@ static inline LONG InterlockedDecrement(LONG volatile *x)
#if HAVE_SYNC_ADD_AND_FETCH # define atomic_add_fetch(ptr, val) __sync_add_and_fetch(ptr, val) -#else -# error "atomic_add_fetch() not implemented for this platform" +#elif defined(_MSC_VER) +# define atomic_add_fetch(ptr, val) InterlockedAdd(ptr, val) #endif /* HAVE_SYNC_ADD_AND_FETCH */
static inline void vkd3d_parse_version(const char *version, int *major, int *minor) diff --git a/include/private/vkd3d_debug.h b/include/private/vkd3d_debug.h index 1a44cb9..c37c841 100644 --- a/include/private/vkd3d_debug.h +++ b/include/private/vkd3d_debug.h @@ -67,8 +67,8 @@ const char *debugstr_w(const WCHAR *wstr, size_t wchar_size) DECLSPEC_HIDDEN; vkd3d_dbg_next_time = true; \ VKD3D_DBG_PRINTF
-#define VKD3D_DBG_PRINTF(args...) \ - vkd3d_dbg_printf(vkd3d_dbg_level, __FUNCTION__, args); } while (0) +#define VKD3D_DBG_PRINTF(...) \ + vkd3d_dbg_printf(vkd3d_dbg_level, __FUNCTION__, __VA_ARGS__); } while (0)
#ifndef TRACE #define TRACE VKD3D_DBG_LOG(TRACE) diff --git a/include/private/vkd3d_threads.h b/include/private/vkd3d_threads.h new file mode 100644 index 0000000..b613b50 --- /dev/null +++ b/include/private/vkd3d_threads.h @@ -0,0 +1,166 @@ +/* + * 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" + +#if defined(HAVE_PTHREAD_H) +#include <pthread.h> + +#elif defined(_WIN32) /* HAVE_PTHREAD_H */ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +typedef struct pthread +{ + HANDLE thread; + DWORD id; +} pthread_t; + +typedef struct pthread_mutex +{ + CRITICAL_SECTION *lock; +} pthread_mutex_t; + +typedef struct pthread_cond +{ + CONDITION_VARIABLE *cond; +} pthread_cond_t; + +struct vkd3d_pthread_wrapper_struct +{ + void * (*routine)(void *); + void *arg; +}; + +static DWORD WINAPI win32_thread_wrapper_routine(struct vkd3d_pthread_wrapper_struct *wrapper) +{ + struct vkd3d_pthread_wrapper_struct tmp = *wrapper; + vkd3d_free(wrapper); + tmp.routine(tmp.arg); + return 0; +} + +static inline int pthread_create(pthread_t *thread, void *attr, void * (*thread_fun)(void *), void *arg) +{ + (void)attr; + struct vkd3d_pthread_wrapper_struct *wrapper = vkd3d_malloc(sizeof(*wrapper)); + if (!wrapper) + return -1; + wrapper->routine = thread_fun; + wrapper->arg = arg; + thread->thread = CreateThread(NULL, 0, win32_thread_wrapper_routine, wrapper, 0, &thread->id); + if (!thread->thread) + { + vkd3d_free(wrapper); + return -1; + } + return 0; +} + +static inline int pthread_join(pthread_t thread, void **ret) +{ + (void)ret; + int success = WaitForSingleObject(thread.thread, INFINITE) == WAIT_OBJECT_0; + CloseHandle(thread.thread); + return success ? 0 : -1; +} + +static inline int pthread_mutex_init(pthread_mutex_t *lock, void *attr) +{ + (void)attr; + lock->lock = vkd3d_malloc(sizeof(CRITICAL_SECTION)); + if (!lock->lock) + return -1; + 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); + vkd3d_free(lock->lock); + return 0; +} + +static inline int pthread_cond_init(pthread_cond_t *cond, void *attr) +{ + (void)attr; + cond->cond = vkd3d_malloc(sizeof(CONDITION_VARIABLE)); + if (!cond->cond) + return -1; + InitializeConditionVariable(cond->cond); + return 0; +} + +static inline void pthread_cond_destroy(pthread_cond_t *cond) +{ + vkd3d_free(cond->cond); +} + +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-shader/spirv.c b/libs/vkd3d-shader/spirv.c index fe8935c..580230f 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -4540,7 +4540,7 @@ static void vkd3d_dxbc_compiler_emit_store_shader_output(struct vkd3d_dxbc_compi
static void vkd3d_dxbc_compiler_emit_shader_epilogue_function(struct vkd3d_dxbc_compiler *compiler) { - uint32_t param_type_id[MAX_REG_OUTPUT + 1], param_id[MAX_REG_OUTPUT + 1] = {}; + uint32_t param_type_id[MAX_REG_OUTPUT + 1], param_id[MAX_REG_OUTPUT + 1] = {0}; uint32_t void_id, type_id, ptr_type_id, function_type_id, function_id; struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; const struct vkd3d_shader_signature *signature; diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index 47764e5..940cb76 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -56,7 +56,6 @@ #include <limits.h> #include <stdbool.h> #include <string.h> -#include <strings.h>
#define VKD3D_VEC4_SIZE 4
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 3da4273..460bdf9 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/resource.c b/libs/vkd3d/resource.c index aebe1fa..88f184d 100644 --- a/libs/vkd3d/resource.c +++ b/libs/vkd3d/resource.c @@ -1388,7 +1388,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_resource_ReadFromSubresource(ID3D12Resour size = (box.right - box.left) / format->block_width * format->byte_count * format->block_byte_count; for (z = box.front; z < box.back; ++z) { - dst = dst_data + (z - box.front) * dst_slice_pitch; + dst = (uint8_t *)dst_data + (z - box.front) * dst_slice_pitch; src = src_data + z * vk_layout.depthPitch + box.top / format->block_height * vk_layout.rowPitch; for (y = box.top; y < box.bottom; y += format->block_height) { diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c index 12a711b..9dc5cff 100644 --- a/libs/vkd3d/state.c +++ b/libs/vkd3d/state.c @@ -1342,7 +1342,7 @@ static HRESULT create_shader_stage(struct d3d12_device *device, struct vkd3d_shader_code dxbc = {code->pShaderBytecode, code->BytecodeLength}; const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs; struct VkShaderModuleCreateInfo shader_desc; - struct vkd3d_shader_code spirv = {}; + struct vkd3d_shader_code spirv = {0}; VkResult vr; int ret;
diff --git a/libs/vkd3d/utils.c b/libs/vkd3d/utils.c index 6a910a7..624b14f 100644 --- a/libs/vkd3d/utils.c +++ b/libs/vkd3d/utils.c @@ -804,7 +804,7 @@ HRESULT vkd3d_load_vk_device_procs(struct vkd3d_vk_device_procs *procs, return S_OK; }
-#ifdef _GNU_SOURCE +#if defined(_GNU_SOURCE) && !defined(_WIN32)
bool vkd3d_get_program_name(char program_name[PATH_MAX]) { @@ -840,7 +840,7 @@ bool vkd3d_get_program_name(char program_name[PATH_MAX])
#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 59f0eac..a51ca4d 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) @@ -1231,16 +1231,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 PATH_MAX +#define VKD3D_PATH_MAX PATH_MAX +#else +#define VKD3D_PATH_MAX 256 #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; diff --git a/libs/vkd3d/vulkan_procs.h b/libs/vkd3d/vulkan_procs.h index 702cfd2..ec29eb4 100644 --- a/libs/vkd3d/vulkan_procs.h +++ b/libs/vkd3d/vulkan_procs.h @@ -178,8 +178,8 @@ VK_DEVICE_PFN(vkUpdateDescriptorSets) VK_DEVICE_PFN(vkWaitForFences)
/* VK_KHR_draw_indirect_count */ -VK_DEVICE_EXT_PFN(vkCmdDrawIndirectCountKHR); -VK_DEVICE_EXT_PFN(vkCmdDrawIndexedIndirectCountKHR); +VK_DEVICE_EXT_PFN(vkCmdDrawIndirectCountKHR) +VK_DEVICE_EXT_PFN(vkCmdDrawIndexedIndirectCountKHR)
/* VK_KHR_get_memory_requirements2 */ VK_DEVICE_EXT_PFN(vkGetBufferMemoryRequirements2KHR)