nvk: add basic device memory support
authorKarol Herbst <kherbst@redhat.com>
Fri, 20 May 2022 13:27:09 +0000 (15:27 +0200)
committerMarge Bot <emma+marge@anholt.net>
Fri, 4 Aug 2023 21:31:53 +0000 (21:31 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>

src/nouveau/vulkan/meson.build
src/nouveau/vulkan/nvk_buffer.c
src/nouveau/vulkan/nvk_device.c
src/nouveau/vulkan/nvk_device.h
src/nouveau/vulkan/nvk_device_memory.c [new file with mode: 0644]
src/nouveau/vulkan/nvk_device_memory.h [new file with mode: 0644]
src/nouveau/vulkan/nvk_image.c

index 8757f54..de93fa9 100644 (file)
@@ -3,6 +3,8 @@ nvk_files = files(
   'nvk_buffer.h',
   'nvk_device.c',
   'nvk_device.h',
+  'nvk_device_memory.c',
+  'nvk_device_memory.h',
   'nvk_image.c',
   'nvk_image.h',
   'nvk_image_view.c',
index ec15b96..ccd53fd 100644 (file)
@@ -1,6 +1,7 @@
 #include "nvk_buffer.h"
 
 #include "nvk_device.h"
+#include "nvk_physical_device.h"
 
 VKAPI_ATTR VkResult VKAPI_CALL nvk_CreateBuffer(VkDevice _device,
    const VkBufferCreateInfo *pCreateInfo,
@@ -31,3 +32,26 @@ VKAPI_ATTR void VKAPI_CALL nvk_DestroyBuffer(VkDevice _device,
 
    vk_buffer_destroy(&device->vk, pAllocator, &buffer->vk);
 }
+
+VKAPI_ATTR void VKAPI_CALL nvk_GetBufferMemoryRequirements2(
+    VkDevice _device,
+    const VkBufferMemoryRequirementsInfo2 *pInfo,
+    VkMemoryRequirements2 *pMemoryRequirements)
+{
+   VK_FROM_HANDLE(nvk_device, device, _device);
+   VK_FROM_HANDLE(nvk_buffer, buffer, pInfo->buffer);
+
+   pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
+      .size = buffer->vk.size,
+      .alignment = 64, /* TODO */
+      .memoryTypeBits = BITFIELD_MASK(device->pdev->mem_type_cnt),
+   };
+
+   vk_foreach_struct(ext, pMemoryRequirements->pNext) {
+      switch (ext->sType) {
+      default:
+         nvk_debug_ignored_stype(ext->sType);
+         break;
+      }
+   }
+}
index d64f4c3..7b8b9fd 100644 (file)
@@ -32,6 +32,8 @@ nvk_CreateDevice(VkPhysicalDevice physicalDevice,
    if (result != VK_SUCCESS)
       goto fail_alloc;
 
+   device->pdev = physical_device;
+
    *pDevice = nvk_device_to_handle(device);
 
    return VK_SUCCESS;
index 95ba571..4991f71 100644 (file)
@@ -5,8 +5,10 @@
 
 #include "vulkan/runtime/vk_device.h"
 
+struct nvk_physical_device;
 struct nvk_device {
    struct vk_device vk;
+   struct nvk_physical_device *pdev;
 };
 
 VK_DEFINE_HANDLE_CASTS(nvk_device, vk.base, VkDevice, VK_OBJECT_TYPE_DEVICE)
diff --git a/src/nouveau/vulkan/nvk_device_memory.c b/src/nouveau/vulkan/nvk_device_memory.c
new file mode 100644 (file)
index 0000000..54e6c7a
--- /dev/null
@@ -0,0 +1,151 @@
+#include "nvk_device_memory.h"
+
+#include "nouveau_bo.h"
+
+#include "nvk_device.h"
+#include "nvk_physical_device.h"
+
+#include <inttypes.h>
+#include <sys/mman.h>
+
+VKAPI_ATTR VkResult VKAPI_CALL
+nvk_AllocateMemory(
+   VkDevice _device,
+   const VkMemoryAllocateInfo *pAllocateInfo,
+   const VkAllocationCallbacks *pAllocator,
+   VkDeviceMemory *pMem)
+{
+   VK_FROM_HANDLE(nvk_device, device, _device);
+   VkMemoryType *type = &device->pdev->mem_types[pAllocateInfo->memoryTypeIndex];
+   struct nvk_device_memory *mem;
+
+   mem = vk_object_alloc(&device->vk, pAllocator, sizeof(*mem), VK_OBJECT_TYPE_DEVICE_MEMORY);
+   if (!mem)
+      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   enum nouveau_ws_bo_flags flags;
+   if (type->propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
+      flags = NOUVEAU_WS_BO_LOCAL;
+   else
+      flags = NOUVEAU_WS_BO_GART;
+
+   if (type->propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+      flags |= NOUVEAU_WS_BO_MAP;
+
+   mem->map = NULL;
+   mem->bo = nouveau_ws_bo_new(device->pdev->dev, pAllocateInfo->allocationSize, 0, flags);
+   if (!mem->bo) {
+      vk_object_free(&device->vk, pAllocator, mem);
+      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
+   }
+
+   *pMem = nvk_device_memory_to_handle(mem);
+
+   return VK_SUCCESS;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+nvk_FreeMemory(
+   VkDevice _device,
+   VkDeviceMemory _mem,
+   const VkAllocationCallbacks *pAllocator)
+{
+   VK_FROM_HANDLE(nvk_device, device, _device);
+   VK_FROM_HANDLE(nvk_device_memory, mem, _mem);
+
+   if (!mem)
+      return;
+
+   if (mem->map)
+      nvk_UnmapMemory(_device, _mem);
+
+   nouveau_ws_bo_destroy(mem->bo);
+
+   vk_object_free(&device->vk, pAllocator, mem);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+nvk_MapMemory(
+   VkDevice _device,
+   VkDeviceMemory _memory,
+   VkDeviceSize offset,
+   VkDeviceSize size,
+   VkMemoryMapFlags flags,
+   void **ppData)
+{
+   VK_FROM_HANDLE(nvk_device, device, _device);
+   VK_FROM_HANDLE(nvk_device_memory, mem, _memory);
+
+   if (mem == NULL) {
+      *ppData = NULL;
+      return VK_SUCCESS;
+   }
+
+   if (size == VK_WHOLE_SIZE)
+      size = mem->bo->size - offset;
+
+   /* From the Vulkan spec version 1.0.32 docs for MapMemory:
+    *
+    *  * If size is not equal to VK_WHOLE_SIZE, size must be greater than 0
+    *    assert(size != 0);
+    *  * If size is not equal to VK_WHOLE_SIZE, size must be less than or
+    *    equal to the size of the memory minus offset
+    */
+   assert(size > 0);
+   assert(offset + size <= mem->bo->size);
+
+   if (size != (size_t)size) {
+      return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED,
+                       "requested size 0x%"PRIx64" does not fit in %u bits",
+                       size, (unsigned)(sizeof(size_t) * 8));
+   }
+
+   /* From the Vulkan 1.2.194 spec:
+    *
+    *    "memory must not be currently host mapped"
+    */
+   if (mem->map != NULL) {
+      return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED, "Memory object already mapped.");
+   }
+
+   mem->map = nouveau_ws_bo_map(mem->bo, NOUVEAU_WS_BO_RDWR);
+   if (mem->map == NULL) {
+      return vk_errorf(device, VK_ERROR_MEMORY_MAP_FAILED, "Memory object couldn't be mapped.");
+   }
+
+   *ppData = mem->map + offset;
+
+   return VK_SUCCESS;
+}
+
+VKAPI_ATTR void VKAPI_CALL
+nvk_UnmapMemory(
+   VkDevice _device,
+   VkDeviceMemory _memory)
+{
+   VK_FROM_HANDLE(nvk_device_memory, mem, _memory);
+
+   if (mem == NULL)
+      return;
+
+   munmap(mem->map, mem->bo->size);
+   mem->map = NULL;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+nvk_FlushMappedMemoryRanges(
+   VkDevice _device,
+   uint32_t memoryRangeCount,
+   const VkMappedMemoryRange *pMemoryRanges)
+{
+   return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+nvk_InvalidateMappedMemoryRanges(
+   VkDevice _device,
+   uint32_t memoryRangeCount,
+   const VkMappedMemoryRange *pMemoryRanges)
+{
+   return VK_SUCCESS;
+}
diff --git a/src/nouveau/vulkan/nvk_device_memory.h b/src/nouveau/vulkan/nvk_device_memory.h
new file mode 100644 (file)
index 0000000..14749c6
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef NVK_MEMORY
+#define NVK_MEMORY 1
+
+#include "nvk_private.h"
+
+struct nvk_device_memory {
+   struct vk_object_base base;
+
+   struct nouveau_ws_bo *bo;
+
+   void *map;
+};
+
+VK_DEFINE_HANDLE_CASTS(nvk_device_memory, base, VkDeviceMemory, VK_OBJECT_TYPE_DEVICE_MEMORY)
+
+#endif
index b1aaf2a..74df875 100644 (file)
@@ -53,3 +53,17 @@ VKAPI_ATTR void VKAPI_CALL nvk_DestroyImage(VkDevice _device,
    nvk_image_finish(image);
    vk_free2(&device->vk.alloc, pAllocator, image);
 }
+
+VKAPI_ATTR void VKAPI_CALL nvk_GetImageMemoryRequirements2(
+   VkDevice _device,
+   const VkImageMemoryRequirementsInfo2 *pInfo,
+   VkMemoryRequirements2 *pMemoryRequirements)
+{
+   vk_foreach_struct_const(ext, pInfo->pNext) {
+      switch (ext->sType) {
+      default:
+         nvk_debug_ignored_stype(ext->sType);
+         break;
+      }
+   }
+}