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(a)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)
--
2.23.0