anv: Create Xe engines
authorJosé Roberto de Souza <jose.souza@intel.com>
Mon, 20 Mar 2023 18:19:13 +0000 (11:19 -0700)
committerMarge Bot <emma+marge@anholt.net>
Thu, 23 Mar 2023 13:27:39 +0000 (13:27 +0000)
Xe engine is not equal to hardware engine, it is just a submission
queue that will be scheduled in the hardware engine during process
time slice of the GPU.

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/22058>

src/intel/common/xe/intel_engine.c
src/intel/common/xe/intel_engine.h
src/intel/vulkan/anv_private.h
src/intel/vulkan/anv_queue.c
src/intel/vulkan/meson.build
src/intel/vulkan/xe/anv_queue.c [new file with mode: 0644]
src/intel/vulkan/xe/anv_queue.h [new file with mode: 0644]

index f1e2ebc..bfcf9e3 100644 (file)
@@ -47,6 +47,25 @@ xe_engine_class_to_intel(uint16_t xe)
    }
 }
 
+uint16_t
+intel_engine_class_to_xe(enum intel_engine_class intel)
+{
+   switch (intel) {
+   case INTEL_ENGINE_CLASS_RENDER:
+      return DRM_XE_ENGINE_CLASS_RENDER;
+   case INTEL_ENGINE_CLASS_COPY:
+      return DRM_XE_ENGINE_CLASS_COPY;
+   case INTEL_ENGINE_CLASS_VIDEO:
+      return DRM_XE_ENGINE_CLASS_VIDEO_DECODE;
+   case INTEL_ENGINE_CLASS_VIDEO_ENHANCE:
+      return DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE;
+   case INTEL_ENGINE_CLASS_COMPUTE:
+      return DRM_XE_ENGINE_CLASS_COMPUTE;
+   default:
+      return -1;
+   }
+}
+
 struct intel_query_engine_info *
 xe_engine_get_info(int fd)
 {
index dd3d21c..ab8faa7 100644 (file)
 
 #pragma once
 
+#include <stdint.h>
+
+#include "common/intel_engine.h"
+
 struct intel_query_engine_info *
 xe_engine_get_info(int fd);
+
+uint16_t intel_engine_class_to_xe(enum intel_engine_class intel);
index ff6b331..414a7b1 100644 (file)
@@ -1065,7 +1065,10 @@ struct anv_queue {
 
    struct intel_batch_decode_ctx *           decoder;
 
-   uint32_t                                  exec_flags;
+   union {
+      uint32_t                               exec_flags; /* i915 */
+      uint32_t                               engine_id; /* Xe */
+   };
 
    /** Synchronization object for debug purposes (DEBUG_SYNC) */
    struct vk_sync                           *sync;
index 1101c90..078211c 100644 (file)
 
 #include "anv_private.h"
 
+#include "xe/anv_queue.h"
+
+static VkResult
+anv_create_engine(struct anv_device *device,
+                  struct anv_queue *queue,
+                  const VkDeviceQueueCreateInfo *pCreateInfo)
+{
+   switch (device->info->kmd_type) {
+   case INTEL_KMD_TYPE_I915:
+      return VK_SUCCESS;
+   case INTEL_KMD_TYPE_XE:
+      return anv_xe_create_engine(device, queue, pCreateInfo);
+   default:
+      unreachable("Missing");
+      return VK_ERROR_UNKNOWN;
+   }
+}
+
+static void
+anv_destroy_engine(struct anv_queue *queue)
+{
+   struct anv_device *device = queue->device;
+   switch (device->info->kmd_type) {
+   case INTEL_KMD_TYPE_I915:
+      break;
+   case INTEL_KMD_TYPE_XE:
+      anv_xe_destroy_engine(device, queue);
+      break;
+   default:
+      unreachable("Missing");
+   }
+}
+
 VkResult
 anv_queue_init(struct anv_device *device, struct anv_queue *queue,
                uint32_t exec_flags,
@@ -36,17 +69,23 @@ anv_queue_init(struct anv_device *device, struct anv_queue *queue,
    struct anv_physical_device *pdevice = device->physical;
    VkResult result;
 
+   result = anv_create_engine(device, queue, pCreateInfo);
+   if (result != VK_SUCCESS)
+      return result;
+
    result = vk_queue_init(&queue->vk, &device->vk, pCreateInfo,
                           index_in_family);
-   if (result != VK_SUCCESS)
+   if (result != VK_SUCCESS) {
+      anv_destroy_engine(queue);
       return result;
+   }
 
    if (INTEL_DEBUG(DEBUG_SYNC)) {
       result = vk_sync_create(&device->vk,
                               &device->physical->sync_syncobj_type,
                               0, 0, &queue->sync);
       if (result != VK_SUCCESS) {
-         vk_queue_finish(&queue->vk);
+         anv_queue_finish(queue);
          return result;
       }
    }
@@ -57,7 +96,9 @@ anv_queue_init(struct anv_device *device, struct anv_queue *queue,
 
    assert(queue->vk.queue_family_index < pdevice->queue.family_count);
    queue->family = &pdevice->queue.families[queue->vk.queue_family_index];
-   queue->exec_flags = exec_flags;
+
+   if (device->info->kmd_type == INTEL_KMD_TYPE_I915)
+      queue->exec_flags = exec_flags;
 
    queue->decoder = &device->decoder[queue->vk.queue_family_index];
 
@@ -70,5 +111,6 @@ anv_queue_finish(struct anv_queue *queue)
    if (queue->sync)
       vk_sync_destroy(&queue->device->vk, queue->sync);
 
+   anv_destroy_engine(queue);
    vk_queue_finish(&queue->vk);
 }
index ce87c99..99cb110 100644 (file)
@@ -140,6 +140,8 @@ libanv_files = files(
   'xe/anv_kmd_backend.c',
   'xe/anv_device.c',
   'xe/anv_device.h',
+  'xe/anv_queue.c',
+  'xe/anv_queue.h',
   'anv_allocator.c',
   'anv_android.h',
   'anv_batch_chain.c',
diff --git a/src/intel/vulkan/xe/anv_queue.c b/src/intel/vulkan/xe/anv_queue.c
new file mode 100644 (file)
index 0000000..3bc47aa
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright © 2023 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "xe/anv_queue.h"
+
+#include "anv_private.h"
+
+#include "common/xe/intel_engine.h"
+#include "common/intel_gem.h"
+
+#include "drm-uapi/xe_drm.h"
+
+VkResult
+anv_xe_create_engine(struct anv_device *device,
+                     struct anv_queue *queue,
+                     const VkDeviceQueueCreateInfo *pCreateInfo)
+{
+   struct anv_physical_device *physical = device->physical;
+   struct anv_queue_family *queue_family =
+      &physical->queue.families[pCreateInfo->queueFamilyIndex];
+   const struct intel_query_engine_info *engines = physical->engine_info;
+   struct drm_xe_engine_class_instance *instances;
+
+   instances = vk_alloc(&device->vk.alloc,
+                        sizeof(*instances) * queue_family->queueCount, 8,
+                        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+   if (!instances)
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+   /* Build a list of all compatible HW engines */
+   uint32_t count = 0;
+   for (uint32_t i = 0; i < engines->num_engines; i++) {
+      const struct intel_engine_class_instance engine = engines->engines[i];
+      if (engine.engine_class != queue_family->engine_class)
+         continue;
+
+      instances[count].engine_class = intel_engine_class_to_xe(engine.engine_class);
+      instances[count].engine_instance = engine.engine_instance;
+      /* TODO: handle gt_id, MTL and newer platforms will have media engines
+       * in a separated gt
+       */
+      instances[count++].gt_id = 0;
+   }
+
+   assert(device->vm_id != 0);
+   /* TODO: drm_xe_engine_set_property XE_ENGINE_PROPERTY_PRIORITY */
+   struct drm_xe_engine_create create = {
+         /* Allows KMD to pick one of those engines for the submission queue */
+         .instances = (uintptr_t)instances,
+         .vm_id = device->vm_id,
+         .width = 1,
+         .num_placements = count,
+   };
+   int ret = intel_ioctl(device->fd, DRM_IOCTL_XE_ENGINE_CREATE, &create);
+   vk_free(&device->vk.alloc, instances);
+   if (ret)
+      return vk_errorf(device, VK_ERROR_UNKNOWN, "Unable to create engine");
+
+   queue->engine_id = create.engine_id;
+   return VK_SUCCESS;
+}
+
+void
+anv_xe_destroy_engine(struct anv_device *device, struct anv_queue *queue)
+{
+   struct drm_xe_engine_destroy destroy = {
+      .engine_id = queue->engine_id,
+   };
+   intel_ioctl(device->fd, DRM_IOCTL_XE_ENGINE_DESTROY, &destroy);
+}
diff --git a/src/intel/vulkan/xe/anv_queue.h b/src/intel/vulkan/xe/anv_queue.h
new file mode 100644 (file)
index 0000000..646f0ef
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright © 2023 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include "vulkan/vulkan_core.h"
+
+struct anv_device;
+struct anv_queue;
+
+VkResult
+anv_xe_create_engine(struct anv_device *device,
+                     struct anv_queue *queue,
+                     const VkDeviceQueueCreateInfo *pCreateInfo);
+void
+anv_xe_destroy_engine(struct anv_device *device, struct anv_queue *queue);