nvk: Add a descriptor table data structure
authorFaith Ekstrand <faith.ekstrand@collabora.com>
Tue, 31 Jan 2023 02:11:48 +0000 (20:11 -0600)
committerMarge Bot <emma+marge@anholt.net>
Fri, 4 Aug 2023 21:31:54 +0000 (21:31 +0000)
This will be used for image and sampler descriptors

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>

src/nouveau/vulkan/meson.build
src/nouveau/vulkan/nvk_descriptor_table.c [new file with mode: 0644]
src/nouveau/vulkan/nvk_descriptor_table.h [new file with mode: 0644]

index 971adc5..7c9bc7b 100644 (file)
@@ -14,6 +14,8 @@ nvk_files = files(
   'nvk_descriptor_set.c',
   'nvk_descriptor_set_layout.c',
   'nvk_descriptor_set_layout.h',
+  'nvk_descriptor_table.c',
+  'nvk_descriptor_table.h',
   'nvk_device.c',
   'nvk_device.h',
   'nvk_device_memory.c',
diff --git a/src/nouveau/vulkan/nvk_descriptor_table.c b/src/nouveau/vulkan/nvk_descriptor_table.c
new file mode 100644 (file)
index 0000000..21ba49b
--- /dev/null
@@ -0,0 +1,109 @@
+#include "nvk_descriptor_table.h"
+
+#include "nvk_device.h"
+#include "nvk_physical_device.h"
+
+VkResult
+nvk_descriptor_table_init(struct nvk_device *device,
+                          struct nvk_descriptor_table *table,
+                          uint32_t descriptor_size,
+                          uint32_t min_descriptor_count,
+                          uint32_t max_descriptor_count)
+{
+   struct nvk_physical_device *pdevice = nvk_device_physical(device);
+   memset(table, 0, sizeof(*table));
+   VkResult result;
+
+   simple_mtx_init(&table->mutex, mtx_plain);
+
+   /* TODO: Implement table growing.  This requires new uAPI */
+   assert(min_descriptor_count == max_descriptor_count);
+
+   table->desc_size = descriptor_size;
+   table->alloc = min_descriptor_count;
+   table->next_desc = 0;
+   table->free_count = 0;
+
+   const uint32_t bo_size = table->alloc * table->desc_size;
+   table->bo = nouveau_ws_bo_new(pdevice->dev, bo_size, 256,
+                                 NOUVEAU_WS_BO_LOCAL | NOUVEAU_WS_BO_MAP);
+   if (table->bo == NULL) {
+      result = vk_errorf(device, VK_ERROR_OUT_OF_DEVICE_MEMORY,
+                         "Failed to allocate the image descriptor table");
+      goto fail;
+   }
+
+   table->map = nouveau_ws_bo_map(table->bo, NOUVEAU_WS_BO_WR);
+   if (table->map == NULL) {
+      result = vk_errorf(device, VK_ERROR_OUT_OF_DEVICE_MEMORY,
+                         "Failed to map the image descriptor table");
+      goto fail;
+   }
+
+   const size_t free_table_size = table->alloc * sizeof(uint32_t);
+   table->free_table = vk_alloc(&device->vk.alloc, free_table_size, 4,
+                                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (table->free_table == NULL) {
+      result = vk_errorf(device, VK_ERROR_OUT_OF_HOST_MEMORY,
+                         "Failed to allocate image descriptor free table");
+      goto fail;
+   }
+
+   return VK_SUCCESS;
+
+fail:
+   nvk_descriptor_table_finish(device, table);
+   return result;
+}
+
+void
+nvk_descriptor_table_finish(struct nvk_device *device,
+                            struct nvk_descriptor_table *table)
+{
+   if (table->bo != NULL)
+      nouveau_ws_bo_destroy(table->bo);
+   vk_free(&device->vk.alloc, table->free_table);
+   simple_mtx_destroy(&table->mutex);
+}
+
+#define NVK_IMAGE_DESC_INVALID
+
+static void *
+nvk_descriptor_table_alloc_locked(struct nvk_device *device,
+                                  struct nvk_descriptor_table *table,
+                                  uint32_t *index_out)
+{
+   if (table->free_count > 0) {
+      *index_out = table->free_table[--table->free_count];
+      return (char *)table->map + (*index_out * table->desc_size);
+   }
+
+   if (table->next_desc < table->alloc) {
+      *index_out = table->next_desc++;
+      return (char *)table->map + (*index_out * table->desc_size);
+   }
+
+   return NULL;
+}
+
+void *
+nvk_descriptor_table_alloc(struct nvk_device *device,
+                           struct nvk_descriptor_table *table,
+                           uint32_t *index_out)
+{
+   simple_mtx_lock(&table->mutex);
+   void *map = nvk_descriptor_table_alloc_locked(device, table, index_out);
+   simple_mtx_unlock(&table->mutex);
+   return map;
+}
+
+void
+nvk_descriptor_table_free(struct nvk_device *device,
+                          struct nvk_descriptor_table *table,
+                          uint32_t index)
+{
+   simple_mtx_lock(&table->mutex);
+   assert(table->free_count < table->alloc);
+   table->free_table[table->free_count++] = index;
+   simple_mtx_unlock(&table->mutex);
+}
diff --git a/src/nouveau/vulkan/nvk_descriptor_table.h b/src/nouveau/vulkan/nvk_descriptor_table.h
new file mode 100644 (file)
index 0000000..970caef
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef NVK_DESCRIPTOR_TABLE_H
+#define NVK_DESCRIPTOR_TABLE_H 1
+
+#include "nvk_private.h"
+
+#include "nouveau_bo.h"
+#include "nouveau_push.h"
+#include "util/simple_mtx.h"
+
+struct nvk_device;
+
+struct nvk_descriptor_table {
+   simple_mtx_t mutex;
+
+   uint32_t desc_size; /**< Size of a descriptor */
+   uint32_t alloc; /**< Number of descriptors allocated */
+   uint32_t next_desc; /**< Next unallocated descriptor */
+   uint32_t free_count; /**< Size of free_table */
+
+   struct nouveau_ws_bo *bo;
+   void *map;
+
+   /* Stack for free descriptor elements */
+   uint32_t *free_table;
+};
+
+VkResult nvk_descriptor_table_init(struct nvk_device *device,
+                                   struct nvk_descriptor_table *table,
+                                   uint32_t descriptor_size,
+                                   uint32_t min_descriptor_count,
+                                   uint32_t max_descriptor_count);
+
+void nvk_descriptor_table_finish(struct nvk_device *device,
+                                 struct nvk_descriptor_table *table);
+
+void *nvk_descriptor_table_alloc(struct nvk_device *device,
+                                 struct nvk_descriptor_table *table,
+                                 uint32_t *index_out);
+
+void nvk_descriptor_table_free(struct nvk_device *device,
+                               struct nvk_descriptor_table *table,
+                               uint32_t index);
+
+static inline void
+nvk_push_descriptor_table_ref(struct nouveau_ws_push *push,
+                              const struct nvk_descriptor_table *table)
+{
+   if (table->bo)
+      nouveau_ws_push_ref(push, table->bo, NOUVEAU_WS_BO_RD);
+}
+
+static inline uint64_t
+nvk_descriptor_table_base_address(const struct nvk_descriptor_table *table)
+{
+   return table->bo->offset;
+}
+
+#endif