[Mesa-dev] [PATCH] RFC: Externd IMG_context_priority with NV_context_priority_realtime

Chris Wilson chris at chris-wilson.co.uk
Fri Mar 30 14:40:13 UTC 2018


NV_context_priority_realtime
https://www.khronos.org/registry/EGL/extensions/NV/EGL_NV_context_priority_realtime.txt

    "This extension allows an EGLContext to be created with one extra
    priority level in addition to three priority levels that are part of
    EGL_IMG_context_priority extension.

    This new level has extra privileges that are not available to other three
    levels. Some of the privileges may include:
    - Allow realtime priority to only few contexts
    - Allow realtime priority only to trusted applications
    - Make sure realtime priority contexts are executed immediately
    - Preempt any current context running on GPU on submission of
      commands for realtime context"

At its most basic, it just adds an extra enum and level into the existing
context priority framework.

For i915, we are proposing to use a quality-of-service parameter in
addition to that of just a priority that usurps everyone. Due to our HW,
preemption may not be immediate and will be forced to wait until an
uncooperative process hits an arbitration point. To prevent that unduly
impacting the privileged RealTime context, we back up the preemption
request with a timeout to reset the GPU and forcibly evict the GPU hog
in order to execute the new context.

Opens:

 - How is include/EGL/eglext.h meant to be updated to include the new
   extension?

 - screen->priority_mask in freedeno_screen.c (Rob?)

References: 95ecf3df6237 ("egl: Support IMG_context_priority")
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Rob Clark <robdclark at gmail.com>
Cc: Ben Widawsky <ben at bwidawsk.net>
Cc: Emil Velikov <emli.velikov at collabora.com>
Cc: Eric Engestrom <eric.engestrom at imgtec.com>
Cc: Kenneth Graunke <kenneth at whitecape.org>
Cc: Joonas Lahtinen <joonas.lahtinen at linux.intel.com>
---
 docs/relnotes/18.1.0.html                    |  1 +
 include/EGL/eglext.h                         |  5 +++++
 include/GL/internal/dri_interface.h          |  2 ++
 src/egl/drivers/dri2/egl_dri2.c              |  3 +++
 src/egl/main/eglcontext.c                    |  3 +++
 src/egl/main/egldisplay.h                    |  7 ++++---
 src/gallium/include/pipe/p_defines.h         | 12 +++++++++---
 src/gallium/include/state_tracker/st_api.h   |  1 +
 src/gallium/state_trackers/dri/dri_context.c |  3 +++
 src/mesa/drivers/dri/i965/brw_bufmgr.c       | 19 +++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_bufmgr.h       |  3 +++
 src/mesa/drivers/dri/i965/brw_context.c      | 11 +++++++++++
 src/mesa/drivers/dri/i965/intel_screen.c     |  6 ++++++
 src/mesa/state_tracker/st_manager.c          |  2 ++
 14 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/docs/relnotes/18.1.0.html b/docs/relnotes/18.1.0.html
index 3e119078731..43f29932e39 100644
--- a/docs/relnotes/18.1.0.html
+++ b/docs/relnotes/18.1.0.html
@@ -51,6 +51,7 @@ Note: some of the new features are only available with certain drivers.
 <li>GL_EXT_shader_framebuffer_fetch on i965 on desktop GL (GLES was already supported)</li>
 <li>GL_EXT_shader_framebuffer_fetch_non_coherent on i965</li>
 <li>Disk shader cache support for i965 enabled by default</li>
+<li>EGL_NV_context_priority_realtime on i965, freedeno</li>
 </ul>
 
 <h2>Bug fixes</h2>
diff --git a/include/EGL/eglext.h b/include/EGL/eglext.h
index 2f990cc54d6..068dbb481c2 100644
--- a/include/EGL/eglext.h
+++ b/include/EGL/eglext.h
@@ -918,6 +918,11 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfi
 #define EGL_CONTEXT_PRIORITY_LOW_IMG      0x3103
 #endif /* EGL_IMG_context_priority */
 
+#ifndef EGL_NV_context_priority_realtime
+#define EGL_NV_context_priority 1_realtime
+#define EGL_CONTEXT_PRIORITY_REALTIME_NV  0x3357
+#endif /* EGL_NV_context_priority_realtime */
+
 #ifndef EGL_IMG_image_plane_attribs
 #define EGL_IMG_image_plane_attribs 1
 #define EGL_NATIVE_BUFFER_MULTIPLANE_SEPARATE_IMG 0x3105
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 4f4795c7ae3..8be0d89e6a6 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -1129,6 +1129,7 @@ struct __DRIdri2LoaderExtensionRec {
 #define __DRI_CTX_PRIORITY_LOW			0
 #define __DRI_CTX_PRIORITY_MEDIUM		1
 #define __DRI_CTX_PRIORITY_HIGH			2
+#define __DRI_CTX_PRIORITY_REALTIME		3
 
 /**
  * \name Context release behaviors.
@@ -1855,6 +1856,7 @@ typedef struct __DRIDriverVtableExtensionRec {
 #define   __DRI2_RENDERER_HAS_CONTEXT_PRIORITY_LOW            (1 << 0)
 #define   __DRI2_RENDERER_HAS_CONTEXT_PRIORITY_MEDIUM         (1 << 1)
 #define   __DRI2_RENDERER_HAS_CONTEXT_PRIORITY_HIGH           (1 << 2)
+#define   __DRI2_RENDERER_HAS_CONTEXT_PRIORITY_REALTIME       (1 << 3)
 
 typedef struct __DRI2rendererQueryExtensionRec __DRI2rendererQueryExtension;
 struct __DRI2rendererQueryExtensionRec {
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 45d0c7275c5..4bed1aa2c6f 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1189,6 +1189,9 @@ dri2_fill_context_attribs(struct dri2_egl_context *dri2_ctx,
       unsigned val;
 
       switch (dri2_ctx->base.ContextPriority) {
+      case EGL_CONTEXT_PRIORITY_REALTIME_NV:
+         val = __DRI_CTX_PRIORITY_REALTIME;
+         break;
       case EGL_CONTEXT_PRIORITY_HIGH_IMG:
          val = __DRI_CTX_PRIORITY_HIGH;
          break;
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index 3e5d8ad97bf..1794e8d191d 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -347,6 +347,9 @@ _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
             int bit;
 
             switch (val) {
+            case EGL_CONTEXT_PRIORITY_REALTIME_NV:
+               bit = __EGL_CONTEXT_PRIORITY_REALTIME_BIT;
+               break;
             case EGL_CONTEXT_PRIORITY_HIGH_IMG:
                bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
                break;
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index d7e51991a45..dd453536837 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -108,9 +108,10 @@ struct _egl_extensions
    EGLBoolean EXT_swap_buffers_with_damage;
 
    unsigned int IMG_context_priority;
-#define  __EGL_CONTEXT_PRIORITY_LOW_BIT    0
-#define  __EGL_CONTEXT_PRIORITY_MEDIUM_BIT 1
-#define  __EGL_CONTEXT_PRIORITY_HIGH_BIT   2
+#define  __EGL_CONTEXT_PRIORITY_LOW_BIT      0
+#define  __EGL_CONTEXT_PRIORITY_MEDIUM_BIT   1
+#define  __EGL_CONTEXT_PRIORITY_HIGH_BIT     2
+#define  __EGL_CONTEXT_PRIORITY_REALTIME_BIT 3
 
    EGLBoolean KHR_cl_event2;
    EGLBoolean KHR_config_attribs;
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index c4ae0532060..8a18ac747a3 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -401,6 +401,11 @@ enum pipe_flush_flags
  */
 #define PIPE_CONTEXT_LOW_PRIORITY      (1 << 5)
 
+/**
+ * Create a realtime priority context.
+ */
+#define PIPE_CONTEXT_REALTIME_PRIORITY (1 << 6)
+
 /**
  * Flags for pipe_context::memory_barrier.
  */
@@ -804,9 +809,10 @@ enum pipe_cap
  *
  * Note that these match __DRI2_RENDER_HAS_CONTEXT_PRIORITY_*
  */
-#define PIPE_CONTEXT_PRIORITY_LOW     (1 << 0)
-#define PIPE_CONTEXT_PRIORITY_MEDIUM  (1 << 1)
-#define PIPE_CONTEXT_PRIORITY_HIGH    (1 << 2)
+#define PIPE_CONTEXT_PRIORITY_LOW      (1 << 0)
+#define PIPE_CONTEXT_PRIORITY_MEDIUM   (1 << 1)
+#define PIPE_CONTEXT_PRIORITY_HIGH     (1 << 2)
+#define PIPE_CONTEXT_PRIORITY_REALTIME (1 << 3)
 
 #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0)
 #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600 (1 << 1)
diff --git a/src/gallium/include/state_tracker/st_api.h b/src/gallium/include/state_tracker/st_api.h
index ec6e7844b87..d0dbffa0e1d 100644
--- a/src/gallium/include/state_tracker/st_api.h
+++ b/src/gallium/include/state_tracker/st_api.h
@@ -94,6 +94,7 @@ enum st_api_feature
 #define ST_CONTEXT_FLAG_RELEASE_NONE	    (1 << 5)
 #define ST_CONTEXT_FLAG_HIGH_PRIORITY       (1 << 6)
 #define ST_CONTEXT_FLAG_LOW_PRIORITY        (1 << 7)
+#define ST_CONTEXT_FLAG_REALTIME_PRIORITY   (1 << 8)
 
 /**
  * Reasons that context creation might fail.
diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c
index fb307337a90..b9e0e108142 100644
--- a/src/gallium/state_trackers/dri/dri_context.c
+++ b/src/gallium/state_trackers/dri/dri_context.c
@@ -122,6 +122,9 @@ dri_create_context(gl_api api, const struct gl_config * visual,
       case __DRI_CTX_PRIORITY_HIGH:
          attribs.flags |= ST_CONTEXT_FLAG_HIGH_PRIORITY;
          break;
+      case __DRI_CTX_PRIORITY_REALTIME:
+         attribs.flags |= ST_CONTEXT_FLAG_REALTIME_PRIORITY;
+         break;
       default:
          break;
       }
diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.c b/src/mesa/drivers/dri/i965/brw_bufmgr.c
index 8ba915b179a..b080c4c58f1 100644
--- a/src/mesa/drivers/dri/i965/brw_bufmgr.c
+++ b/src/mesa/drivers/dri/i965/brw_bufmgr.c
@@ -1351,6 +1351,25 @@ brw_hw_context_set_priority(struct brw_bufmgr *bufmgr,
    return err;
 }
 
+int
+brw_hw_context_set_preempt_timeout(struct brw_bufmgr *bufmgr,
+				   uint32_t ctx_id,
+				   uint64_t timeout_ns)
+{
+   struct drm_i915_gem_context_param p = {
+      .ctx_id = ctx_id,
+      .param = 7, /* I915_CONTEXT_PARAM_PREEMPT_TIMEOUT, */
+      .value = timeout_ns,
+   };
+   int err;
+
+   err = 0;
+   if (drmIoctl(bufmgr->fd, DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &p))
+      err = -errno;
+
+   return err;
+}
+
 void
 brw_destroy_hw_context(struct brw_bufmgr *bufmgr, uint32_t ctx_id)
 {
diff --git a/src/mesa/drivers/dri/i965/brw_bufmgr.h b/src/mesa/drivers/dri/i965/brw_bufmgr.h
index 68f5e0c2c85..a493b7018af 100644
--- a/src/mesa/drivers/dri/i965/brw_bufmgr.h
+++ b/src/mesa/drivers/dri/i965/brw_bufmgr.h
@@ -316,6 +316,9 @@ uint32_t brw_create_hw_context(struct brw_bufmgr *bufmgr);
 int brw_hw_context_set_priority(struct brw_bufmgr *bufmgr,
                                 uint32_t ctx_id,
                                 int priority);
+int brw_hw_context_set_preempt_timeout(struct brw_bufmgr *bufmgr,
+				       uint32_t ctx_id,
+				       uint64_t timeout_ns);
 
 void brw_destroy_hw_context(struct brw_bufmgr *bufmgr, uint32_t ctx_id);
 
diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
index 2e961a1ef6e..9b84a29d4a2 100644
--- a/src/mesa/drivers/dri/i965/brw_context.c
+++ b/src/mesa/drivers/dri/i965/brw_context.c
@@ -1013,6 +1013,9 @@ brwCreateContext(gl_api api,
          case __DRI_CTX_PRIORITY_HIGH:
             hw_priority = GEN_CONTEXT_HIGH_PRIORITY;
             break;
+         case __DRI_CTX_PRIORITY_REALTIME:
+            hw_priority = GEN_CONTEXT_REALTIME_PRIORITY;
+            break;
          }
       }
       if (hw_priority != I915_CONTEXT_DEFAULT_PRIORITY &&
@@ -1023,6 +1026,14 @@ brwCreateContext(gl_api api,
          intelDestroyContext(driContextPriv);
          return false;
       }
+      if (hw_priority >= GEN_CONTEXT_REALTIME_PRIORITY &&
+          brw_hw_context_set_preempt_timeout(brw->bufmgr, brw->hw_ctx,
+					     8 * 1000 * 1000 /* 8ms */)) {
+         fprintf(stderr,
+		 "Failed to set preempt timeout for RT hardware context.\n");
+         intelDestroyContext(driContextPriv);
+         return false;
+      }
    }
 
    if (brw_init_pipe_control(brw, devinfo)) {
diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c
index dcb98dab03a..a84165ebaff 100644
--- a/src/mesa/drivers/dri/i965/intel_screen.c
+++ b/src/mesa/drivers/dri/i965/intel_screen.c
@@ -1463,6 +1463,12 @@ brw_query_renderer_integer(__DRIscreen *dri_screen,
       return 0;
    case __DRI2_RENDERER_HAS_CONTEXT_PRIORITY:
       value[0] = 0;
+      if (brw_hw_context_set_priority(screen->bufmgr,
+				      0, GEN_CONTEXT_REALTIME_PRIORITY) == 0 &&
+	  brw_hw_context_set_preempt_timeout(screen->bufmgr, 0, 10 * 1000)) {
+	 value[0] |= __DRI2_RENDERER_HAS_CONTEXT_PRIORITY_REALTIME;
+	 brw_hw_context_set_preempt_timeout(screen->bufmgr, 0, 0);
+      }
       if (brw_hw_context_set_priority(screen->bufmgr,
 				      0, GEN_CONTEXT_HIGH_PRIORITY) == 0)
          value[0] |= __DRI2_RENDERER_HAS_CONTEXT_PRIORITY_HIGH;
diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c
index d6901c96eb0..f383bdef6c3 100644
--- a/src/mesa/state_tracker/st_manager.c
+++ b/src/mesa/state_tracker/st_manager.c
@@ -884,6 +884,8 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
       ctx_flags |= PIPE_CONTEXT_LOW_PRIORITY;
    else if (attribs->flags & ST_CONTEXT_FLAG_HIGH_PRIORITY)
       ctx_flags |= PIPE_CONTEXT_HIGH_PRIORITY;
+   else if (attribs->flags & ST_CONTEXT_FLAG_REALTIME_PRIORITY)
+      ctx_flags |= PIPE_CONTEXT_REALTIME_PRIORITY;
 
    pipe = smapi->screen->context_create(smapi->screen, NULL, ctx_flags);
    if (!pipe) {
-- 
2.16.3



More information about the mesa-dev mailing list