[PATCH 1/6] vkd3d: Enable MSVC to compile.

Hans-Kristian Arntzen post at arntzen-software.no
Mon Sep 30 09:16:36 CDT 2019


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 at 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




More information about the wine-devel mailing list