17ec681f3Smrg/*
27ec681f3Smrg * Copyright 2019 Google LLC
37ec681f3Smrg * SPDX-License-Identifier: MIT
47ec681f3Smrg *
57ec681f3Smrg * based in part on anv and radv which are:
67ec681f3Smrg * Copyright © 2015 Intel Corporation
77ec681f3Smrg * Copyright © 2016 Red Hat.
87ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen
97ec681f3Smrg */
107ec681f3Smrg
117ec681f3Smrg#include "vn_buffer.h"
127ec681f3Smrg
137ec681f3Smrg#include "venus-protocol/vn_protocol_driver_buffer.h"
147ec681f3Smrg#include "venus-protocol/vn_protocol_driver_buffer_view.h"
157ec681f3Smrg
167ec681f3Smrg#include "vn_android.h"
177ec681f3Smrg#include "vn_device.h"
187ec681f3Smrg#include "vn_device_memory.h"
197ec681f3Smrg
207ec681f3Smrg/* buffer commands */
217ec681f3Smrg
227ec681f3SmrgVkResult
237ec681f3Smrgvn_buffer_create(struct vn_device *dev,
247ec681f3Smrg                 const VkBufferCreateInfo *create_info,
257ec681f3Smrg                 const VkAllocationCallbacks *alloc,
267ec681f3Smrg                 struct vn_buffer **out_buf)
277ec681f3Smrg{
287ec681f3Smrg   VkDevice device = vn_device_to_handle(dev);
297ec681f3Smrg   struct vn_buffer *buf = NULL;
307ec681f3Smrg   VkBuffer buffer = VK_NULL_HANDLE;
317ec681f3Smrg   VkResult result;
327ec681f3Smrg
337ec681f3Smrg   buf = vk_zalloc(alloc, sizeof(*buf), VN_DEFAULT_ALIGN,
347ec681f3Smrg                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
357ec681f3Smrg   if (!buf)
367ec681f3Smrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
377ec681f3Smrg
387ec681f3Smrg   vn_object_base_init(&buf->base, VK_OBJECT_TYPE_BUFFER, &dev->base);
397ec681f3Smrg
407ec681f3Smrg   buffer = vn_buffer_to_handle(buf);
417ec681f3Smrg   /* TODO async */
427ec681f3Smrg   result = vn_call_vkCreateBuffer(dev->instance, device, create_info, NULL,
437ec681f3Smrg                                   &buffer);
447ec681f3Smrg   if (result != VK_SUCCESS) {
457ec681f3Smrg      vn_object_base_fini(&buf->base);
467ec681f3Smrg      vk_free(alloc, buf);
477ec681f3Smrg      return result;
487ec681f3Smrg   }
497ec681f3Smrg
507ec681f3Smrg   /* TODO add a per-device cache for the requirements */
517ec681f3Smrg   buf->memory_requirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
527ec681f3Smrg   buf->memory_requirements.pNext = &buf->dedicated_requirements;
537ec681f3Smrg   buf->dedicated_requirements.sType =
547ec681f3Smrg      VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
557ec681f3Smrg   buf->dedicated_requirements.pNext = NULL;
567ec681f3Smrg
577ec681f3Smrg   vn_call_vkGetBufferMemoryRequirements2(
587ec681f3Smrg      dev->instance, device,
597ec681f3Smrg      &(VkBufferMemoryRequirementsInfo2){
607ec681f3Smrg         .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,
617ec681f3Smrg         .buffer = buffer,
627ec681f3Smrg      },
637ec681f3Smrg      &buf->memory_requirements);
647ec681f3Smrg
657ec681f3Smrg   *out_buf = buf;
667ec681f3Smrg
677ec681f3Smrg   return VK_SUCCESS;
687ec681f3Smrg}
697ec681f3Smrg
707ec681f3SmrgVkResult
717ec681f3Smrgvn_CreateBuffer(VkDevice device,
727ec681f3Smrg                const VkBufferCreateInfo *pCreateInfo,
737ec681f3Smrg                const VkAllocationCallbacks *pAllocator,
747ec681f3Smrg                VkBuffer *pBuffer)
757ec681f3Smrg{
767ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
777ec681f3Smrg   const VkAllocationCallbacks *alloc =
787ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
797ec681f3Smrg   struct vn_buffer *buf = NULL;
807ec681f3Smrg   VkResult result;
817ec681f3Smrg
827ec681f3Smrg   const VkExternalMemoryBufferCreateInfo *external_info =
837ec681f3Smrg      vk_find_struct_const(pCreateInfo->pNext,
847ec681f3Smrg                           EXTERNAL_MEMORY_BUFFER_CREATE_INFO);
857ec681f3Smrg   const bool ahb_info =
867ec681f3Smrg      external_info &&
877ec681f3Smrg      external_info->handleTypes ==
887ec681f3Smrg         VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
897ec681f3Smrg
907ec681f3Smrg   if (ahb_info)
917ec681f3Smrg      result = vn_android_buffer_from_ahb(dev, pCreateInfo, alloc, &buf);
927ec681f3Smrg   else
937ec681f3Smrg      result = vn_buffer_create(dev, pCreateInfo, alloc, &buf);
947ec681f3Smrg
957ec681f3Smrg   if (result != VK_SUCCESS)
967ec681f3Smrg      return vn_error(dev->instance, result);
977ec681f3Smrg
987ec681f3Smrg   *pBuffer = vn_buffer_to_handle(buf);
997ec681f3Smrg
1007ec681f3Smrg   return VK_SUCCESS;
1017ec681f3Smrg}
1027ec681f3Smrg
1037ec681f3Smrgvoid
1047ec681f3Smrgvn_DestroyBuffer(VkDevice device,
1057ec681f3Smrg                 VkBuffer buffer,
1067ec681f3Smrg                 const VkAllocationCallbacks *pAllocator)
1077ec681f3Smrg{
1087ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1097ec681f3Smrg   struct vn_buffer *buf = vn_buffer_from_handle(buffer);
1107ec681f3Smrg   const VkAllocationCallbacks *alloc =
1117ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
1127ec681f3Smrg
1137ec681f3Smrg   if (!buf)
1147ec681f3Smrg      return;
1157ec681f3Smrg
1167ec681f3Smrg   vn_async_vkDestroyBuffer(dev->instance, device, buffer, NULL);
1177ec681f3Smrg
1187ec681f3Smrg   vn_object_base_fini(&buf->base);
1197ec681f3Smrg   vk_free(alloc, buf);
1207ec681f3Smrg}
1217ec681f3Smrg
1227ec681f3SmrgVkDeviceAddress
1237ec681f3Smrgvn_GetBufferDeviceAddress(VkDevice device,
1247ec681f3Smrg                          const VkBufferDeviceAddressInfo *pInfo)
1257ec681f3Smrg{
1267ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1277ec681f3Smrg
1287ec681f3Smrg   return vn_call_vkGetBufferDeviceAddress(dev->instance, device, pInfo);
1297ec681f3Smrg}
1307ec681f3Smrg
1317ec681f3Smrguint64_t
1327ec681f3Smrgvn_GetBufferOpaqueCaptureAddress(VkDevice device,
1337ec681f3Smrg                                 const VkBufferDeviceAddressInfo *pInfo)
1347ec681f3Smrg{
1357ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1367ec681f3Smrg
1377ec681f3Smrg   return vn_call_vkGetBufferOpaqueCaptureAddress(dev->instance, device,
1387ec681f3Smrg                                                  pInfo);
1397ec681f3Smrg}
1407ec681f3Smrg
1417ec681f3Smrgvoid
1427ec681f3Smrgvn_GetBufferMemoryRequirements(VkDevice device,
1437ec681f3Smrg                               VkBuffer buffer,
1447ec681f3Smrg                               VkMemoryRequirements *pMemoryRequirements)
1457ec681f3Smrg{
1467ec681f3Smrg   const struct vn_buffer *buf = vn_buffer_from_handle(buffer);
1477ec681f3Smrg
1487ec681f3Smrg   *pMemoryRequirements = buf->memory_requirements.memoryRequirements;
1497ec681f3Smrg}
1507ec681f3Smrg
1517ec681f3Smrgvoid
1527ec681f3Smrgvn_GetBufferMemoryRequirements2(VkDevice device,
1537ec681f3Smrg                                const VkBufferMemoryRequirementsInfo2 *pInfo,
1547ec681f3Smrg                                VkMemoryRequirements2 *pMemoryRequirements)
1557ec681f3Smrg{
1567ec681f3Smrg   const struct vn_buffer *buf = vn_buffer_from_handle(pInfo->buffer);
1577ec681f3Smrg   union {
1587ec681f3Smrg      VkBaseOutStructure *pnext;
1597ec681f3Smrg      VkMemoryRequirements2 *two;
1607ec681f3Smrg      VkMemoryDedicatedRequirements *dedicated;
1617ec681f3Smrg   } u = { .two = pMemoryRequirements };
1627ec681f3Smrg
1637ec681f3Smrg   while (u.pnext) {
1647ec681f3Smrg      switch (u.pnext->sType) {
1657ec681f3Smrg      case VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2:
1667ec681f3Smrg         u.two->memoryRequirements =
1677ec681f3Smrg            buf->memory_requirements.memoryRequirements;
1687ec681f3Smrg         break;
1697ec681f3Smrg      case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS:
1707ec681f3Smrg         u.dedicated->prefersDedicatedAllocation =
1717ec681f3Smrg            buf->dedicated_requirements.prefersDedicatedAllocation;
1727ec681f3Smrg         u.dedicated->requiresDedicatedAllocation =
1737ec681f3Smrg            buf->dedicated_requirements.requiresDedicatedAllocation;
1747ec681f3Smrg         break;
1757ec681f3Smrg      default:
1767ec681f3Smrg         break;
1777ec681f3Smrg      }
1787ec681f3Smrg      u.pnext = u.pnext->pNext;
1797ec681f3Smrg   }
1807ec681f3Smrg}
1817ec681f3Smrg
1827ec681f3SmrgVkResult
1837ec681f3Smrgvn_BindBufferMemory(VkDevice device,
1847ec681f3Smrg                    VkBuffer buffer,
1857ec681f3Smrg                    VkDeviceMemory memory,
1867ec681f3Smrg                    VkDeviceSize memoryOffset)
1877ec681f3Smrg{
1887ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
1897ec681f3Smrg   struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
1907ec681f3Smrg
1917ec681f3Smrg   if (mem->base_memory) {
1927ec681f3Smrg      memory = vn_device_memory_to_handle(mem->base_memory);
1937ec681f3Smrg      memoryOffset += mem->base_offset;
1947ec681f3Smrg   }
1957ec681f3Smrg
1967ec681f3Smrg   vn_async_vkBindBufferMemory(dev->instance, device, buffer, memory,
1977ec681f3Smrg                               memoryOffset);
1987ec681f3Smrg
1997ec681f3Smrg   return VK_SUCCESS;
2007ec681f3Smrg}
2017ec681f3Smrg
2027ec681f3SmrgVkResult
2037ec681f3Smrgvn_BindBufferMemory2(VkDevice device,
2047ec681f3Smrg                     uint32_t bindInfoCount,
2057ec681f3Smrg                     const VkBindBufferMemoryInfo *pBindInfos)
2067ec681f3Smrg{
2077ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
2087ec681f3Smrg   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
2097ec681f3Smrg
2107ec681f3Smrg   VkBindBufferMemoryInfo *local_infos = NULL;
2117ec681f3Smrg   for (uint32_t i = 0; i < bindInfoCount; i++) {
2127ec681f3Smrg      const VkBindBufferMemoryInfo *info = &pBindInfos[i];
2137ec681f3Smrg      struct vn_device_memory *mem =
2147ec681f3Smrg         vn_device_memory_from_handle(info->memory);
2157ec681f3Smrg      if (!mem->base_memory)
2167ec681f3Smrg         continue;
2177ec681f3Smrg
2187ec681f3Smrg      if (!local_infos) {
2197ec681f3Smrg         const size_t size = sizeof(*local_infos) * bindInfoCount;
2207ec681f3Smrg         local_infos = vk_alloc(alloc, size, VN_DEFAULT_ALIGN,
2217ec681f3Smrg                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
2227ec681f3Smrg         if (!local_infos)
2237ec681f3Smrg            return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2247ec681f3Smrg
2257ec681f3Smrg         memcpy(local_infos, pBindInfos, size);
2267ec681f3Smrg      }
2277ec681f3Smrg
2287ec681f3Smrg      local_infos[i].memory = vn_device_memory_to_handle(mem->base_memory);
2297ec681f3Smrg      local_infos[i].memoryOffset += mem->base_offset;
2307ec681f3Smrg   }
2317ec681f3Smrg   if (local_infos)
2327ec681f3Smrg      pBindInfos = local_infos;
2337ec681f3Smrg
2347ec681f3Smrg   vn_async_vkBindBufferMemory2(dev->instance, device, bindInfoCount,
2357ec681f3Smrg                                pBindInfos);
2367ec681f3Smrg
2377ec681f3Smrg   vk_free(alloc, local_infos);
2387ec681f3Smrg
2397ec681f3Smrg   return VK_SUCCESS;
2407ec681f3Smrg}
2417ec681f3Smrg
2427ec681f3Smrg/* buffer view commands */
2437ec681f3Smrg
2447ec681f3SmrgVkResult
2457ec681f3Smrgvn_CreateBufferView(VkDevice device,
2467ec681f3Smrg                    const VkBufferViewCreateInfo *pCreateInfo,
2477ec681f3Smrg                    const VkAllocationCallbacks *pAllocator,
2487ec681f3Smrg                    VkBufferView *pView)
2497ec681f3Smrg{
2507ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
2517ec681f3Smrg   const VkAllocationCallbacks *alloc =
2527ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
2537ec681f3Smrg
2547ec681f3Smrg   struct vn_buffer_view *view =
2557ec681f3Smrg      vk_zalloc(alloc, sizeof(*view), VN_DEFAULT_ALIGN,
2567ec681f3Smrg                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2577ec681f3Smrg   if (!view)
2587ec681f3Smrg      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2597ec681f3Smrg
2607ec681f3Smrg   vn_object_base_init(&view->base, VK_OBJECT_TYPE_BUFFER_VIEW, &dev->base);
2617ec681f3Smrg
2627ec681f3Smrg   VkBufferView view_handle = vn_buffer_view_to_handle(view);
2637ec681f3Smrg   vn_async_vkCreateBufferView(dev->instance, device, pCreateInfo, NULL,
2647ec681f3Smrg                               &view_handle);
2657ec681f3Smrg
2667ec681f3Smrg   *pView = view_handle;
2677ec681f3Smrg
2687ec681f3Smrg   return VK_SUCCESS;
2697ec681f3Smrg}
2707ec681f3Smrg
2717ec681f3Smrgvoid
2727ec681f3Smrgvn_DestroyBufferView(VkDevice device,
2737ec681f3Smrg                     VkBufferView bufferView,
2747ec681f3Smrg                     const VkAllocationCallbacks *pAllocator)
2757ec681f3Smrg{
2767ec681f3Smrg   struct vn_device *dev = vn_device_from_handle(device);
2777ec681f3Smrg   struct vn_buffer_view *view = vn_buffer_view_from_handle(bufferView);
2787ec681f3Smrg   const VkAllocationCallbacks *alloc =
2797ec681f3Smrg      pAllocator ? pAllocator : &dev->base.base.alloc;
2807ec681f3Smrg
2817ec681f3Smrg   if (!view)
2827ec681f3Smrg      return;
2837ec681f3Smrg
2847ec681f3Smrg   vn_async_vkDestroyBufferView(dev->instance, device, bufferView, NULL);
2857ec681f3Smrg
2867ec681f3Smrg   vn_object_base_fini(&view->base);
2877ec681f3Smrg   vk_free(alloc, view);
2887ec681f3Smrg}
289