gallium: implement the backend of threaded GL dispatch
authorMarek Olšák <marek.olsak@amd.com>
Sun, 5 Feb 2017 00:20:51 +0000 (01:20 +0100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Thu, 16 Mar 2017 03:14:19 +0000 (14:14 +1100)
Acked-by: Timothy Arceri <tarceri@itsqueeze.com>
Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
Tested-by: Mike Lothian <mike@fireburn.co.uk>
src/gallium/include/state_tracker/st_api.h
src/gallium/state_trackers/dri/dri_context.c
src/gallium/state_trackers/dri/dri_drawable.c
src/gallium/state_trackers/dri/dri_screen.c
src/mesa/drivers/dri/common/xmlpool/t_options.h
src/mesa/state_tracker/st_context.c
src/mesa/state_tracker/st_manager.c

index a9997744cde79dc54174edf45f4d81fd3d495570..bf9a7e95d7cb3b5260ea90cf1f4ce390c6311827 100644 (file)
@@ -417,6 +417,19 @@ struct st_context_iface
     */
    boolean (*get_resource_for_egl_image)(struct st_context_iface *stctxi,
                                          struct st_context_resource *stres);
+
+   /**
+    * Start the thread if the API has a worker thread.
+    * Called after the context has been created and fully initialized on both
+    * sides (e.g. st/mesa and st/dri).
+    */
+   void (*start_thread)(struct st_context_iface *stctxi);
+
+   /**
+    * If the API is multithreaded, wait for all queued commands to complete.
+    * Called from the main thread.
+    */
+   void (*thread_finish)(struct st_context_iface *stctxi);
 };
 
 
@@ -454,6 +467,12 @@ struct st_manager
     */
    int (*get_param)(struct st_manager *smapi,
                     enum st_manager_param param);
+
+   /**
+    * Call the loader function setBackgroundContext. Called from the worker
+    * thread.
+    */
+   void (*set_background_context)(struct st_context_iface *stctxi);
 };
 
 /**
index 3d8af65ca6160b7bcfbd72d8405033bd21b86c77..91d2d1fbbe87c5bc4a982f7393c205e1a2dea5b9 100644 (file)
@@ -156,6 +156,13 @@ dri_create_context(gl_api api, const struct gl_config * visual,
       ctx->hud = hud_create(ctx->st->pipe, ctx->st->cso_context);
    }
 
+   /* Do this last. */
+   if (ctx->st->start_thread &&
+       /* the driver loader must implement this */
+       screen->sPriv->dri2.backgroundCallable &&
+       driQueryOptionb(&screen->optionCache, "mesa_glthread"))
+      ctx->st->start_thread(ctx->st);
+
    *error = __DRI_CTX_ERROR_SUCCESS;
    return GL_TRUE;
 
@@ -222,6 +229,9 @@ dri_make_current(__DRIcontext * cPriv,
    struct dri_drawable *read = dri_drawable(driReadPriv);
    struct st_context_iface *old_st = ctx->stapi->get_current(ctx->stapi);
 
+   if (old_st && old_st->thread_finish)
+      old_st->thread_finish(old_st);
+
    /* Flush the old context here so we don't have to flush on unbind() */
    if (old_st && old_st != ctx->st)
       old_st->flush(old_st, ST_FLUSH_FRONT, NULL);
index fd3b458de6c5b6021b7d874bade1dcef1fb51191..3c2e3075249e07f0590153a7072a234451ec9641 100644 (file)
@@ -217,9 +217,13 @@ dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target,
                     GLint format, __DRIdrawable *dPriv)
 {
    struct dri_context *ctx = dri_context(pDRICtx);
+   struct st_context_iface *st = ctx->st;
    struct dri_drawable *drawable = dri_drawable(dPriv);
    struct pipe_resource *pt;
 
+   if (st->thread_finish)
+      st->thread_finish(st);
+
    dri_drawable_validate_att(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT);
 
    /* Use the pipe resource associated with the X drawable */
@@ -453,6 +457,8 @@ dri_flush(__DRIcontext *cPriv,
    }
 
    st = ctx->st;
+   if (st->thread_finish)
+      st->thread_finish(st);
 
    if (drawable) {
       /* prevent recursion */
index 9b37dff67781e2387193426e48a487dd2cd771c4..799a2649b04126a84f1085ec75437397c2821e23 100644 (file)
@@ -33,6 +33,7 @@
 #include "xmlpool.h"
 
 #include "dri_screen.h"
+#include "dri_context.h"
 
 #include "util/u_inlines.h"
 #include "pipe/p_screen.h"
@@ -53,6 +54,10 @@ const __DRIconfigOptionsExtension gallium_config_options = {
    .xml =
 
    DRI_CONF_BEGIN
+      DRI_CONF_SECTION_PERFORMANCE
+         DRI_CONF_MESA_GLTHREAD("false")
+      DRI_CONF_SECTION_END
+
       DRI_CONF_SECTION_QUALITY
          DRI_CONF_FORCE_S3TC_ENABLE("false")
          DRI_CONF_PP_CELSHADE(0)
@@ -432,6 +437,21 @@ dri_postprocessing_init(struct dri_screen *screen)
    }
 }
 
+static void
+dri_set_background_context(struct st_context_iface *st)
+{
+   struct dri_context *ctx = (struct dri_context *)st->st_manager_private;
+   const __DRIbackgroundCallableExtension *backgroundCallable =
+      ctx->sPriv->dri2.backgroundCallable;
+
+   /* Note: Mesa will only call this function if GL multithreading is enabled
+    * We only do that if the loader exposed the __DRI_BACKGROUND_CALLABLE
+    * extension. So we know that backgroundCallable is not NULL.
+    */
+   assert(backgroundCallable);
+   backgroundCallable->setBackgroundContext(ctx->cPriv->loaderPrivate);
+}
+
 const __DRIconfig **
 dri_init_screen_helper(struct dri_screen *screen,
                        struct pipe_screen *pscreen,
@@ -440,6 +460,7 @@ dri_init_screen_helper(struct dri_screen *screen,
    screen->base.screen = pscreen;
    screen->base.get_egl_image = dri_get_egl_image;
    screen->base.get_param = dri_get_param;
+   screen->base.set_background_context = dri_set_background_context;
 
    screen->st_api = st_gl_api_create();
    if (!screen->st_api)
index f200093177deed2c667fde167c27bacf21197b7b..c7c658d0aac5a6997f564b1c023bcb2095aa3aab 100644 (file)
@@ -313,6 +313,10 @@ DRI_CONF_OPT_BEGIN_V(texture_heaps,enum,def,"0:2") \
        DRI_CONF_DESC_END \
 DRI_CONF_OPT_END
 
+#define DRI_CONF_MESA_GLTHREAD(def) \
+DRI_CONF_OPT_BEGIN_B(mesa_glthread, def) \
+        DRI_CONF_DESC(en,gettext("Enable offloading GL driver work to a separate thread")) \
+DRI_CONF_OPT_END
 
 
 /**
index a528f343700980dccf810485fd4647ea3dcf208b..869e6e9f87bd60c0f911f4e6f5d120f7f63367cf 100644 (file)
@@ -29,6 +29,7 @@
 #include "main/accum.h"
 #include "main/api_exec.h"
 #include "main/context.h"
+#include "main/glthread.h"
 #include "main/samplerobj.h"
 #include "main/shaderobj.h"
 #include "main/version.h"
@@ -612,6 +613,17 @@ st_emit_string_marker(struct gl_context *ctx, const GLchar *string, GLsizei len)
    st->pipe->emit_string_marker(st->pipe, string, len);
 }
 
+static void
+st_set_background_context(struct gl_context *ctx)
+{
+   struct st_context *st = ctx->st;
+   struct st_manager *smapi =
+      (struct st_manager*)st->iface.st_context_private;
+
+   assert(smapi->set_background_context);
+   smapi->set_background_context(&st->iface);
+}
+
 void st_init_driver_functions(struct pipe_screen *screen,
                               struct dd_function_table *functions)
 {
@@ -656,4 +668,5 @@ void st_init_driver_functions(struct pipe_screen *screen,
    functions->Enable = st_Enable;
    functions->UpdateState = st_invalidate_state;
    functions->QueryMemoryInfo = st_query_memory_info;
+   functions->SetBackgroundContext = st_set_background_context;
 }
index e663b017174ebb5b4260de2dd133abc9c6b0c4a4..dad408a451e183f01c29b83fbecd8e4e8a5e8b2a 100644 (file)
@@ -29,6 +29,7 @@
 #include "main/extensions.h"
 #include "main/context.h"
 #include "main/debug_output.h"
+#include "main/glthread.h"
 #include "main/texobj.h"
 #include "main/teximage.h"
 #include "main/texstate.h"
@@ -629,6 +630,22 @@ st_context_destroy(struct st_context_iface *stctxi)
    st_destroy_context(st);
 }
 
+static void
+st_start_thread(struct st_context_iface *stctxi)
+{
+   struct st_context *st = (struct st_context *) stctxi;
+
+   _mesa_glthread_init(st->ctx);
+}
+
+static void
+st_thread_finish(struct st_context_iface *stctxi)
+{
+   struct st_context *st = (struct st_context *) stctxi;
+
+   _mesa_glthread_finish(st->ctx);
+}
+
 static struct st_context_iface *
 st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
                       const struct st_context_attribs *attribs,
@@ -723,6 +740,8 @@ st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
    st->iface.teximage = st_context_teximage;
    st->iface.copy = st_context_copy;
    st->iface.share = st_context_share;
+   st->iface.start_thread = st_start_thread;
+   st->iface.thread_finish = st_thread_finish;
    st->iface.st_context_private = (void *) smapi;
    st->iface.cso_context = st->cso_context;
    st->iface.pipe = st->pipe;