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 515a2c1db7acf03f6a228b0cf0168a12daf544ed..f35b3e66b215ecdc0d3d6e3d47e91ae0763b3bbd 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 e9e581472e8c23dafff15764de3e371ce4813afb..0cf2bc3ce5e4f8187366b4bdb3c9f46936196caa 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 f4bff78e91aafe31bc848fa69d89af2ac5ae6f00..76c5f2f27e17956407e6eec53795d8cbe44c4c29 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 bec54560470a34fd0e4140bdba4f1d79cdf61d49..ff424053df0001204175bcc0ef45045cf2e7d55a 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 0546958d6502c91f1a8544c601dbed02beaf8dee..82917a88f4b4ed1059df9dd43ca19b6f3fd93a97 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 2053c81b6edeb37fd129183f4d21ccf7f1d119ef..46c4939e4da1f714de79e9cc9d209f9a7fed72c2 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,