All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: Intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org,
	Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Subject: [PATCH] drm/i915: Document the Virtual Engine uAPI
Date: Fri, 11 Jun 2021 17:31:09 +0100	[thread overview]
Message-ID: <20210611163109.1085592-1-tvrtko.ursulin@linux.intel.com> (raw)

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

A little bit of documentation covering the topics of engine discovery,
context engine maps and virtual engines. It is not very detailed but
supposed to be a starting point of giving a brief high level overview of
general principles and intended use cases.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 Documentation/gpu/i915.rst | 184 +++++++++++++++++++++++++++++++++++++
 1 file changed, 184 insertions(+)

diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 42ce0196930a..8e5ab299c31f 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -335,6 +335,190 @@ for execution also include a list of all locations within buffers that
 refer to GPU-addresses so that the kernel can edit the buffer correctly.
 This process is dubbed relocation.
 
+Engine Discovery uAPI
+---------------------
+
+Engine discovery uAPI is a way of enumerating physical engines present in a GPU
+associated with an open i915 DRM file descriptor. This supersedes the old way of
+using `DRM_IOCTL_I915_GETPARAM` and engine identifiers like
+`I915_PARAM_HAS_BLT`.
+
+The need for this interface came starting with Icelake and newer GPUs, which
+started to establish a pattern of having multiple engines of a same class, where
+not all instances were always completely functionally equivalent.
+
+Entry point for this uapi is `DRM_IOCTL_I915_QUERY` with the
+`DRM_I915_QUERY_ENGINE_INFO` as the queried item id.
+
+Example for getting the list of engines:
+
+.. code-block:: C
+
+	struct drm_i915_query_engine_info *info;
+	struct drm_i915_query_item item = {
+		.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	};
+	struct drm_i915_query query = {
+		.num_items = 1,
+		.items_ptr = (uintptr_t)&item,
+	};
+	int err, i;
+
+	// First query the size of the blob we need, this needs to be large
+	// enough to hold our array of engines. The kernel will fill out the
+	// item.length for us, which is the number of bytes we need.
+	//
+	// Alternatively a large buffer can be allocated straight away enabling
+	// querying in one pass, in which case item.length should contain the
+	// length of the provided buffer.
+	err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
+	if (err) ...
+
+	info = calloc(1, item.length);
+	// Now that we allocated the required number of bytes, we call the ioctl
+	// again, this time with the data_ptr pointing to our newly allocated
+	// blob, which the kernel can then populate with info on all engines.
+	item.data_ptr = (uintptr_t)&info,
+
+	err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
+	if (err) ...
+
+	// We can now access each engine in the array
+	for (i = 0; i < info->num_engines; i++) {
+		struct drm_i915_engine_info einfo = info->engines[i];
+		u16 class = einfo.engine.class;
+		u16 instance = einfo.engine.instance;
+		....
+	}
+
+	free(info);
+
+Each of the enumerated engines, apart from being defined by its class and
+instance (see `struct i915_engine_class_instance`), also can have flags and
+capabilities defined as documented in i915_drm.h.
+
+For instance video engines which support HEVC encoding will have the
+`I915_VIDEO_CLASS_CAPABILITY_HEVC` capability bit set.
+
+Engine discovery only fully comes to its own when combined with the new way of
+addressing engines when submitting batch buffers using contexts with engine
+maps configured.
+
+Context Engine Map uAPI
+-----------------------
+
+Context engine map is a new way of addressing engines when submitting batch-
+buffers, replacing the existing way of using identifiers like `I915_EXEC_BLT`
+inside the flags field of `struct drm_i915_gem_execbuffer2`.
+
+To use it created GEM contexts need to be configured with a list of engines
+the user is intending to submit to. This is accomplished using the
+`I915_CONTEXT_PARAM_ENGINES` parameter and `struct i915_context_param_engines`.
+
+For such contexts the `I915_EXEC_RING_MASK` field becomes an index into the
+configured map.
+
+Example of creating such context and submitting against it:
+
+.. code-block:: C
+
+	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 2) = {
+		.engines = { { I915_ENGINE_CLASS_RENDER, 0 },
+			     { I915_ENGINE_CLASS_COPY, 0 } }
+	};
+	struct drm_i915_gem_context_create_ext_setparam p_engines = {
+		.base = {
+			.name = I915_CONTEXT_CREATE_EXT_SETPARAM,
+		},
+		.param = {
+			.param = I915_CONTEXT_PARAM_ENGINES,
+			.value = to_user_pointer(&engines),
+			.size = sizeof(engines),
+		},
+	};
+	struct drm_i915_gem_context_create_ext create = {
+		.flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
+		.extensions = to_user_pointer(&p_engines);
+	};
+
+	ctx_id = gem_context_create_ext(drm_fd, &create);
+
+	// We have now created a GEM context with two engines in the map:
+	// Index 0 points to rcs0 while index 1 points to bcs0. Other engines
+	// will not be accessible from this context.
+
+	...
+	execbuf.rsvd1 = ctx_id;
+	execbuf.flags = 0; // Submits to index0, which is rcs0 for this context
+	gem_execbuf(drm_fd, &execbuf);
+
+	...
+	execbuf.rsvd1 = ctx_id;
+	execbuf.flags = 1; // Submits to index0, which is bcs0 for this context
+	gem_execbuf(drm_fd, &execbuf);
+
+Virtual Engine uAPI
+-------------------
+
+Virtual engine is a concept where userspace is able to configure a set of
+physical engines, submit a batch buffer, and let the driver execute it on any
+engine from the set as it sees fit.
+
+This is primarily useful on parts which have multiple instances of a same class
+engine, like for example GT3+ Skylake parts with their two VCS engines.
+
+For instance userspace can enumerate all engines of a certain class using the
+previously described `Engine Discovery uAPI`_. After
+that userspace can create a GEM context with a placeholder slot for the virtual
+engine (using `I915_ENGINE_CLASS_INVALID` and `I915_ENGINE_CLASS_INVALID_NONE`
+for class and instance respectively) and finally using the
+`I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE` extension place a virtual engine in the
+same reserved slot.
+
+Example of creating a virtual engine and submitting a batch buffer to it:
+
+.. code-block:: C
+
+	I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(virtual, 2) = {
+		.base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE,
+		.engine_index = 0, // Place this virtual engine into engine map slot 0
+		.num_siblings = 2,
+		.engines = { { I915_ENGINE_CLASS_VIDEO, 0 },
+			     { I915_ENGINE_CLASS_VIDEO, 1 }, },
+	};
+	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 1) = {
+		.engines = { { I915_ENGINE_CLASS_INVALID,
+			       I915_ENGINE_CLASS_INVALID_NONE } },
+		.extensions = to_user_pointer(&virtual), // Chains with the load_balance extension
+	};
+	struct drm_i915_gem_context_create_ext_setparam p_engines = {
+		.base = {
+			.name = I915_CONTEXT_CREATE_EXT_SETPARAM,
+		},
+		.param = {
+			.param = I915_CONTEXT_PARAM_ENGINES,
+			.value = to_user_pointer(&engines),
+			.size = sizeof(engines),
+		},
+	};
+	struct drm_i915_gem_context_create_ext create = {
+		.flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
+		.extensions = to_user_pointer(&p_engines);
+	};
+
+	ctx_id = gem_context_create_ext(drm_fd, &create);
+
+	// Now we have created a GEM context with its engine map containing a
+	// single virtual engine. Submissions to this slot can go either to
+	// vcs0 or vcs1, depending on the load balancing algorithm used inside
+	// the driver. The load balancing is dynamic from one batch buffer to
+	// another and transparent to userspace.
+
+	...
+	execbuf.rsvd1 = ctx_id;
+	execbuf.flags = 0; // Submits to index0 which is the virtual engine
+	gem_execbuf(drm_fd, &execbuf);
+
 Locking Guidelines
 ------------------
 
-- 
2.30.2


WARNING: multiple messages have this Message-ID (diff)
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: Intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
Subject: [Intel-gfx] [PATCH] drm/i915: Document the Virtual Engine uAPI
Date: Fri, 11 Jun 2021 17:31:09 +0100	[thread overview]
Message-ID: <20210611163109.1085592-1-tvrtko.ursulin@linux.intel.com> (raw)

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

A little bit of documentation covering the topics of engine discovery,
context engine maps and virtual engines. It is not very detailed but
supposed to be a starting point of giving a brief high level overview of
general principles and intended use cases.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 Documentation/gpu/i915.rst | 184 +++++++++++++++++++++++++++++++++++++
 1 file changed, 184 insertions(+)

diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 42ce0196930a..8e5ab299c31f 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -335,6 +335,190 @@ for execution also include a list of all locations within buffers that
 refer to GPU-addresses so that the kernel can edit the buffer correctly.
 This process is dubbed relocation.
 
+Engine Discovery uAPI
+---------------------
+
+Engine discovery uAPI is a way of enumerating physical engines present in a GPU
+associated with an open i915 DRM file descriptor. This supersedes the old way of
+using `DRM_IOCTL_I915_GETPARAM` and engine identifiers like
+`I915_PARAM_HAS_BLT`.
+
+The need for this interface came starting with Icelake and newer GPUs, which
+started to establish a pattern of having multiple engines of a same class, where
+not all instances were always completely functionally equivalent.
+
+Entry point for this uapi is `DRM_IOCTL_I915_QUERY` with the
+`DRM_I915_QUERY_ENGINE_INFO` as the queried item id.
+
+Example for getting the list of engines:
+
+.. code-block:: C
+
+	struct drm_i915_query_engine_info *info;
+	struct drm_i915_query_item item = {
+		.query_id = DRM_I915_QUERY_ENGINE_INFO;
+	};
+	struct drm_i915_query query = {
+		.num_items = 1,
+		.items_ptr = (uintptr_t)&item,
+	};
+	int err, i;
+
+	// First query the size of the blob we need, this needs to be large
+	// enough to hold our array of engines. The kernel will fill out the
+	// item.length for us, which is the number of bytes we need.
+	//
+	// Alternatively a large buffer can be allocated straight away enabling
+	// querying in one pass, in which case item.length should contain the
+	// length of the provided buffer.
+	err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
+	if (err) ...
+
+	info = calloc(1, item.length);
+	// Now that we allocated the required number of bytes, we call the ioctl
+	// again, this time with the data_ptr pointing to our newly allocated
+	// blob, which the kernel can then populate with info on all engines.
+	item.data_ptr = (uintptr_t)&info,
+
+	err = ioctl(fd, DRM_IOCTL_I915_QUERY, &query);
+	if (err) ...
+
+	// We can now access each engine in the array
+	for (i = 0; i < info->num_engines; i++) {
+		struct drm_i915_engine_info einfo = info->engines[i];
+		u16 class = einfo.engine.class;
+		u16 instance = einfo.engine.instance;
+		....
+	}
+
+	free(info);
+
+Each of the enumerated engines, apart from being defined by its class and
+instance (see `struct i915_engine_class_instance`), also can have flags and
+capabilities defined as documented in i915_drm.h.
+
+For instance video engines which support HEVC encoding will have the
+`I915_VIDEO_CLASS_CAPABILITY_HEVC` capability bit set.
+
+Engine discovery only fully comes to its own when combined with the new way of
+addressing engines when submitting batch buffers using contexts with engine
+maps configured.
+
+Context Engine Map uAPI
+-----------------------
+
+Context engine map is a new way of addressing engines when submitting batch-
+buffers, replacing the existing way of using identifiers like `I915_EXEC_BLT`
+inside the flags field of `struct drm_i915_gem_execbuffer2`.
+
+To use it created GEM contexts need to be configured with a list of engines
+the user is intending to submit to. This is accomplished using the
+`I915_CONTEXT_PARAM_ENGINES` parameter and `struct i915_context_param_engines`.
+
+For such contexts the `I915_EXEC_RING_MASK` field becomes an index into the
+configured map.
+
+Example of creating such context and submitting against it:
+
+.. code-block:: C
+
+	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 2) = {
+		.engines = { { I915_ENGINE_CLASS_RENDER, 0 },
+			     { I915_ENGINE_CLASS_COPY, 0 } }
+	};
+	struct drm_i915_gem_context_create_ext_setparam p_engines = {
+		.base = {
+			.name = I915_CONTEXT_CREATE_EXT_SETPARAM,
+		},
+		.param = {
+			.param = I915_CONTEXT_PARAM_ENGINES,
+			.value = to_user_pointer(&engines),
+			.size = sizeof(engines),
+		},
+	};
+	struct drm_i915_gem_context_create_ext create = {
+		.flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
+		.extensions = to_user_pointer(&p_engines);
+	};
+
+	ctx_id = gem_context_create_ext(drm_fd, &create);
+
+	// We have now created a GEM context with two engines in the map:
+	// Index 0 points to rcs0 while index 1 points to bcs0. Other engines
+	// will not be accessible from this context.
+
+	...
+	execbuf.rsvd1 = ctx_id;
+	execbuf.flags = 0; // Submits to index0, which is rcs0 for this context
+	gem_execbuf(drm_fd, &execbuf);
+
+	...
+	execbuf.rsvd1 = ctx_id;
+	execbuf.flags = 1; // Submits to index0, which is bcs0 for this context
+	gem_execbuf(drm_fd, &execbuf);
+
+Virtual Engine uAPI
+-------------------
+
+Virtual engine is a concept where userspace is able to configure a set of
+physical engines, submit a batch buffer, and let the driver execute it on any
+engine from the set as it sees fit.
+
+This is primarily useful on parts which have multiple instances of a same class
+engine, like for example GT3+ Skylake parts with their two VCS engines.
+
+For instance userspace can enumerate all engines of a certain class using the
+previously described `Engine Discovery uAPI`_. After
+that userspace can create a GEM context with a placeholder slot for the virtual
+engine (using `I915_ENGINE_CLASS_INVALID` and `I915_ENGINE_CLASS_INVALID_NONE`
+for class and instance respectively) and finally using the
+`I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE` extension place a virtual engine in the
+same reserved slot.
+
+Example of creating a virtual engine and submitting a batch buffer to it:
+
+.. code-block:: C
+
+	I915_DEFINE_CONTEXT_ENGINES_LOAD_BALANCE(virtual, 2) = {
+		.base.name = I915_CONTEXT_ENGINES_EXT_LOAD_BALANCE,
+		.engine_index = 0, // Place this virtual engine into engine map slot 0
+		.num_siblings = 2,
+		.engines = { { I915_ENGINE_CLASS_VIDEO, 0 },
+			     { I915_ENGINE_CLASS_VIDEO, 1 }, },
+	};
+	I915_DEFINE_CONTEXT_PARAM_ENGINES(engines, 1) = {
+		.engines = { { I915_ENGINE_CLASS_INVALID,
+			       I915_ENGINE_CLASS_INVALID_NONE } },
+		.extensions = to_user_pointer(&virtual), // Chains with the load_balance extension
+	};
+	struct drm_i915_gem_context_create_ext_setparam p_engines = {
+		.base = {
+			.name = I915_CONTEXT_CREATE_EXT_SETPARAM,
+		},
+		.param = {
+			.param = I915_CONTEXT_PARAM_ENGINES,
+			.value = to_user_pointer(&engines),
+			.size = sizeof(engines),
+		},
+	};
+	struct drm_i915_gem_context_create_ext create = {
+		.flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
+		.extensions = to_user_pointer(&p_engines);
+	};
+
+	ctx_id = gem_context_create_ext(drm_fd, &create);
+
+	// Now we have created a GEM context with its engine map containing a
+	// single virtual engine. Submissions to this slot can go either to
+	// vcs0 or vcs1, depending on the load balancing algorithm used inside
+	// the driver. The load balancing is dynamic from one batch buffer to
+	// another and transparent to userspace.
+
+	...
+	execbuf.rsvd1 = ctx_id;
+	execbuf.flags = 0; // Submits to index0 which is the virtual engine
+	gem_execbuf(drm_fd, &execbuf);
+
 Locking Guidelines
 ------------------
 
-- 
2.30.2

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

             reply	other threads:[~2021-06-11 16:31 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-11 16:31 Tvrtko Ursulin [this message]
2021-06-11 16:31 ` [Intel-gfx] [PATCH] drm/i915: Document the Virtual Engine uAPI Tvrtko Ursulin
2021-06-11 16:35 ` Daniel Vetter
2021-06-11 16:35   ` [Intel-gfx] " Daniel Vetter
2021-06-11 18:15 ` [Intel-gfx] ✓ Fi.CI.BAT: success for " Patchwork
2021-06-11 20:09 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210611163109.1085592-1-tvrtko.ursulin@linux.intel.com \
    --to=tvrtko.ursulin@linux.intel.com \
    --cc=Intel-gfx@lists.freedesktop.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=tvrtko.ursulin@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.