From 6c2c5be150279877adb61e54394ba98db7fd4f76 Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Wed, 24 Nov 2021 18:39:03 +0100
Subject: [PATCH 1/3] dzn: Get an ID3D12Device1 object

We need SetEventOnMultipleFenceCompletion() to implement
vk_sync.wait_many(), and this method is part of the ID3D12Device1
interface.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 src/microsoft/vulkan/dzn_device.cpp | 2 +-
 src/microsoft/vulkan/dzn_private.h  | 8 ++++----
 src/microsoft/vulkan/dzn_util.cpp   | 4 ++--
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/microsoft/vulkan/dzn_device.cpp b/src/microsoft/vulkan/dzn_device.cpp
index baa327f8515d6..8323309958a4d 100644
--- a/src/microsoft/vulkan/dzn_device.cpp
+++ b/src/microsoft/vulkan/dzn_device.cpp
@@ -364,7 +364,7 @@ dzn_physical_device::get_max_array_layers()
    return get_max_extent(false);
 }
 
-ID3D12Device *
+ID3D12Device1 *
 dzn_physical_device::get_d3d12_dev()
 {
    std::lock_guard<std::mutex> lock(dev_lock);
diff --git a/src/microsoft/vulkan/dzn_private.h b/src/microsoft/vulkan/dzn_private.h
index 30939812620b3..8fb444102faf8 100644
--- a/src/microsoft/vulkan/dzn_private.h
+++ b/src/microsoft/vulkan/dzn_private.h
@@ -356,7 +356,7 @@ struct dzn_physical_device {
                        const VkAllocationCallbacks *alloc);
    ~dzn_physical_device();
    const VkAllocationCallbacks *get_vk_allocator();
-   ID3D12Device *get_d3d12_dev();
+   ID3D12Device1 *get_d3d12_dev();
 
    const D3D12_FEATURE_DATA_ARCHITECTURE1 &get_arch_caps() const;
    const VkPhysicalDeviceMemoryProperties &get_memory() const;
@@ -383,7 +383,7 @@ private:
    uint32_t get_max_extent(bool is_3d);
 
    std::mutex dev_lock;
-   ComPtr<ID3D12Device> dev;
+   ComPtr<ID3D12Device1> dev;
    D3D_FEATURE_LEVEL feature_level = (D3D_FEATURE_LEVEL)0;
    D3D12_FEATURE_DATA_ARCHITECTURE1 architecture = {};
    D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
@@ -415,7 +415,7 @@ d3d12_enable_debug_layer();
 void
 d3d12_enable_gpu_validation();
 
-ComPtr<ID3D12Device>
+ComPtr<ID3D12Device1>
 d3d12_create_device(IUnknown *adapter, bool experimental_features);
 
 struct dzn_queue {
@@ -444,7 +444,7 @@ struct dzn_device {
    struct vk_device_extension_table enabled_extensions;
    struct vk_device_dispatch_table dispatch;
 
-   ID3D12Device *dev;
+   ID3D12Device1 *dev;
 
    dzn_object_unique_ptr<dzn_meta_indirect_draw> indirect_draws[DZN_NUM_INDIRECT_DRAW_TYPES];
    dzn_object_unique_ptr<dzn_meta_triangle_fan_rewrite_index> triangle_fan[dzn_meta_triangle_fan_rewrite_index::NUM_INDEX_TYPE];
diff --git a/src/microsoft/vulkan/dzn_util.cpp b/src/microsoft/vulkan/dzn_util.cpp
index bf8d72e1b7160..921747340d5f4 100644
--- a/src/microsoft/vulkan/dzn_util.cpp
+++ b/src/microsoft/vulkan/dzn_util.cpp
@@ -112,7 +112,7 @@ d3d12_enable_gpu_validation()
       debug3->SetEnableGPUBasedValidation(true);
 }
 
-ComPtr<ID3D12Device>
+ComPtr<ID3D12Device1>
 d3d12_create_device(IUnknown *adapter, bool experimental_features)
 {
    typedef HRESULT(WINAPI *PFN_D3D12CREATEDEVICE)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);
@@ -143,7 +143,7 @@ d3d12_create_device(IUnknown *adapter, bool experimental_features)
       return NULL;
    }
 
-   ComPtr<ID3D12Device> dev;
+   ComPtr<ID3D12Device1> dev;
    if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
                  IID_PPV_ARGS(&dev))))
       return dev;
-- 
GitLab


From 5a086d788b86a5013e53229bc6c57d9087d29e55 Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Wed, 24 Nov 2021 18:42:14 +0100
Subject: [PATCH 2/3] dzn: Implement a dzn_sync class to transition to the
 common sync/queue infra

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 src/microsoft/vulkan/dzn_private.h |  25 +++
 src/microsoft/vulkan/dzn_sync.cpp  | 280 +++++++++++++++++++++++++++++
 src/microsoft/vulkan/meson.build   |   1 +
 3 files changed, 306 insertions(+)
 create mode 100644 src/microsoft/vulkan/dzn_sync.cpp

diff --git a/src/microsoft/vulkan/dzn_private.h b/src/microsoft/vulkan/dzn_private.h
index 8fb444102faf8..60574bf0b3875 100644
--- a/src/microsoft/vulkan/dzn_private.h
+++ b/src/microsoft/vulkan/dzn_private.h
@@ -30,6 +30,7 @@
 #include "vk_image.h"
 #include "vk_log.h"
 #include "vk_physical_device.h"
+#include "vk_sync.h"
 #include "vk_queue.h"
 #include "vk_shader_module.h"
 #include "wsi_common.h"
@@ -1576,6 +1577,30 @@ struct dzn_event {
    ~dzn_event();
 };
 
+struct dzn_sync {
+   dzn_sync(dzn_device *device, uint64_t initial_value);
+   ~dzn_sync() = default;
+
+   VkResult signal(uint64_t value);
+   uint64_t get_value();
+   VkResult move(dzn_device *device, dzn_sync *dst);
+   ID3D12Fence *get_fence();
+
+   static VkResult wait(dzn_device *device,
+                        uint32_t wait_count,
+                        const struct vk_sync_wait *waits,
+                        enum vk_sync_wait_flags wait_flags,
+                        uint64_t abs_timeout_ns);
+
+   static dzn_sync *to_dzn_sync(const struct vk_sync *sync);
+   static const struct vk_sync_type *get_type();
+
+   struct vk_sync vk;
+
+private:
+   ComPtr<ID3D12Fence> fence;
+};
+
 struct dzn_query_pool {
    struct query {
       enum status {
diff --git a/src/microsoft/vulkan/dzn_sync.cpp b/src/microsoft/vulkan/dzn_sync.cpp
new file mode 100644
index 0000000000000..0d63e39c910e6
--- /dev/null
+++ b/src/microsoft/vulkan/dzn_sync.cpp
@@ -0,0 +1,280 @@
+/*
+ * Copyright © Microsoft Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "dzn_private.h"
+
+#include "vk_alloc.h"
+#include "vk_debug_report.h"
+#include "vk_util.h"
+
+#include "util/macros.h"
+#include "util/os_time.h"
+
+static VkResult
+dzn_sync_init(struct vk_device *device,
+              struct vk_sync *sync,
+              uint64_t initial_value)
+{
+   dzn_sync *dsync = container_of(sync, dzn_sync, vk);
+   dzn_device *ddev = container_of(device, dzn_device, vk);
+
+   assert((void *)dsync == (void *)sync);
+
+   try {
+      std::construct_at(dsync, ddev, initial_value);
+   } catch (VkResult error) {
+      return error;
+   }
+
+   return VK_SUCCESS;
+}
+
+static void
+dzn_sync_finish(struct vk_device *device,
+                struct vk_sync *sync)
+{
+   dzn_sync *dsync = container_of(sync, dzn_sync, vk);
+
+   std::destroy_at(dsync);
+}
+
+static VkResult
+dzn_sync_signal(struct vk_device *device,
+                struct vk_sync *sync,
+                uint64_t value)
+{
+   dzn_sync *dsync = container_of(sync, dzn_sync, vk);
+
+   if (!(sync->flags & VK_SYNC_IS_TIMELINE))
+      value = 1;
+
+   return dsync->signal(value);
+}
+
+static VkResult
+dzn_sync_get_value(struct vk_device *device,
+                   struct vk_sync *sync,
+                   uint64_t *value)
+{
+   dzn_sync *dsync = container_of(sync, dzn_sync, vk);
+
+   *value = dsync->get_value();
+   return VK_SUCCESS;
+}
+
+static VkResult
+dzn_sync_reset(struct vk_device *device,
+               struct vk_sync *sync)
+{
+   dzn_sync *dsync = container_of(sync, dzn_sync, vk);
+
+   dsync->signal(0);
+   return VK_SUCCESS;
+}
+
+static VkResult
+dzn_sync_move(struct vk_device *device,
+              struct vk_sync *dst,
+              struct vk_sync *src)
+{
+   dzn_device *ddev = container_of(device, dzn_device, vk);
+   dzn_sync *ddst = container_of(dst, dzn_sync, vk);
+   dzn_sync *dsrc = container_of(src, dzn_sync, vk);
+
+   return dsrc->move(ddev, ddst);
+}
+
+static VkResult
+dzn_sync_wait(struct vk_device *device,
+              uint32_t wait_count,
+              const struct vk_sync_wait *waits,
+              enum vk_sync_wait_flags wait_flags,
+              uint64_t abs_timeout_ns)
+{
+   dzn_device *ddev = container_of(device, dzn_device, vk);
+
+   return dzn_sync::wait(ddev, wait_count, waits, wait_flags, abs_timeout_ns);
+}
+
+const struct vk_sync_type dzn_sync_type = {
+   .size = sizeof(dzn_sync),
+   .features = (enum vk_sync_features)
+      (VK_SYNC_FEATURE_BINARY |
+       VK_SYNC_FEATURE_TIMELINE |
+       VK_SYNC_FEATURE_GPU_WAIT |
+       VK_SYNC_FEATURE_GPU_MULTI_WAIT |
+       VK_SYNC_FEATURE_CPU_WAIT |
+       VK_SYNC_FEATURE_CPU_RESET |
+       VK_SYNC_FEATURE_CPU_SIGNAL |
+       VK_SYNC_FEATURE_WAIT_ANY |
+       VK_SYNC_FEATURE_WAIT_BEFORE_SIGNAL),
+
+   .init = dzn_sync_init,
+   .finish = dzn_sync_finish,
+   .signal = dzn_sync_signal,
+   .get_value = dzn_sync_get_value,
+   .reset = dzn_sync_reset,
+   .move = dzn_sync_move,
+   .wait_many = dzn_sync_wait,
+};
+
+dzn_sync::dzn_sync(dzn_device *device, uint64_t initial_value)
+{
+   assert(!(vk.flags & VK_SYNC_IS_SHAREABLE));
+
+   HRESULT hres =
+      device->dev->CreateFence(initial_value, D3D12_FENCE_FLAG_NONE,
+                               IID_PPV_ARGS(&fence));
+
+   if (FAILED(hres))
+      throw vk_error(device, VK_ERROR_UNKNOWN);
+
+}
+
+VkResult
+dzn_sync::signal(uint64_t value)
+{
+   HRESULT hres = fence->Signal(value);
+   if (FAILED(hres))
+      return VK_ERROR_UNKNOWN;
+
+   return VK_SUCCESS;
+}
+
+uint64_t
+dzn_sync::get_value()
+{
+   return fence->GetCompletedValue();
+}
+
+VkResult
+dzn_sync::move(dzn_device *device, dzn_sync *dst)
+{
+   ComPtr<ID3D12Fence> new_fence;
+
+   HRESULT hres =
+      device->dev->CreateFence(0, D3D12_FENCE_FLAG_NONE,
+                               IID_PPV_ARGS(&new_fence));
+   if (FAILED(hres))
+      return VK_ERROR_UNKNOWN;
+
+   dst->fence = fence;
+   fence = new_fence;
+   return VK_SUCCESS;
+}
+
+VkResult
+dzn_sync::wait(dzn_device *device,
+               uint32_t wait_count,
+               const struct vk_sync_wait *waits,
+               enum vk_sync_wait_flags wait_flags,
+               uint64_t abs_timeout_ns)
+{
+   struct {
+      dzn_transient_object<ID3D12Fence *> fences;
+      dzn_transient_object<uint64_t> values;
+   } heap_waits;
+
+   struct {
+      ID3D12Fence *fences[STACK_ARRAY_SIZE];
+      uint64_t values[STACK_ARRAY_SIZE];
+   } stack_waits;
+
+   ID3D12Fence **fences;
+   uint64_t *values;
+
+   if (wait_count > STACK_ARRAY_SIZE) {
+      heap_waits.fences = dzn_transient_alloc<ID3D12Fence *>(wait_count, &device->vk.alloc);
+      heap_waits.values = dzn_transient_alloc<uint64_t>(wait_count, &device->vk.alloc);
+      fences = heap_waits.fences.get();
+      values = heap_waits.values.get();
+   } else {
+      fences = stack_waits.fences;
+      values = stack_waits.values;
+   }
+
+   for (uint32_t i = 0; i < wait_count; i++) {
+      dzn_sync *sync = container_of(waits[i].sync, dzn_sync, vk);
+
+      fences[i] = sync->fence.Get();
+      values[i] = (sync->vk.flags & VK_SYNC_IS_TIMELINE) ? waits[i].wait_value : 1;
+   }
+
+   HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
+   if (event == NULL)
+      throw VK_ERROR_UNKNOWN;
+
+   D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags =
+      (wait_flags & VK_SYNC_WAIT_ANY) ?
+      D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY :
+      D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL;
+
+   device->dev->SetEventOnMultipleFenceCompletion(fences, values,
+                                                  wait_count, flags,
+                                                  event);
+
+   DWORD timeout_ms;
+
+   if (abs_timeout_ns == OS_TIMEOUT_INFINITE) {
+      timeout_ms = INFINITE;
+   } else {
+      uint64_t cur_time = os_time_get_nano();
+      uint64_t rel_timeout_ns =
+         abs_timeout_ns > cur_time ? abs_timeout_ns - cur_time : 0;
+
+      timeout_ms = (rel_timeout_ns / 1000000) + (rel_timeout_ns % 1000000 ? 1 : 0);
+   }
+
+   DWORD res =
+      WaitForSingleObject(event, timeout_ms);
+
+   CloseHandle(event);
+
+   if (res == WAIT_TIMEOUT)
+      return VK_TIMEOUT;
+   else if (res != WAIT_OBJECT_0)
+      return VK_ERROR_UNKNOWN;
+
+   return VK_SUCCESS;
+}
+
+ID3D12Fence *
+dzn_sync::get_fence()
+{
+   return fence.Get();
+}
+
+dzn_sync *
+dzn_sync::to_dzn_sync(const struct vk_sync *sync)
+{
+   if (sync->type != &dzn_sync_type)
+      return NULL;
+
+   return container_of(sync, dzn_sync, vk);
+}
+
+const struct vk_sync_type *
+dzn_sync::get_type()
+{
+   return &dzn_sync_type;
+}
diff --git a/src/microsoft/vulkan/meson.build b/src/microsoft/vulkan/meson.build
index a55aa6cc7df59..a50a06a9a4a67 100644
--- a/src/microsoft/vulkan/meson.build
+++ b/src/microsoft/vulkan/meson.build
@@ -94,6 +94,7 @@ libdzn_files = files(
   'dzn_query.cpp',
   'dzn_semaphore.cpp',
   'dzn_state.cpp',
+  'dzn_sync.cpp',
   'dzn_util.cpp',
   'dzn_util.c',
   'dzn_wsi.cpp',
-- 
GitLab


From 0a2b3821cbced07a5fe9215573908e8f2b678f5a Mon Sep 17 00:00:00 2001
From: Boris Brezillon <boris.brezillon@collabora.com>
Date: Wed, 24 Nov 2021 18:44:40 +0100
Subject: [PATCH 3/3] dzn: Get rid of the custom semaphore/fence implementation

And transition to the generic queue_submit() infrastructure.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
---
 src/microsoft/vulkan/dzn_device.cpp    | 200 +++++++++++++++----------
 src/microsoft/vulkan/dzn_fence.cpp     | 126 ----------------
 src/microsoft/vulkan/dzn_private.h     |  39 ++---
 src/microsoft/vulkan/dzn_semaphore.cpp |  61 --------
 src/microsoft/vulkan/meson.build       |   2 -
 5 files changed, 136 insertions(+), 292 deletions(-)
 delete mode 100644 src/microsoft/vulkan/dzn_fence.cpp
 delete mode 100644 src/microsoft/vulkan/dzn_semaphore.cpp

diff --git a/src/microsoft/vulkan/dzn_device.cpp b/src/microsoft/vulkan/dzn_device.cpp
index 8323309958a4d..e7dedff570b4e 100644
--- a/src/microsoft/vulkan/dzn_device.cpp
+++ b/src/microsoft/vulkan/dzn_device.cpp
@@ -195,6 +195,12 @@ dzn_physical_device::dzn_physical_device(dzn_instance *inst,
    }
 
    get_device_extensions();
+
+   uint32_t num_sync_types = 0;
+   sync_types[num_sync_types++] = dzn_sync::get_type();
+   sync_types[num_sync_types] = NULL;
+   assert(num_sync_types <= MAX_SYNC_TYPES);
+   vk.supported_sync_types = sync_types;
 }
 
 dzn_physical_device::~dzn_physical_device()
@@ -1353,6 +1359,15 @@ dzn_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
    return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
 }
 
+static VkResult
+dzn_queue_submit(struct vk_queue *queue,
+                 struct vk_queue_submit *info)
+{
+   dzn_queue *dqueue = container_of(queue, dzn_queue, vk);
+
+   return dqueue->submit(info);
+}
+
 dzn_queue::dzn_queue(dzn_device *dev,
                      const VkDeviceQueueCreateInfo *pCreateInfo,
                      const VkAllocationCallbacks *alloc)
@@ -1361,6 +1376,7 @@ dzn_queue::dzn_queue(dzn_device *dev,
    if (result != VK_SUCCESS)
       throw result;
 
+   vk.driver_submit = dzn_queue_submit;
    device = dev;
 
    D3D12_COMMAND_QUEUE_DESC queue_desc = {
@@ -1390,6 +1406,114 @@ dzn_queue::get_vk_allocator()
    return &device->vk.alloc;
 }
 
+VkResult
+dzn_queue::sync_wait(const struct vk_sync_wait &wait)
+{
+   dzn_sync *sync = dzn_sync::to_dzn_sync(wait.sync);
+   assert(sync != NULL);
+
+   uint64_t value =
+      (sync->vk.flags & VK_SYNC_IS_TIMELINE) ? wait.wait_value : 1;
+
+   ID3D12Fence *sync_fence = sync->get_fence();
+   assert(sync_fence != NULL);
+
+   if (value > 0 && FAILED(cmdqueue->Wait(sync_fence, value)))
+      return vk_error(device, VK_ERROR_UNKNOWN);
+
+   return VK_SUCCESS;
+}
+
+VkResult
+dzn_queue::sync_signal(const struct vk_sync_signal &signal)
+{
+   dzn_sync *sync = dzn_sync::to_dzn_sync(signal.sync);
+   assert(sync != NULL);
+
+   uint64_t value =
+      (sync->vk.flags & VK_SYNC_IS_TIMELINE) ? signal.signal_value : 1;
+   assert(value > 0);
+
+   ID3D12Fence *sync_fence = sync->get_fence();
+   assert(sync_fence != NULL);
+   HRESULT hres;
+
+   hres = cmdqueue->Signal(sync_fence, value);
+   if (FAILED(hres))
+      return vk_error(device, VK_ERROR_UNKNOWN);
+
+   return VK_SUCCESS;
+}
+
+VkResult
+dzn_queue::submit(struct vk_queue_submit *info)
+{
+   VkResult result;
+
+   for (uint32_t i = 0; i < info->wait_count; i++) {
+      result = sync_wait(info->waits[i]);
+      if (result != VK_SUCCESS)
+         return result;
+   }
+
+   for (uint32_t i = 0; i < info->command_buffer_count; i++) {
+      dzn_cmd_buffer *cmd_buffer =
+         container_of(info->command_buffers[i], dzn_cmd_buffer, vk);
+
+      for (auto &batch : cmd_buffer->batches) {
+         ID3D12CommandList *cmdlists[] = { batch->cmdlist.Get() };
+
+         for (auto &event : batch->wait) {
+            if (FAILED(cmdqueue->Wait(event->fence.Get(), 1)))
+               return VK_ERROR_UNKNOWN;
+	 }
+
+         for (auto &qop : batch->queries) {
+            auto &query = qop.qpool->queries[qop.query];
+            ComPtr<ID3D12Fence> query_fence = query.fence;
+            uint64_t query_fence_val = query.fence_value.load();
+
+            if (qop.wait && query_fence.Get() && query_fence_val > 0) {
+               if (FAILED(cmdqueue->Wait(query_fence.Get(), query_fence_val)))
+                  return VK_ERROR_UNKNOWN;
+            }
+
+            if (qop.reset) {
+               query.fence = ComPtr<ID3D12Fence>(NULL);
+               query.fence_value = 0;
+            }
+         }
+
+         cmdqueue->ExecuteCommandLists(1, cmdlists);
+
+         for (auto &signal : batch->signal) {
+            if (FAILED(cmdqueue->Signal(signal.event->fence.Get(), signal.value ? 1 : 0)))
+               return VK_ERROR_UNKNOWN;
+         }
+
+         for (auto &qop : batch->queries) {
+            if (qop.signal) {
+               auto &query = qop.qpool->queries[qop.query];
+
+               query.fence = fence;
+               query.fence_value = fence_point + 1;
+            }
+         }
+      }
+   }
+
+   for (uint32_t i = 0; i < info->signal_count; i++) {
+      result = sync_signal(info->signals[i]);
+      if (result != VK_SUCCESS)
+         return result;
+   }
+
+   if (FAILED(cmdqueue->Signal(fence.Get(), ++fence_point)))
+      return VK_ERROR_UNKNOWN;
+
+   return VK_SUCCESS;
+}
+
 static VkResult
 check_physical_device_features(VkPhysicalDevice physicalDevice,
                                const VkPhysicalDeviceFeatures *features)
@@ -1688,82 +1812,6 @@ dzn_DeviceWaitIdle(VkDevice _device)
 #endif
 }
 
-VKAPI_ATTR VkResult VKAPI_CALL
-dzn_QueueWaitIdle(VkQueue _queue)
-{
-   VK_FROM_HANDLE(dzn_queue, queue, _queue);
-
-   if (FAILED(queue->fence->SetEventOnCompletion(queue->fence_point, NULL)))
-      return vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
-
-   return VK_SUCCESS;
-}
-
-VKAPI_ATTR VkResult VKAPI_CALL
-dzn_QueueSubmit(VkQueue _queue,
-                uint32_t submitCount,
-                const VkSubmitInfo *pSubmits,
-                VkFence _fence)
-{
-   VK_FROM_HANDLE(dzn_queue, queue, _queue);
-   VK_FROM_HANDLE(dzn_fence, fence, _fence);
-   struct dzn_device *device = queue->device;
-
-   /* TODO: execute an array of these instead of one at the time */
-   for (uint32_t i = 0; i < submitCount; i++) {
-      for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j++) {
-         VK_FROM_HANDLE(dzn_cmd_buffer, cmd_buffer,
-                         pSubmits[i].pCommandBuffers[j]);
-         assert(cmd_buffer->vk.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY);
-
-         for (auto &batch : cmd_buffer->batches) {
-            ID3D12CommandList *cmdlists[] = { batch->cmdlist.Get() };
-
-            for (auto &event : batch->wait)
-               queue->cmdqueue->Wait(event->fence.Get(), 1);
-
-            for (auto &qop : batch->queries) {
-               auto &query = qop.qpool->queries[qop.query];
-               ComPtr<ID3D12Fence> query_fence = query.fence;
-               uint64_t query_fence_val = query.fence_value.load();
-
-               if (qop.wait && query_fence.Get() && query_fence_val > 0)
-                  queue->cmdqueue->Wait(query_fence.Get(), query_fence_val);
-
-               if (qop.reset) {
-                  query.fence = ComPtr<ID3D12Fence>(NULL);
-                  query.fence_value = 0;
-               }
-            }
-
-            queue->cmdqueue->ExecuteCommandLists(1, cmdlists);
-
-            for (auto &signal : batch->signal)
-               queue->cmdqueue->Signal(signal.event->fence.Get(), signal.value ? 1 : 0);
-
-            for (auto &qop : batch->queries) {
-               if (qop.signal) {
-                  auto &query = qop.qpool->queries[qop.query];
-
-                  query.fence = queue->fence;
-                  query.fence_value = queue->fence_point + 1;
-               }
-            }
-         }
-      }
-   }
-
-   if (fence)
-      queue->cmdqueue->Signal(fence->fence.Get(), 1);
-
-   queue->cmdqueue->Signal(queue->fence.Get(), ++queue->fence_point);
-
-   if (queue->device->physical_device->instance->debug_flags & DZN_DEBUG_SYNC)
-      dzn_QueueWaitIdle(_queue);
-
-   return VK_SUCCESS;
-}
-
 dzn_device_memory::dzn_device_memory(dzn_device *device,
                                      const VkMemoryAllocateInfo *pAllocateInfo,
                                      const VkAllocationCallbacks *pAllocator)
diff --git a/src/microsoft/vulkan/dzn_fence.cpp b/src/microsoft/vulkan/dzn_fence.cpp
deleted file mode 100644
index d7b43ed0edbff..0000000000000
--- a/src/microsoft/vulkan/dzn_fence.cpp
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright © Microsoft Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "dzn_private.h"
-
-#include "vk_alloc.h"
-#include "vk_debug_report.h"
-#include "vk_util.h"
-
-#include "util/macros.h"
-
-dzn_fence::dzn_fence(dzn_device *device,
-                     const VkFenceCreateInfo *pCreateInfo,
-                     const VkAllocationCallbacks *pAllocator)
-{
-   BOOL initial_state =
-      pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT ? TRUE : FALSE;
-
-   /* I suspect that this approach is bunk, and we should instead create the actual
-    * fence object on the cmdqueue and just signal things on the dzn_fence object
-    * instead. But I don't know yet, so let's just leave it like this for now...
-    */
-   if (FAILED(device->dev->CreateFence(initial_state ? 1 : 0, D3D12_FENCE_FLAG_NONE,
-                                       IID_PPV_ARGS(&fence))))
-      throw vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
-
-   event = CreateEventA(NULL, TRUE, initial_state, NULL);
-   fence->SetEventOnCompletion(1, event);
-
-   vk_object_base_init(&device->vk, &base, VK_OBJECT_TYPE_FENCE);
-}
-
-dzn_fence::~dzn_fence()
-{
-   vk_object_base_finish(&base);
-   CloseHandle(event);
-}
-
-VKAPI_ATTR VkResult VKAPI_CALL
-dzn_CreateFence(VkDevice device,
-                const VkFenceCreateInfo *pCreateInfo,
-                const VkAllocationCallbacks *pAllocator,
-                VkFence *pFence)
-{
-   return dzn_fence_factory::create(device, pCreateInfo, pAllocator, pFence);
-}
-
-VKAPI_ATTR void VKAPI_CALL
-dzn_DestroyFence(VkDevice device,
-                 VkFence fence,
-                 const VkAllocationCallbacks *pAllocator)
-{
-   return dzn_fence_factory::destroy(device, fence, pAllocator);
-}
-
-VKAPI_ATTR VkResult VKAPI_CALL
-dzn_GetFenceStatus(VkDevice _device,
-                   VkFence _fence)
-{
-   VK_FROM_HANDLE(dzn_fence, fence, _fence);
-
-   if (fence->fence->GetCompletedValue() != 1)
-      return VK_NOT_READY;
-
-   return VK_SUCCESS;
-}
-
-VKAPI_ATTR VkResult VKAPI_CALL
-dzn_ResetFences(VkDevice _device,
-                uint32_t fenceCount,
-                const VkFence *pFences)
-{
-   VK_FROM_HANDLE(dzn_device, device, _device);
-
-   for (uint32_t i = 0; i < fenceCount; i++) {
-      VK_FROM_HANDLE(dzn_fence, fence, pFences[i]);
-      fence->fence->Signal(0);
-      ResetEvent(fence->event);
-      fence->fence->SetEventOnCompletion(1, fence->event);
-   }
-
-   return VK_SUCCESS;
-}
-
-VKAPI_ATTR VkResult VKAPI_CALL
-dzn_WaitForFences(VkDevice _device,
-                  uint32_t fenceCount,
-                  const VkFence *pFences,
-                  VkBool32 waitAll,
-                  uint64_t timeout)
-{
-   /* TODO: deal with more fences! */
-   assert(fenceCount < MAXIMUM_WAIT_OBJECTS);
-
-   HANDLE handles[MAXIMUM_WAIT_OBJECTS];
-   for (int i = 0; i < fenceCount; ++i) {
-      VK_FROM_HANDLE(dzn_fence, fence, pFences[i]);
-      handles[i] = fence->event;
-   }
-   HRESULT hr = WaitForMultipleObjects(fenceCount, handles, waitAll, timeout / 1000000);
-
-   if (hr == WAIT_TIMEOUT)
-      return VK_TIMEOUT;      
-
-   return VK_SUCCESS;
-}
diff --git a/src/microsoft/vulkan/dzn_private.h b/src/microsoft/vulkan/dzn_private.h
index 60574bf0b3875..f80592afb2ab4 100644
--- a/src/microsoft/vulkan/dzn_private.h
+++ b/src/microsoft/vulkan/dzn_private.h
@@ -334,6 +334,8 @@ struct dzn_meta_blits {
                       std::hash<uint64_t>, std::equal_to<uint64_t>, contexts_allocator> contexts;
 };
 
+#define MAX_SYNC_TYPES 1
+
 struct dzn_physical_device {
    struct vk_physical_device vk;
 
@@ -390,6 +392,7 @@ private:
    D3D12_FEATURE_DATA_D3D12_OPTIONS options = {};
    VkPhysicalDeviceMemoryProperties memory = {};
    D3D12_HEAP_FLAGS heap_flags_for_mem_type[VK_MAX_MEMORY_TYPES] = {};
+   const struct vk_sync_type *sync_types[MAX_SYNC_TYPES + 1];
 };
 
 #define dzn_debug_ignored_stype(sType) \
@@ -424,14 +427,21 @@ struct dzn_queue {
    struct dzn_device *device;
 
    ComPtr<ID3D12CommandQueue> cmdqueue;
-   ComPtr<ID3D12Fence> fence;
-   uint64_t fence_point = 0;
 
    dzn_queue(dzn_device *device,
              const VkDeviceQueueCreateInfo *pCreateInfo,
              const VkAllocationCallbacks *alloc);
    ~dzn_queue();
+
+   VkResult submit(struct vk_queue_submit *info);
+
    const VkAllocationCallbacks *get_vk_allocator();
+
+private:
+   VkResult sync_wait(const struct vk_sync_wait &wait);
+   VkResult sync_signal(const struct vk_sync_signal &signal);
+   ComPtr<ID3D12Fence> fence;
+   uint64_t fence_point = 0;
 };
 
 struct dzn_device {
@@ -1545,27 +1555,6 @@ private:
    dzn_object_vector<dzn_physical_device> physical_devices;
 };
 
-struct dzn_semaphore {
-   struct vk_object_base base;
-
-   dzn_semaphore(dzn_device *device,
-                 const VkSemaphoreCreateInfo *pCreateInfo,
-                 const VkAllocationCallbacks *pAllocator);
-   ~dzn_semaphore();
-};
-
-struct dzn_fence {
-   struct vk_object_base base;
-
-   ComPtr<ID3D12Fence> fence;
-   HANDLE event;
-
-   dzn_fence(dzn_device *device,
-             const VkFenceCreateInfo *pCreateInfo,
-             const VkAllocationCallbacks *pAllocator);
-   ~dzn_fence();
-};
-
 struct dzn_event {
    struct vk_object_base base;
 
@@ -1669,7 +1658,6 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_descriptor_pool, base, VkDescriptorPool, VK_O
 VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_descriptor_set, base, VkDescriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET)
 VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_descriptor_set_layout, base, VkDescriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT)
 VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_event, base, VkEvent, VK_OBJECT_TYPE_EVENT)
-VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_fence, base, VkFence, VK_OBJECT_TYPE_FENCE)
 VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_framebuffer, base, VkFramebuffer, VK_OBJECT_TYPE_FRAMEBUFFER)
 VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_image, vk.base, VkImage, VK_OBJECT_TYPE_IMAGE)
 VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_image_view, vk.base, VkImageView, VK_OBJECT_TYPE_IMAGE_VIEW)
@@ -1681,7 +1669,6 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_pipeline_layout, base, VkPipelineLayout, VK_O
 VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_query_pool, base, VkQueryPool, VK_OBJECT_TYPE_QUERY_POOL)
 VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_render_pass, base, VkRenderPass, VK_OBJECT_TYPE_RENDER_PASS)
 VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_sampler, base, VkSampler, VK_OBJECT_TYPE_SAMPLER)
-VK_DEFINE_NONDISP_HANDLE_CASTS(dzn_semaphore, base, VkSemaphore, VK_OBJECT_TYPE_SEMAPHORE)
 
 template <typename DT, typename VH, typename Conv, typename... CreateArgs>
 class dzn_object_factory {
@@ -1865,7 +1852,6 @@ DZN_OBJ_FACTORY(dzn_descriptor_set_layout, VkDescriptorSetLayout, VkDevice, cons
 DZN_OBJ_FACTORY(dzn_device, VkDevice, VkPhysicalDevice, const VkDeviceCreateInfo *);
 DZN_OBJ_FACTORY(dzn_device_memory, VkDeviceMemory, VkDevice, const VkMemoryAllocateInfo *);
 DZN_OBJ_FACTORY(dzn_event, VkEvent, VkDevice, const VkEventCreateInfo *);
-DZN_OBJ_FACTORY(dzn_fence, VkFence, VkDevice, const VkFenceCreateInfo *);
 DZN_OBJ_FACTORY(dzn_framebuffer, VkFramebuffer, VkDevice, const VkFramebufferCreateInfo *);
 DZN_OBJ_FACTORY(dzn_graphics_pipeline, VkPipeline, VkDevice, VkPipelineCache, const VkGraphicsPipelineCreateInfo *);
 DZN_OBJ_FACTORY(dzn_image, VkImage, VkDevice, const VkImageCreateInfo *);
@@ -1878,6 +1864,5 @@ DZN_OBJ_FACTORY(dzn_queue, VkQueue, VkDevice, const VkDeviceQueueCreateInfo *);
 DZN_OBJ_FACTORY(dzn_query_pool, VkQueryPool, VkDevice, const VkQueryPoolCreateInfo *);
 DZN_OBJ_FACTORY(dzn_render_pass, VkRenderPass, VkDevice, const VkRenderPassCreateInfo2KHR *);
 DZN_OBJ_FACTORY(dzn_sampler, VkSampler, VkDevice, const VkSamplerCreateInfo *);
-DZN_OBJ_FACTORY(dzn_semaphore, VkSemaphore, VkDevice, const VkSemaphoreCreateInfo *);
 
 #endif /* DZN_PRIVATE_H */
diff --git a/src/microsoft/vulkan/dzn_semaphore.cpp b/src/microsoft/vulkan/dzn_semaphore.cpp
deleted file mode 100644
index 301c9fc30ee32..0000000000000
--- a/src/microsoft/vulkan/dzn_semaphore.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright © Microsoft Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include "dzn_private.h"
-
-#include "vk_alloc.h"
-#include "vk_debug_report.h"
-#include "vk_util.h"
-
-#include "util/macros.h"
-
-dzn_semaphore::dzn_semaphore(dzn_device *device,
-                             const VkSemaphoreCreateInfo *pCreateInfo,
-                             const VkAllocationCallbacks *pAllocator)
-{
-   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO);
-   vk_object_base_init(&device->vk, &base, VK_OBJECT_TYPE_SEMAPHORE);
-   /* TODO: do something useful ;) */
-}
-
-dzn_semaphore::~dzn_semaphore()
-{
-   vk_object_base_finish(&base);
-}
-
-VKAPI_ATTR VkResult VKAPI_CALL
-dzn_CreateSemaphore(VkDevice device,
-                    const VkSemaphoreCreateInfo *pCreateInfo,
-                    const VkAllocationCallbacks *pAllocator,
-                    VkSemaphore *pSemaphore)
-{
-   return dzn_semaphore_factory::create(device, pCreateInfo, pAllocator, pSemaphore);
-}
-
-VKAPI_ATTR void VKAPI_CALL
-dzn_DestroySemaphore(VkDevice device,
-                     VkSemaphore semaphore,
-                     const VkAllocationCallbacks *pAllocator)
-{
-   return dzn_semaphore_factory::destroy(device, semaphore, pAllocator);
-}
diff --git a/src/microsoft/vulkan/meson.build b/src/microsoft/vulkan/meson.build
index a50a06a9a4a67..9f82c30eb6cff 100644
--- a/src/microsoft/vulkan/meson.build
+++ b/src/microsoft/vulkan/meson.build
@@ -84,7 +84,6 @@ libdzn_files = files(
   'dzn_cmd_buffer.cpp',
   'dzn_descriptor_set.cpp',
   'dzn_device.cpp',
-  'dzn_fence.cpp',
   'dzn_image.cpp',
   'dzn_meta.cpp',
   'dzn_nir.c',
@@ -92,7 +91,6 @@ libdzn_files = files(
   'dzn_pipeline_cache.cpp',
   'dzn_pipeline.cpp',
   'dzn_query.cpp',
-  'dzn_semaphore.cpp',
   'dzn_state.cpp',
   'dzn_sync.cpp',
   'dzn_util.cpp',
-- 
GitLab