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