Edit

IABSD.fr/xenocara/lib/mesa/src/intel/vulkan/anv_buffer.c

Branch :

  • Show log

    Commit

  • Author : jsg
    Date : 2025-06-05 11:23:11
    Hash : 67d6f117
    Message : Import Mesa 25.0.7

  • lib/mesa/src/intel/vulkan/anv_buffer.c
  • /* Copyright © 2024 Intel Corporation
     * SPDX-License-Identifier: MIT
     */
    
    #include "anv_private.h"
    
    static void
    anv_bind_buffer_memory(struct anv_device *device,
                           const VkBindBufferMemoryInfo *pBindInfo)
    {
       ANV_FROM_HANDLE(anv_device_memory, mem, pBindInfo->memory);
       ANV_FROM_HANDLE(anv_buffer, buffer, pBindInfo->buffer);
    
       assert(pBindInfo->sType == VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO);
       assert(!anv_buffer_is_sparse(buffer));
    
       const VkBindMemoryStatusKHR *bind_status =
          vk_find_struct_const(pBindInfo->pNext, BIND_MEMORY_STATUS_KHR);
    
       if (mem) {
          assert(pBindInfo->memoryOffset < mem->vk.size);
          assert(mem->vk.size - pBindInfo->memoryOffset >= buffer->vk.size);
          buffer->address = (struct anv_address) {
             .bo = mem->bo,
             .offset = pBindInfo->memoryOffset,
          };
       } else {
          buffer->address = ANV_NULL_ADDRESS;
       }
    
       ANV_RMV(buffer_bind, device, buffer);
    
       if (bind_status)
          *bind_status->pResult = VK_SUCCESS;
    }
    
    VkResult anv_BindBufferMemory2(
        VkDevice                                    _device,
        uint32_t                                    bindInfoCount,
        const VkBindBufferMemoryInfo*               pBindInfos)
    {
       ANV_FROM_HANDLE(anv_device, device, _device);
    
       for (uint32_t i = 0; i < bindInfoCount; i++)
          anv_bind_buffer_memory(device, &pBindInfos[i]);
    
       return VK_SUCCESS;
    }
    
    // Buffer functions
    
    static void
    anv_get_buffer_memory_requirements(struct anv_device *device,
                                       VkBufferCreateFlags flags,
                                       VkDeviceSize size,
                                       VkBufferUsageFlags2KHR usage,
                                       bool is_sparse,
                                       VkMemoryRequirements2* pMemoryRequirements)
    {
       /* The Vulkan spec (git aaed022) says:
        *
        *    memoryTypeBits is a bitfield and contains one bit set for every
        *    supported memory type for the resource. The bit `1<<i` is set if and
        *    only if the memory type `i` in the VkPhysicalDeviceMemoryProperties
        *    structure for the physical device is supported.
        *
        * We have special memory types for descriptor buffers.
        */
       uint32_t memory_types;
       if (flags & VK_BUFFER_CREATE_PROTECTED_BIT)
          memory_types = device->physical->memory.protected_mem_types;
       else if (usage & (VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT |
                         VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT))
          memory_types = device->physical->memory.dynamic_visible_mem_types;
       else if (device->physical->instance->enable_buffer_comp)
          memory_types = device->physical->memory.default_buffer_mem_types |
                         device->physical->memory.compressed_mem_types;
       else
          memory_types = device->physical->memory.default_buffer_mem_types;
    
       /* The GPU appears to write back to main memory in cachelines. Writes to a
        * buffers should not clobber with writes to another buffers so make sure
        * those are in different cachelines.
        */
       uint32_t alignment = 64;
    
       /* From the spec, section "Sparse Buffer and Fully-Resident Image Block
        * Size":
        *   "The sparse block size in bytes for sparse buffers and fully-resident
        *    images is reported as VkMemoryRequirements::alignment. alignment
        *    represents both the memory alignment requirement and the binding
        *    granularity (in bytes) for sparse resources."
        */
       if (is_sparse) {
          alignment = ANV_SPARSE_BLOCK_SIZE;
          size = align64(size, alignment);
       }
    
       pMemoryRequirements->memoryRequirements.size = size;
       pMemoryRequirements->memoryRequirements.alignment = alignment;
    
       /* Storage and Uniform buffers should have their size aligned to
        * 32-bits to avoid boundary checks when last DWord is not complete.
        * This would ensure that not internal padding would be needed for
        * 16-bit types.
        */
       if (device->robust_buffer_access &&
           (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ||
            usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
          pMemoryRequirements->memoryRequirements.size = align64(size, 4);
    
       pMemoryRequirements->memoryRequirements.memoryTypeBits = memory_types;
    
       vk_foreach_struct(ext, pMemoryRequirements->pNext) {
          switch (ext->sType) {
          case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
             VkMemoryDedicatedRequirements *requirements = (void *)ext;
             requirements->prefersDedicatedAllocation = false;
             requirements->requiresDedicatedAllocation = false;
             break;
          }
    
          default:
             vk_debug_ignored_stype(ext->sType);
             break;
          }
       }
    }
    
    static VkBufferUsageFlags2KHR
    get_buffer_usages(const VkBufferCreateInfo *create_info)
    {
       const VkBufferUsageFlags2CreateInfoKHR *usage2_info =
          vk_find_struct_const(create_info->pNext,
                               BUFFER_USAGE_FLAGS_2_CREATE_INFO_KHR);
       return usage2_info != NULL ? usage2_info->usage : create_info->usage;
    }
    
    void anv_GetDeviceBufferMemoryRequirements(
        VkDevice                                    _device,
        const VkDeviceBufferMemoryRequirements*     pInfo,
        VkMemoryRequirements2*                      pMemoryRequirements)
    {
       ANV_FROM_HANDLE(anv_device, device, _device);
       const bool is_sparse =
          pInfo->pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT;
       VkBufferUsageFlags2KHR usages = get_buffer_usages(pInfo->pCreateInfo);
    
       if ((device->physical->sparse_type == ANV_SPARSE_TYPE_NOT_SUPPORTED) &&
           INTEL_DEBUG(DEBUG_SPARSE) &&
           pInfo->pCreateInfo->flags & (VK_BUFFER_CREATE_SPARSE_BINDING_BIT |
                                        VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT |
                                        VK_BUFFER_CREATE_SPARSE_ALIASED_BIT))
          fprintf(stderr, "=== %s %s:%d flags:0x%08x\n", __func__, __FILE__,
                  __LINE__, pInfo->pCreateInfo->flags);
    
       anv_get_buffer_memory_requirements(device,
                                          pInfo->pCreateInfo->flags,
                                          pInfo->pCreateInfo->size,
                                          usages,
                                          is_sparse,
                                          pMemoryRequirements);
    }
    
    VkResult anv_CreateBuffer(
        VkDevice                                    _device,
        const VkBufferCreateInfo*                   pCreateInfo,
        const VkAllocationCallbacks*                pAllocator,
        VkBuffer*                                   pBuffer)
    {
       ANV_FROM_HANDLE(anv_device, device, _device);
       struct anv_buffer *buffer;
    
       if ((device->physical->sparse_type == ANV_SPARSE_TYPE_NOT_SUPPORTED) &&
           INTEL_DEBUG(DEBUG_SPARSE) &&
           pCreateInfo->flags & (VK_BUFFER_CREATE_SPARSE_BINDING_BIT |
                                 VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT |
                                 VK_BUFFER_CREATE_SPARSE_ALIASED_BIT))
          fprintf(stderr, "=== %s %s:%d flags:0x%08x\n", __func__, __FILE__,
                  __LINE__, pCreateInfo->flags);
    
       if ((pCreateInfo->flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) &&
           device->physical->sparse_type == ANV_SPARSE_TYPE_TRTT) {
          VkBufferUsageFlags2KHR usages = get_buffer_usages(pCreateInfo);
          if (usages & (VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT |
                        VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT)) {
             return vk_errorf(device, VK_ERROR_UNKNOWN,
                              "Cannot support sparse descriptor buffers with TRTT.");
          }
       }
    
       /* Don't allow creating buffers bigger than our address space.  The real
        * issue here is that we may align up the buffer size and we don't want
        * doing so to cause roll-over.  However, no one has any business
        * allocating a buffer larger than our GTT size.
        */
       if (pCreateInfo->size > device->physical->gtt_size)
          return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
    
       buffer = vk_buffer_create(&device->vk, pCreateInfo,
                                 pAllocator, sizeof(*buffer));
       if (buffer == NULL)
          return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
    
       buffer->address = ANV_NULL_ADDRESS;
       if (anv_buffer_is_sparse(buffer)) {
          enum anv_bo_alloc_flags alloc_flags = 0;
          uint64_t client_address = 0;
    
          if (buffer->vk.create_flags & VK_BUFFER_CREATE_DEVICE_ADDRESS_CAPTURE_REPLAY_BIT) {
             alloc_flags = ANV_BO_ALLOC_CLIENT_VISIBLE_ADDRESS;
             const VkBufferOpaqueCaptureAddressCreateInfo *opaque_addr_info =
                vk_find_struct_const(pCreateInfo->pNext,
                                     BUFFER_OPAQUE_CAPTURE_ADDRESS_CREATE_INFO);
             if (opaque_addr_info)
                client_address = opaque_addr_info->opaqueCaptureAddress;
          }
    
          if (buffer->vk.create_flags & VK_BUFFER_CREATE_DESCRIPTOR_BUFFER_CAPTURE_REPLAY_BIT_EXT) {
             alloc_flags = ANV_BO_ALLOC_CLIENT_VISIBLE_ADDRESS;
    
             const VkOpaqueCaptureDescriptorDataCreateInfoEXT *opaque_info =
                vk_find_struct_const(pCreateInfo->pNext,
                                     OPAQUE_CAPTURE_DESCRIPTOR_DATA_CREATE_INFO_EXT);
             if (opaque_info)
                client_address = *((const uint64_t *)opaque_info->opaqueCaptureDescriptorData);
          }
    
          /* If this buffer will be used as a descriptor buffer, make sure we
           * allocate it on the correct heap.
           */
          if (buffer->vk.usage & (VK_BUFFER_USAGE_2_SAMPLER_DESCRIPTOR_BUFFER_BIT_EXT |
                                  VK_BUFFER_USAGE_2_RESOURCE_DESCRIPTOR_BUFFER_BIT_EXT)) {
             alloc_flags |= ANV_BO_ALLOC_DYNAMIC_VISIBLE_POOL;
          }
    
          VkResult result = anv_init_sparse_bindings(device, buffer->vk.size,
                                                     &buffer->sparse_data,
                                                     alloc_flags, client_address,
                                                     &buffer->address);
          if (result != VK_SUCCESS) {
             vk_buffer_destroy(&device->vk, pAllocator, &buffer->vk);
             return result;
          }
       }
    
       ANV_RMV(buffer_create, device, false, buffer);
    
       *pBuffer = anv_buffer_to_handle(buffer);
    
       return VK_SUCCESS;
    }
    
    void anv_DestroyBuffer(
        VkDevice                                    _device,
        VkBuffer                                    _buffer,
        const VkAllocationCallbacks*                pAllocator)
    {
       ANV_FROM_HANDLE(anv_device, device, _device);
       ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
    
       if (!buffer)
          return;
    
       ANV_RMV(buffer_destroy, device, buffer);
    
       if (anv_buffer_is_sparse(buffer)) {
          assert(buffer->address.offset == buffer->sparse_data.address);
          anv_free_sparse_bindings(device, &buffer->sparse_data);
       }
    
       vk_buffer_destroy(&device->vk, pAllocator, &buffer->vk);
    }
    
    VkDeviceAddress anv_GetBufferDeviceAddress(
        VkDevice                                    device,
        const VkBufferDeviceAddressInfo*            pInfo)
    {
       ANV_FROM_HANDLE(anv_buffer, buffer, pInfo->buffer);
    
       assert(!anv_address_is_null(buffer->address));
    
       return anv_address_physical(buffer->address);
    }
    
    uint64_t anv_GetBufferOpaqueCaptureAddress(
        VkDevice                                    device,
        const VkBufferDeviceAddressInfo*            pInfo)
    {
       ANV_FROM_HANDLE(anv_buffer, buffer, pInfo->buffer);
    
       return anv_address_physical(buffer->address);
    }
    
    VkResult anv_GetBufferOpaqueCaptureDescriptorDataEXT(
        VkDevice                                    device,
        const VkBufferCaptureDescriptorDataInfoEXT* pInfo,
        void*                                       pData)
    {
       ANV_FROM_HANDLE(anv_buffer, buffer, pInfo->buffer);
    
       *((uint64_t *)pData) = anv_address_physical(buffer->address);
    
       return VK_SUCCESS;
    }
    
    uint64_t anv_GetDeviceMemoryOpaqueCaptureAddress(
        VkDevice                                    device,
        const VkDeviceMemoryOpaqueCaptureAddressInfo* pInfo)
    {
       ANV_FROM_HANDLE(anv_device_memory, memory, pInfo->memory);
    
       assert(memory->bo->alloc_flags & ANV_BO_ALLOC_CLIENT_VISIBLE_ADDRESS);
    
       return intel_48b_address(memory->bo->offset);
    }
    
    void
    anv_fill_buffer_surface_state(struct anv_device *device,
                                  void *surface_state_ptr,
                                  enum isl_format format,
                                  struct isl_swizzle swizzle,
                                  isl_surf_usage_flags_t usage,
                                  struct anv_address address,
                                  uint32_t range, uint32_t stride)
    {
       if (address.bo && address.bo->alloc_flags & ANV_BO_ALLOC_PROTECTED)
          usage |= ISL_SURF_USAGE_PROTECTED_BIT;
       isl_buffer_fill_state(&device->isl_dev, surface_state_ptr,
                             .address = anv_address_physical(address),
                             .mocs = isl_mocs(&device->isl_dev, usage,
                                              address.bo && anv_bo_is_external(address.bo)),
                             .size_B = range,
                             .format = format,
                             .swizzle = swizzle,
                             .stride_B = stride);
    }