anv: Move i915 handling of imported bos bo_flags
authorJosé Roberto de Souza <jose.souza@intel.com>
Mon, 4 Sep 2023 18:20:27 +0000 (11:20 -0700)
committerJosé Roberto de Souza <jose.souza@intel.com>
Wed, 13 Sep 2023 20:10:59 +0000 (13:10 -0700)
Imported bos already imported need special handling in i915.
That handling was moved to
anv_i915_gem_import_bo_alloc_flags_to_bo_flags() as the number of
imported bos is low.

Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Reviewed-by: Sagar Ghuge <sagar.ghuge@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25044>

src/intel/vulkan/anv_allocator.c
src/intel/vulkan/anv_gem.c
src/intel/vulkan/anv_gem_stubs.c
src/intel/vulkan/anv_private.h
src/intel/vulkan/i915/anv_gem.c
src/intel/vulkan/i915/anv_gem.h

index c554db8..edae4b0 100644 (file)
@@ -1683,8 +1683,6 @@ anv_device_import_bo(struct anv_device *device,
           (device->physical->has_implicit_ccs && device->info->has_aux_map));
 
    struct anv_bo_cache *cache = &device->bo_cache;
-   const uint32_t bo_flags =
-         device->kmd_backend->bo_alloc_flags_to_bo_flags(device, alloc_flags);
 
    pthread_mutex_lock(&cache->mutex);
 
@@ -1695,46 +1693,17 @@ anv_device_import_bo(struct anv_device *device,
    }
 
    struct anv_bo *bo = anv_device_lookup_bo(device, gem_handle);
-   if (bo->refcount > 0) {
-      /* We have to be careful how we combine flags so that it makes sense.
-       * Really, though, if we get to this case and it actually matters, the
-       * client has imported a BO twice in different ways and they get what
-       * they have coming.
-       */
-      uint64_t new_flags = 0;
-      new_flags |= (bo->flags | bo_flags) & EXEC_OBJECT_WRITE;
-      new_flags |= (bo->flags & bo_flags) & EXEC_OBJECT_ASYNC;
-      new_flags |= (bo->flags & bo_flags) & EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
-      new_flags |= (bo->flags | bo_flags) & EXEC_OBJECT_PINNED;
-      new_flags |= (bo->flags | bo_flags) & EXEC_OBJECT_CAPTURE;
-
-      /* It's theoretically possible for a BO to get imported such that it's
-       * both pinned and not pinned.  The only way this can happen is if it
-       * gets imported as both a semaphore and a memory object and that would
-       * be an application error.  Just fail out in that case.
-       */
-      if ((bo->flags & EXEC_OBJECT_PINNED) !=
-          (bo_flags & EXEC_OBJECT_PINNED)) {
-         pthread_mutex_unlock(&cache->mutex);
-         return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                          "The same BO was imported two different ways");
-      }
 
-      /* It's also theoretically possible that someone could export a BO from
-       * one heap and import it into another or to import the same BO into two
-       * different heaps.  If this happens, we could potentially end up both
-       * allowing and disallowing 48-bit addresses.  There's not much we can
-       * do about it if we're pinning so we just throw an error and hope no
-       * app is actually that stupid.
-       */
-      if ((new_flags & EXEC_OBJECT_PINNED) &&
-          (bo->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) !=
-          (bo_flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS)) {
-         pthread_mutex_unlock(&cache->mutex);
-         return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
-                          "The same BO was imported on two different heaps");
-      }
+   uint32_t bo_flags;
+   VkResult result = anv_gem_import_bo_alloc_flags_to_bo_flags(device, bo,
+                                                               alloc_flags,
+                                                               &bo_flags);
+   if (result != VK_SUCCESS) {
+      pthread_mutex_unlock(&cache->mutex);
+      return result;
+   }
 
+   if (bo->refcount > 0) {
       if (bo->has_client_visible_address !=
           ((alloc_flags & ANV_BO_ALLOC_CLIENT_VISIBLE_ADDRESS) != 0)) {
          pthread_mutex_unlock(&cache->mutex);
@@ -1750,8 +1719,6 @@ anv_device_import_bo(struct anv_device *device,
                           "addresses");
       }
 
-      bo->flags = new_flags;
-
       __sync_fetch_and_add(&bo->refcount, 1);
    } else {
       struct anv_bo new_bo = {
@@ -1759,7 +1726,6 @@ anv_device_import_bo(struct anv_device *device,
          .gem_handle = gem_handle,
          .refcount = 1,
          .offset = -1,
-         .flags = bo_flags,
          .is_external = true,
          .has_client_visible_address =
             (alloc_flags & ANV_BO_ALLOC_CLIENT_VISIBLE_ADDRESS) != 0,
@@ -1792,6 +1758,8 @@ anv_device_import_bo(struct anv_device *device,
       *bo = new_bo;
    }
 
+   bo->flags = bo_flags;
+
    pthread_mutex_unlock(&cache->mutex);
    *bo_out = bo;
 
index 1fe5bdf..5514149 100644 (file)
@@ -133,6 +133,26 @@ anv_gem_fd_to_handle(struct anv_device *device, int fd)
    return args.handle;
 }
 
+VkResult
+anv_gem_import_bo_alloc_flags_to_bo_flags(struct anv_device *device,
+                                          struct anv_bo *bo,
+                                          enum anv_bo_alloc_flags alloc_flags,
+                                          uint32_t *bo_flags)
+{
+   switch (device->info->kmd_type) {
+   case INTEL_KMD_TYPE_I915:
+      return anv_i915_gem_import_bo_alloc_flags_to_bo_flags(device, bo,
+                                                            alloc_flags,
+                                                            bo_flags);
+   case INTEL_KMD_TYPE_XE:
+      *bo_flags = device->kmd_backend->bo_alloc_flags_to_bo_flags(device, alloc_flags);
+      return VK_SUCCESS;
+   default:
+      unreachable("missing");
+      return VK_ERROR_UNKNOWN;
+   }
+}
+
 const struct anv_kmd_backend *anv_stub_kmd_backend_get(void)
 {
    return NULL;
index 524fcee..9e6ab8c 100644 (file)
@@ -157,6 +157,15 @@ anv_gem_fd_to_handle(struct anv_device *device, int fd)
    unreachable("Unused");
 }
 
+VkResult
+anv_gem_import_bo_alloc_flags_to_bo_flags(struct anv_device *device,
+                                          struct anv_bo *bo,
+                                          enum anv_bo_alloc_flags alloc_flags,
+                                          uint32_t *bo_flags)
+{
+   return VK_SUCCESS;
+}
+
 static int
 stub_vm_bind(struct anv_device *device, int num_binds,
              struct anv_vm_bind *binds)
index 6265d2f..1e024a8 100644 (file)
@@ -1793,6 +1793,11 @@ int anv_gem_handle_to_fd(struct anv_device *device, uint32_t gem_handle);
 uint32_t anv_gem_fd_to_handle(struct anv_device *device, int fd);
 int anv_gem_set_context_param(int fd, uint32_t context, uint32_t param,
                               uint64_t value);
+VkResult
+anv_gem_import_bo_alloc_flags_to_bo_flags(struct anv_device *device,
+                                          struct anv_bo *bo,
+                                          enum anv_bo_alloc_flags alloc_flags,
+                                          uint32_t *bo_flags);
 
 uint64_t anv_vma_alloc(struct anv_device *device,
                        uint64_t size, uint64_t align,
index cf727b7..a159844 100644 (file)
@@ -85,3 +85,55 @@ anv_i915_gem_wait(struct anv_device *device, uint32_t gem_handle,
 
    return ret;
 }
+
+VkResult
+anv_i915_gem_import_bo_alloc_flags_to_bo_flags(struct anv_device *device,
+                                               struct anv_bo *bo,
+                                               enum anv_bo_alloc_flags alloc_flags,
+                                               uint32_t *out_bo_flags)
+{
+   const uint32_t bo_flags =
+         device->kmd_backend->bo_alloc_flags_to_bo_flags(device, alloc_flags);
+   if (bo->refcount == 0) {
+      *out_bo_flags = bo_flags;
+      return VK_SUCCESS;
+   }
+
+   /* We have to be careful how we combine flags so that it makes sense.
+    * Really, though, if we get to this case and it actually matters, the
+    * client has imported a BO twice in different ways and they get what
+    * they have coming.
+    */
+   uint32_t new_flags = 0;
+   new_flags |= (bo->flags | bo_flags) & EXEC_OBJECT_WRITE;
+   new_flags |= (bo->flags & bo_flags) & EXEC_OBJECT_ASYNC;
+   new_flags |= (bo->flags & bo_flags) & EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
+   new_flags |= (bo->flags | bo_flags) & EXEC_OBJECT_PINNED;
+   new_flags |= (bo->flags | bo_flags) & EXEC_OBJECT_CAPTURE;
+
+   /* It's theoretically possible for a BO to get imported such that it's
+    * both pinned and not pinned.  The only way this can happen is if it
+    * gets imported as both a semaphore and a memory object and that would
+    * be an application error.  Just fail out in that case.
+    */
+   if ((bo->flags & EXEC_OBJECT_PINNED) !=
+       (bo_flags & EXEC_OBJECT_PINNED))
+      return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
+                       "The same BO was imported two different ways");
+
+   /* It's also theoretically possible that someone could export a BO from
+    * one heap and import it into another or to import the same BO into two
+    * different heaps.  If this happens, we could potentially end up both
+    * allowing and disallowing 48-bit addresses.  There's not much we can
+    * do about it if we're pinning so we just throw an error and hope no
+    * app is actually that stupid.
+    */
+   if ((new_flags & EXEC_OBJECT_PINNED) &&
+       (bo->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) !=
+       (bo_flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS))
+      return vk_errorf(device, VK_ERROR_INVALID_EXTERNAL_HANDLE,
+                       "The same BO was imported on two different heaps");
+
+   *out_bo_flags = new_flags;
+   return VK_SUCCESS;
+}
index 669934c..bf3713f 100644 (file)
 
 #include <stdint.h>
 
+#include "vulkan/vulkan_core.h"
+
+struct anv_bo;
 struct anv_device;
+enum anv_bo_alloc_flags;
 
 int anv_i915_gem_get_tiling(struct anv_device *device, uint32_t gem_handle);
 int anv_i915_gem_set_tiling(struct anv_device *device, uint32_t gem_handle,
@@ -32,3 +36,8 @@ int anv_i915_gem_set_tiling(struct anv_device *device, uint32_t gem_handle,
 
 int anv_i915_gem_wait(struct anv_device *device, uint32_t gem_handle,
                       int64_t *timeout_ns);
+
+VkResult anv_i915_gem_import_bo_alloc_flags_to_bo_flags(struct anv_device *device,
+                                                        struct anv_bo *bo,
+                                                        enum anv_bo_alloc_flags alloc_flags,
+                                                        uint32_t *out_bo_flags);