Mesa (main): vulkan/runtime: Add sparse bind support.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Dec 31 15:40:22 UTC 2021


Module: Mesa
Branch: main
Commit: 7a84314c12ae0d001eb7d9df7d1f3c5c1c04b819
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=7a84314c12ae0d001eb7d9df7d1f3c5c1c04b819

Author: Bas Nieuwenhuizen <bas at basnieuwenhuizen.nl>
Date:   Sun Nov 28 18:52:16 2021 +0100

vulkan/runtime: Add sparse bind support.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13974>

---

 src/vulkan/runtime/vk_queue.c | 182 +++++++++++++++++++++++++++++++++++++++++-
 src/vulkan/runtime/vk_queue.h |   8 ++
 2 files changed, 187 insertions(+), 3 deletions(-)

diff --git a/src/vulkan/runtime/vk_queue.c b/src/vulkan/runtime/vk_queue.c
index c76a7321b6f..cd9c7daccf9 100644
--- a/src/vulkan/runtime/vk_queue.c
+++ b/src/vulkan/runtime/vk_queue.c
@@ -131,13 +131,30 @@ static struct vk_queue_submit *
 vk_queue_submit_alloc(struct vk_queue *queue,
                       uint32_t wait_count,
                       uint32_t command_buffer_count,
-                      uint32_t signal_count)
+                      uint32_t buffer_bind_count,
+                      uint32_t image_opaque_bind_count,
+                      uint32_t image_bind_count,
+                      uint32_t bind_entry_count,
+                      uint32_t image_bind_entry_count,
+                      uint32_t signal_count,
+                      VkSparseMemoryBind **bind_entries,
+                      VkSparseImageMemoryBind **image_bind_entries)
 {
    VK_MULTIALLOC(ma);
    VK_MULTIALLOC_DECL(&ma, struct vk_queue_submit, submit, 1);
    VK_MULTIALLOC_DECL(&ma, struct vk_sync_wait, waits, wait_count);
    VK_MULTIALLOC_DECL(&ma, struct vk_command_buffer *, command_buffers,
                       command_buffer_count);
+   VK_MULTIALLOC_DECL(&ma, VkSparseBufferMemoryBindInfo, buffer_binds,
+                      buffer_bind_count);
+   VK_MULTIALLOC_DECL(&ma, VkSparseImageOpaqueMemoryBindInfo,
+                      image_opaque_binds, image_opaque_bind_count);
+   VK_MULTIALLOC_DECL(&ma, VkSparseImageMemoryBindInfo, image_binds,
+                      image_bind_count);
+   VK_MULTIALLOC_DECL(&ma, VkSparseMemoryBind,
+                      bind_entries_local, bind_entry_count);
+   VK_MULTIALLOC_DECL(&ma, VkSparseImageMemoryBind, image_bind_entries_local,
+                      image_bind_entry_count);
    VK_MULTIALLOC_DECL(&ma, struct vk_sync_signal, signals, signal_count);
    VK_MULTIALLOC_DECL(&ma, struct vk_sync *, wait_temps, wait_count);
 
@@ -156,14 +173,26 @@ vk_queue_submit_alloc(struct vk_queue *queue,
    submit->wait_count            = wait_count;
    submit->command_buffer_count  = command_buffer_count;
    submit->signal_count          = signal_count;
+   submit->buffer_bind_count     = buffer_bind_count;
+   submit->image_opaque_bind_count = image_opaque_bind_count;
+   submit->image_bind_count      = image_bind_count;
 
    submit->waits           = waits;
    submit->command_buffers = command_buffers;
    submit->signals         = signals;
+   submit->buffer_binds    = buffer_binds;
+   submit->image_opaque_binds = image_opaque_binds;
+   submit->image_binds     = image_binds;
    submit->_wait_temps     = wait_temps;
    submit->_wait_points    = wait_points;
    submit->_signal_points  = signal_points;
 
+   if (bind_entries)
+      *bind_entries = bind_entries_local;
+
+   if (image_bind_entries)
+      *image_bind_entries = image_bind_entries_local;
+
    return submit;
 }
 
@@ -518,6 +547,15 @@ struct vulkan_submit_info {
    uint32_t signal_count;
    const VkSemaphoreSubmitInfoKHR *signals;
 
+   uint32_t buffer_bind_count;
+   const VkSparseBufferMemoryBindInfo *buffer_binds;
+
+   uint32_t image_opaque_bind_count;
+   const VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
+
+   uint32_t image_bind_count;
+   const VkSparseImageMemoryBindInfo *image_binds;
+
    struct vk_fence *fence;
 };
 
@@ -526,6 +564,19 @@ vk_queue_submit(struct vk_queue *queue,
                 const struct vulkan_submit_info *info)
 {
    VkResult result;
+   uint32_t sparse_memory_bind_entry_count = 0;
+   uint32_t sparse_memory_image_bind_entry_count = 0;
+   VkSparseMemoryBind *sparse_memory_bind_entries = NULL;
+   VkSparseImageMemoryBind *sparse_memory_image_bind_entries = NULL;
+
+   for (uint32_t i = 0; i < info->buffer_bind_count; ++i)
+      sparse_memory_bind_entry_count += info->buffer_binds[i].bindCount;
+
+   for (uint32_t i = 0; i < info->image_opaque_bind_count; ++i)
+      sparse_memory_bind_entry_count += info->image_opaque_binds[i].bindCount;
+
+   for (uint32_t i = 0; i < info->image_bind_count; ++i)
+      sparse_memory_image_bind_entry_count += info->image_binds[i].bindCount;
 
    const struct wsi_memory_signal_submit_info *mem_signal =
       vk_find_struct_const(info->pNext, WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA);
@@ -536,8 +587,15 @@ vk_queue_submit(struct vk_queue *queue,
    struct vk_queue_submit *submit =
       vk_queue_submit_alloc(queue, info->wait_count,
                             info->command_buffer_count,
+                            info->buffer_bind_count,
+                            info->image_opaque_bind_count,
+                            info->image_bind_count,
+                            sparse_memory_bind_entry_count,
+                            sparse_memory_image_bind_entry_count,
                             info->signal_count +
-                            signal_mem_sync + (info->fence != NULL));
+                            signal_mem_sync + (info->fence != NULL),
+                            &sparse_memory_bind_entries,
+                            &sparse_memory_image_bind_entries);
    if (unlikely(submit == NULL))
       return vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
 
@@ -607,6 +665,43 @@ vk_queue_submit(struct vk_queue *queue,
       submit->command_buffers[i] = cmd_buffer;
    }
 
+   sparse_memory_bind_entry_count = 0;
+   sparse_memory_image_bind_entry_count = 0;
+
+   typed_memcpy(submit->buffer_binds, info->buffer_binds, info->buffer_bind_count);
+   for (uint32_t i = 0; i < info->buffer_bind_count; ++i) {
+      VkSparseMemoryBind *binds = sparse_memory_bind_entries +
+                                  sparse_memory_bind_entry_count;
+      submit->buffer_binds[i].pBinds = binds;
+      typed_memcpy(binds, info->buffer_binds[i].pBinds,
+                   info->buffer_binds[i].bindCount);
+
+      sparse_memory_bind_entry_count += info->buffer_binds[i].bindCount;
+   }
+
+   typed_memcpy(submit->image_opaque_binds, info->image_opaque_binds,
+                info->image_opaque_bind_count);
+   for (uint32_t i = 0; i < info->image_opaque_bind_count; ++i) {
+      VkSparseMemoryBind *binds = sparse_memory_bind_entries +
+                                  sparse_memory_bind_entry_count;
+      submit->image_opaque_binds[i].pBinds = binds;
+      typed_memcpy(binds, info->image_opaque_binds[i].pBinds,
+                   info->image_opaque_binds[i].bindCount);
+
+      sparse_memory_bind_entry_count += info->image_opaque_binds[i].bindCount;
+   }
+
+   typed_memcpy(submit->image_binds, info->image_binds, info->image_bind_count);
+   for (uint32_t i = 0; i < info->image_bind_count; ++i) {
+      VkSparseImageMemoryBind *binds = sparse_memory_image_bind_entries +
+                                       sparse_memory_image_bind_entry_count;
+      submit->image_binds[i].pBinds = binds;
+      typed_memcpy(binds, info->image_binds[i].pBinds,
+                   info->image_binds[i].bindCount);
+
+      sparse_memory_image_bind_entry_count += info->image_binds[i].bindCount;
+   }
+
    for (uint32_t i = 0; i < info->signal_count; i++) {
       VK_FROM_HANDLE(vk_semaphore, semaphore,
                      info->signals[i].semaphore);
@@ -933,7 +1028,8 @@ vk_queue_signal_sync(struct vk_queue *queue,
                      struct vk_sync *sync,
                      uint32_t signal_value)
 {
-   struct vk_queue_submit *submit = vk_queue_submit_alloc(queue, 0, 0, 1);
+   struct vk_queue_submit *submit = vk_queue_submit_alloc(queue, 0, 0, 0, 0, 0,
+                                                          0, 0, 1, NULL, NULL);
    if (unlikely(submit == NULL))
       return vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
 
@@ -1033,6 +1129,86 @@ vk_common_QueueSubmit2KHR(VkQueue _queue,
    return VK_SUCCESS;
 }
 
+VKAPI_ATTR VkResult VKAPI_CALL
+vk_common_QueueBindSparse(VkQueue _queue,
+                          uint32_t bindInfoCount,
+                          const VkBindSparseInfo *pBindInfo,
+                          VkFence _fence)
+{
+   VK_FROM_HANDLE(vk_queue, queue, _queue);
+   VK_FROM_HANDLE(vk_fence, fence, _fence);
+
+   if (vk_device_is_lost(queue->base.device))
+      return VK_ERROR_DEVICE_LOST;
+
+   if (bindInfoCount == 0) {
+      if (fence == NULL) {
+         return VK_SUCCESS;
+      } else {
+         return vk_queue_signal_sync(queue, vk_fence_get_active_sync(fence), 0);
+      }
+   }
+
+   for (uint32_t i = 0; i < bindInfoCount; i++) {
+      const VkTimelineSemaphoreSubmitInfo *timeline_info =
+         vk_find_struct_const(pBindInfo[i].pNext, TIMELINE_SEMAPHORE_SUBMIT_INFO);
+      const uint64_t *wait_values = timeline_info &&
+         timeline_info->waitSemaphoreValueCount ? timeline_info->pWaitSemaphoreValues : NULL;
+      const uint64_t *signal_values = timeline_info &&
+         timeline_info->signalSemaphoreValueCount ? timeline_info->pSignalSemaphoreValues : NULL;
+
+      STACK_ARRAY(VkSemaphoreSubmitInfoKHR, wait_semaphore_infos,
+                  pBindInfo[i].waitSemaphoreCount);
+      STACK_ARRAY(VkSemaphoreSubmitInfoKHR, signal_semaphore_infos,
+                  pBindInfo[i].signalSemaphoreCount);
+
+      if (!wait_semaphore_infos || !signal_semaphore_infos) {
+         STACK_ARRAY_FINISH(wait_semaphore_infos);
+         STACK_ARRAY_FINISH(signal_semaphore_infos);
+         return vk_error(queue, VK_ERROR_OUT_OF_HOST_MEMORY);
+      }
+
+      for (uint32_t j = 0; j < pBindInfo[i].waitSemaphoreCount; j++) {
+         wait_semaphore_infos[j] = (VkSemaphoreSubmitInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR,
+            .semaphore = pBindInfo[i].pWaitSemaphores[j],
+            .value = wait_values ? wait_values[j] : 0,
+         };
+      }
+
+      for (uint32_t j = 0; j < pBindInfo[i].signalSemaphoreCount; j++) {
+         signal_semaphore_infos[j] = (VkSemaphoreSubmitInfoKHR) {
+            .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR,
+            .semaphore = pBindInfo[i].pSignalSemaphores[j],
+            .value = signal_values ? signal_values[j] : 0,
+         };
+      }
+      struct vulkan_submit_info info = {
+         .pNext = pBindInfo[i].pNext,
+         .wait_count = pBindInfo[i].waitSemaphoreCount,
+         .waits = wait_semaphore_infos,
+         .signal_count = pBindInfo[i].signalSemaphoreCount,
+         .signals = signal_semaphore_infos,
+         .buffer_bind_count = pBindInfo[i].bufferBindCount,
+         .buffer_binds = pBindInfo[i].pBufferBinds,
+         .image_opaque_bind_count = pBindInfo[i].imageOpaqueBindCount,
+         .image_opaque_binds = pBindInfo[i].pImageOpaqueBinds,
+         .image_bind_count = pBindInfo[i].imageBindCount,
+         .image_binds = pBindInfo[i].pImageBinds,
+         .fence = i == bindInfoCount - 1 ? fence : NULL
+      };
+      VkResult result = vk_queue_submit(queue, &info);
+
+      STACK_ARRAY_FINISH(wait_semaphore_infos);
+      STACK_ARRAY_FINISH(signal_semaphore_infos);
+
+      if (unlikely(result != VK_SUCCESS))
+         return result;
+   }
+
+   return VK_SUCCESS;
+}
+
 static const struct vk_sync_type *
 get_cpu_wait_type(struct vk_physical_device *pdevice)
 {
diff --git a/src/vulkan/runtime/vk_queue.h b/src/vulkan/runtime/vk_queue.h
index 1e3dc12d9f8..88f6da6c037 100644
--- a/src/vulkan/runtime/vk_queue.h
+++ b/src/vulkan/runtime/vk_queue.h
@@ -180,10 +180,18 @@ struct vk_queue_submit {
    uint32_t command_buffer_count;
    uint32_t signal_count;
 
+   uint32_t buffer_bind_count;
+   uint32_t image_opaque_bind_count;
+   uint32_t image_bind_count;
+
    struct vk_sync_wait *waits;
    struct vk_command_buffer **command_buffers;
    struct vk_sync_signal *signals;
 
+   VkSparseBufferMemoryBindInfo *buffer_binds;
+   VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
+   VkSparseImageMemoryBindInfo *image_binds;
+
    uint32_t perf_pass_index;
 
    /* Used internally; should be ignored by drivers */



More information about the mesa-commit mailing list