anv: Fix vm bind of imported buffers
authorJosé Roberto de Souza <jose.souza@intel.com>
Tue, 11 Apr 2023 15:36:42 +0000 (08:36 -0700)
committerMarge Bot <emma+marge@anholt.net>
Wed, 12 Apr 2023 10:05:32 +0000 (10:05 +0000)
Imported buffers may be created in a device with different
memory alignment and this can cause vm bind to fail because bo
size can be smaller than the calculated vm bind range using the
importer device memory alignment.

So here adding actual_size to anv_bo, this will be set with the actual
size of the bo allocated by kmd for bos allocate in the current device.
For other bo the lseek or the Vulkan API size will be used.

Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22219>

src/intel/vulkan/anv_allocator.c
src/intel/vulkan/anv_gem_stubs.c
src/intel/vulkan/anv_kmd_backend.h
src/intel/vulkan/anv_private.h
src/intel/vulkan/i915/anv_kmd_backend.c
src/intel/vulkan/xe/anv_kmd_backend.c

index 515a2c1..f35b3e6 100644 (file)
@@ -1485,10 +1485,12 @@ anv_device_alloc_bo(struct anv_device *device,
       regions[nregions++] = device->physical->sys.region;
    }
 
+   uint64_t actual_size;
    uint32_t gem_handle = device->kmd_backend->gem_create(device, regions,
                                                          nregions,
                                                          size + ccs_size,
-                                                         alloc_flags);
+                                                         alloc_flags,
+                                                         &actual_size);
    if (gem_handle == 0)
       return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
 
@@ -1499,6 +1501,7 @@ anv_device_alloc_bo(struct anv_device *device,
       .offset = -1,
       .size = size,
       ._ccs_size = ccs_size,
+      .actual_size = actual_size,
       .flags = bo_flags,
       .is_external = (alloc_flags & ANV_BO_ALLOC_EXTERNAL),
       .has_client_visible_address =
@@ -1666,6 +1669,7 @@ anv_device_import_bo_from_host_ptr(struct anv_device *device,
          .refcount = 1,
          .offset = -1,
          .size = size,
+         .actual_size = size,
          .map = host_ptr,
          .flags = bo_flags,
          .is_external = true,
@@ -1791,6 +1795,7 @@ anv_device_import_bo(struct anv_device *device,
          .refcount = 1,
          .offset = -1,
          .size = size,
+         .actual_size = size,
          .flags = bo_flags,
          .is_external = true,
          .has_client_visible_address =
index e9e5814..0cf2bc3 100644 (file)
@@ -37,7 +37,8 @@ static uint32_t
 stub_gem_create(struct anv_device *device,
                 const struct intel_memory_class_instance **regions,
                 uint16_t num_regions, uint64_t size,
-                enum anv_bo_alloc_flags alloc_flags)
+                enum anv_bo_alloc_flags alloc_flags,
+                uint64_t *actual_size)
 {
    int fd = os_create_anonymous_file(size, "fake bo");
    if (fd == -1)
@@ -45,6 +46,7 @@ stub_gem_create(struct anv_device *device,
 
    assert(fd != 0);
 
+   *actual_size = size;
    return fd;
 }
 
index f4bff78..76c5f2f 100644 (file)
@@ -47,7 +47,8 @@ struct anv_kmd_backend {
    uint32_t (*gem_create)(struct anv_device *device,
                           const struct intel_memory_class_instance **regions,
                           uint16_t num_regions, uint64_t size,
-                          enum anv_bo_alloc_flags alloc_flags);
+                          enum anv_bo_alloc_flags alloc_flags,
+                          uint64_t *actual_size);
    void (*gem_close)(struct anv_device *device, uint32_t handle);
    /* Returns MAP_FAILED on error */
    void *(*gem_mmap)(struct anv_device *device, struct anv_bo *bo,
index bec5456..ff42405 100644 (file)
@@ -506,6 +506,11 @@ struct anv_bo {
     */
    uint32_t _ccs_size;
 
+   /* The actual size of bo allocated by kmd, basically:
+    * align(size + _ccs_size, mem_alignment)
+    */
+   uint64_t actual_size;
+
    /** Flags to pass to the kernel through drm_i915_exec_object2::flags */
    uint32_t flags;
 
index 0546958..82917a8 100644 (file)
@@ -33,7 +33,8 @@ static uint32_t
 i915_gem_create(struct anv_device *device,
                 const struct intel_memory_class_instance **regions,
                 uint16_t num_regions, uint64_t size,
-                enum anv_bo_alloc_flags alloc_flags)
+                enum anv_bo_alloc_flags alloc_flags,
+                uint64_t *actual_size)
 {
    if (unlikely(!device->info->mem.use_class_instance)) {
       assert(num_regions == 1 &&
@@ -44,6 +45,8 @@ i915_gem_create(struct anv_device *device,
       };
       if (intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create))
          return 0;
+
+      *actual_size = gem_create.size;
       return gem_create.handle;
    }
 
@@ -75,6 +78,7 @@ i915_gem_create(struct anv_device *device,
    if (intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &gem_create))
       return 0;
 
+   *actual_size = gem_create.size;
    return gem_create.handle;
 }
 
index 2053c81..46c4939 100644 (file)
@@ -34,7 +34,8 @@ static uint32_t
 xe_gem_create(struct anv_device *device,
               const struct intel_memory_class_instance **regions,
               uint16_t regions_count, uint64_t size,
-              enum anv_bo_alloc_flags alloc_flags)
+              enum anv_bo_alloc_flags alloc_flags,
+              uint64_t *actual_size)
 {
    struct drm_xe_gem_create gem_create = {
      /* From xe_drm.h: If a VM is specified, this BO must:
@@ -51,6 +52,7 @@ xe_gem_create(struct anv_device *device,
    if (intel_ioctl(device->fd, DRM_IOCTL_XE_GEM_CREATE, &gem_create))
       return 0;
 
+   *actual_size = gem_create.size;
    return gem_create.handle;
 }
 
@@ -95,7 +97,7 @@ xe_gem_vm_bind_op(struct anv_device *device, struct anv_bo *bo, uint32_t op)
       .num_binds = 1,
       .bind.obj = op == XE_VM_BIND_OP_UNMAP ? 0 : bo->gem_handle,
       .bind.obj_offset = 0,
-      .bind.range = align64(bo->size + bo->_ccs_size, device->info->mem_alignment),
+      .bind.range = bo->actual_size,
       .bind.addr = intel_48b_address(bo->offset),
       .bind.op = op,
       .num_syncs = 1,