<div dir="ltr">Ping<br></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Nov 12, 2018 at 7:21 PM Marek Olšák <<a href="mailto:maraeo@gmail.com">maraeo@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">From: Marek Olšák <<a href="mailto:marek.olsak@amd.com" target="_blank">marek.olsak@amd.com</a>><br>
<br>
This is used when glthread is disabled.<br>
<br>
Mesa pretty much chases the app thread on the CPU.<br>
The performance is the same as pinning the app thread.<br>
---<br>
 src/mesa/state_tracker/st_context.h |  2 ++<br>
 src/mesa/state_tracker/st_draw.c    | 32 +++++++++++++++++++++++++++++<br>
 2 files changed, 34 insertions(+)<br>
<br>
diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h<br>
index 14b9b018809..95133c7020f 100644<br>
--- a/src/mesa/state_tracker/st_context.h<br>
+++ b/src/mesa/state_tracker/st_context.h<br>
@@ -186,20 +186,22 @@ struct st_context<br>
       uint8_t sample_locations[<br>
          PIPE_MAX_SAMPLE_LOCATION_GRID_SIZE *<br>
          PIPE_MAX_SAMPLE_LOCATION_GRID_SIZE * 32];<br>
    } state;<br>
<br>
    uint64_t dirty; /**< dirty states */<br>
<br>
    /** This masks out unused shader resources. Only valid in draw calls. */<br>
    uint64_t active_states;<br>
<br>
+   unsigned pin_thread_counter; /* for L3 thread pinning on AMD Zen */<br>
+<br>
    /* If true, further analysis of states is required to know if something<br>
     * has changed. Used mainly for shaders.<br>
     */<br>
    bool gfx_shaders_may_be_dirty;<br>
    bool compute_shader_may_be_dirty;<br>
<br>
    GLboolean vertdata_edgeflags;<br>
    GLboolean edgeflag_culls_prims;<br>
<br>
    struct st_vertex_program *vp;    /**< Currently bound vertex program */<br>
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c<br>
index eb52d9505b6..5910ffa5bda 100644<br>
--- a/src/mesa/state_tracker/st_draw.c<br>
+++ b/src/mesa/state_tracker/st_draw.c<br>
@@ -51,28 +51,36 @@<br>
 #include "st_atom.h"<br>
 #include "st_cb_bitmap.h"<br>
 #include "st_cb_bufferobjects.h"<br>
 #include "st_cb_xformfb.h"<br>
 #include "st_debug.h"<br>
 #include "st_draw.h"<br>
 #include "st_program.h"<br>
<br>
 #include "pipe/p_context.h"<br>
 #include "pipe/p_defines.h"<br>
+#include "util/u_cpu_detect.h"<br>
 #include "util/u_inlines.h"<br>
 #include "util/u_format.h"<br>
 #include "util/u_prim.h"<br>
 #include "util/u_draw.h"<br>
 #include "util/u_upload_mgr.h"<br>
 #include "draw/draw_context.h"<br>
 #include "cso_cache/cso_context.h"<br>
<br>
+#ifdef PIPE_OS_LINUX<br>
+#include <sched.h><br>
+#define HAVE_SCHED_GETCPU 1<br>
+#else<br>
+#define sched_getcpu() 0<br>
+#define HAVE_SCHED_GETCPU 0<br>
+#endif<br>
<br>
 /**<br>
  * Set the restart index.<br>
  */<br>
 static void<br>
 setup_primitive_restart(struct gl_context *ctx, struct pipe_draw_info *info)<br>
 {<br>
    if (ctx->Array._PrimitiveRestart) {<br>
       unsigned index_size = info->index_size;<br>
<br>
@@ -115,20 +123,44 @@ prepare_draw(struct st_context *st, struct gl_context *ctx)<br>
    if (unlikely(!st->bitmap.cache.empty))<br>
       st_flush_bitmap_cache(st);<br>
<br>
    st_invalidate_readpix_cache(st);<br>
<br>
    /* Validate state. */<br>
    if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_RENDER_STATE_MASK ||<br>
        st->gfx_shaders_may_be_dirty) {<br>
       st_validate_state(st, ST_PIPELINE_RENDER);<br>
    }<br>
+<br>
+   struct pipe_context *pipe = st->pipe;<br>
+<br>
+   /* Pin threads regularly to the same Zen CCX that the main thread is<br>
+    * running on. The main thread can move between CCXs.<br>
+    */<br>
+   if (unlikely(HAVE_SCHED_GETCPU && /* Linux */<br>
+                /* AMD Zen */<br>
+                util_cpu_caps.nr_cpus != util_cpu_caps.cores_per_L3 &&<br>
+                /* no glthread */<br>
+                ctx->CurrentClientDispatch != ctx->MarshalExec &&<br>
+                /* driver support */<br>
+                pipe->set_context_param &&<br>
+                /* do it occasionally */<br>
+                ++st->pin_thread_counter % 512 == 0)) {<br>
+      int cpu = sched_getcpu();<br>
+      if (cpu >= 0) {<br>
+         unsigned L3_cache = cpu / util_cpu_caps.cores_per_L3;<br>
+<br>
+         pipe->set_context_param(pipe,<br>
+                                 PIPE_CONTEXT_PARAM_PIN_THREADS_TO_L3_CACHE,<br>
+                                 L3_cache);<br>
+      }<br>
+   }<br>
 }<br>
<br>
 /**<br>
  * This function gets plugged into the VBO module and is called when<br>
  * we have something to render.<br>
  * Basically, translate the information into the format expected by gallium.<br>
  */<br>
 static void<br>
 st_draw_vbo(struct gl_context *ctx,<br>
             const struct _mesa_prim *prims,<br>
-- <br>
2.17.1<br>
<br>
</blockquote></div>