Module: Mesa
Branch: main
Commit: 48062f91c721b8cc177e4df09719cfe609a92453
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=48062f91c721b8cc177e4df09719cfe609a92453

Author: Ryan Neph <[email protected]>
Date:   Wed Apr  5 12:16:34 2023 -0700

virgl: add debug flag to force synchronous GL shader compilation

This does two things:
1. Flush the command buffer and associate a fence with each
   glLinkProgram().
2. Force the application calling glLinkProgram() to wait on the
   associated fence, matching the semantics of native drivers.

This important for some workloads and some environments. For example, on
ChromeOS devices supporting VM-based android (ARCVM), an app's HWUI thread
may be configured to use skiagl, while the app may create its own GLES
context for custom rendering. Virgl+virtio_gpu supports a single fencing
timeline, so all guest GL/GLES contexts are serialized by submission
order to the guest kernel.

If the app's submits multiple heavy shaders for compliation+linking
(glCompileShader + glLinkProgram()), these are batched into a single
virtgpu execbuffer (with one fence). Then rendering performed by the
HWUI thread is blocked until the unrelated heavy host-side work is
finished. To the user, the app appears completely frozen until finished.

With this change, the app is throttled in its calls to glLinkProgram(),
and the HWUI work can fill in the gaps between each while hitting most
display update deadlines. To the user, the UI may render at reduced
framerate, but remains mostly responsive to interaction.

Signed-off-by: Ryan Neph <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22341>

---

 src/gallium/drivers/virgl/virgl_context.c    | 11 +++++++++++
 src/gallium/drivers/virgl/virgl_driinfo.h.in |  4 +++-
 src/gallium/drivers/virgl/virgl_screen.c     |  4 ++++
 src/gallium/drivers/virgl/virgl_screen.h     |  2 ++
 src/util/driconf.h                           |  4 ++++
 5 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/gallium/drivers/virgl/virgl_context.c 
b/src/gallium/drivers/virgl/virgl_context.c
index 8bd8b278980..ba831ca3fb7 100644
--- a/src/gallium/drivers/virgl/virgl_context.c
+++ b/src/gallium/drivers/virgl/virgl_context.c
@@ -1622,10 +1622,21 @@ static void virgl_send_tweaks(struct virgl_context 
*vctx, struct virgl_screen *r
 static void virgl_link_shader(struct pipe_context *ctx, void **handles)
 {
    struct virgl_context *vctx = virgl_context(ctx);
+   struct virgl_screen *rs = virgl_screen(vctx->base.screen);
+
    uint32_t shader_handles[PIPE_SHADER_TYPES];
    for (uint32_t i = 0; i < PIPE_SHADER_TYPES; ++i)
       shader_handles[i] = (uintptr_t)handles[i];
    virgl_encode_link_shader(vctx, shader_handles);
+
+   /* block until shader linking is finished on host */
+   if (rs->shader_sync && !unlikely(virgl_debug & VIRGL_DEBUG_SYNC)) {
+      struct virgl_winsys *vws = rs->vws;
+      struct pipe_fence_handle *sync_fence;
+      virgl_flush_eq(vctx, vctx, &sync_fence);
+      vws->fence_wait(vws, sync_fence, PIPE_TIMEOUT_INFINITE);
+      vws->fence_reference(vws, &sync_fence, NULL);
+   }
 }
 
 struct pipe_context *virgl_context_create(struct pipe_screen *pscreen,
diff --git a/src/gallium/drivers/virgl/virgl_driinfo.h.in 
b/src/gallium/drivers/virgl/virgl_driinfo.h.in
index 17e728b1920..ec688f5227c 100644
--- a/src/gallium/drivers/virgl/virgl_driinfo.h.in
+++ b/src/gallium/drivers/virgl/virgl_driinfo.h.in
@@ -19,9 +19,11 @@ DRI_CONF_SECTION_MISCELLANEOUS
      * possible drm-native-context guest driver:
      */
     DRI_CONF_DISABLE_CONSERVATIVE_LRZ(false)
+
+    DRI_CONF_VIRGL_SHADER_SYNC(false)
 DRI_CONF_SECTION_END
 
 DRI_CONF_SECTION_DEBUG
    /* Also needed for native-context drivers (freedreno) */
    DRI_CONF_DISABLE_THROTTLING(false)
-DRI_CONF_SECTION_END
\ No newline at end of file
+DRI_CONF_SECTION_END
diff --git a/src/gallium/drivers/virgl/virgl_screen.c 
b/src/gallium/drivers/virgl/virgl_screen.c
index ff04d406fa2..6acaa38e7c2 100644
--- a/src/gallium/drivers/virgl/virgl_screen.c
+++ b/src/gallium/drivers/virgl/virgl_screen.c
@@ -55,6 +55,7 @@ static const struct debug_named_value virgl_debug_options[] = 
{
    { "r8srgb-readback",   VIRGL_DEBUG_L8_SRGB_ENABLE_READBACK, "Enable 
redaback for L8 sRGB textures" },
    { "nocoherent", VIRGL_DEBUG_NO_COHERENT,        "Disable coherent memory"},
    { "video",     VIRGL_DEBUG_VIDEO,               "Video codec"},
+   { "shader_sync", VIRGL_DEBUG_SHADER_SYNC,       "Sync after every shader 
link"},
    DEBUG_NAMED_VALUE_END
 };
 DEBUG_GET_ONCE_FLAGS_OPTION(virgl_debug, "VIRGL_DEBUG", virgl_debug_options, 0)
@@ -1122,6 +1123,7 @@ virgl_create_screen(struct virgl_winsys *vws, const 
struct pipe_screen_config *c
    const char *VIRGL_GLES_APPLY_BGRA_DEST_SWIZZLE = 
"gles_apply_bgra_dest_swizzle";
    const char *VIRGL_GLES_SAMPLES_PASSED_VALUE = "gles_samples_passed_value";
    const char *VIRGL_FORMAT_L8_SRGB_ENABLE_READBACK = 
"format_l8_srgb_enable_readback";
+   const char *VIRGL_SHADER_SYNC = "virgl_shader_sync";
 
    if (!screen)
       return NULL;
@@ -1140,11 +1142,13 @@ virgl_create_screen(struct virgl_winsys *vws, const 
struct pipe_screen_config *c
             driQueryOptioni(config->options, VIRGL_GLES_SAMPLES_PASSED_VALUE);
       screen->tweak_l8_srgb_readback =
             driQueryOptionb(config->options, 
VIRGL_FORMAT_L8_SRGB_ENABLE_READBACK);
+      screen->shader_sync = driQueryOptionb(config->options, 
VIRGL_SHADER_SYNC);
    }
    screen->tweak_gles_emulate_bgra &= !(virgl_debug & 
VIRGL_DEBUG_NO_EMULATE_BGRA);
    screen->tweak_gles_apply_bgra_dest_swizzle &= !(virgl_debug & 
VIRGL_DEBUG_NO_BGRA_DEST_SWIZZLE);
    screen->no_coherent = virgl_debug & VIRGL_DEBUG_NO_COHERENT;
    screen->tweak_l8_srgb_readback |= !!(virgl_debug & 
VIRGL_DEBUG_L8_SRGB_ENABLE_READBACK);
+   screen->shader_sync |= !!(virgl_debug & VIRGL_DEBUG_SHADER_SYNC);
 
    screen->vws = vws;
    screen->base.get_name = virgl_get_name;
diff --git a/src/gallium/drivers/virgl/virgl_screen.h 
b/src/gallium/drivers/virgl/virgl_screen.h
index ce8a531092a..7b32e3d8294 100644
--- a/src/gallium/drivers/virgl/virgl_screen.h
+++ b/src/gallium/drivers/virgl/virgl_screen.h
@@ -41,6 +41,7 @@ enum virgl_debug_flags {
    VIRGL_DEBUG_USE_TGSI             = 1 << 7,
    VIRGL_DEBUG_L8_SRGB_ENABLE_READBACK = 1 << 8,
    VIRGL_DEBUG_VIDEO                = 1 << 9,
+   VIRGL_DEBUG_SHADER_SYNC          = 1 << 10,
 };
 
 extern int virgl_debug;
@@ -64,6 +65,7 @@ struct virgl_screen {
    bool tweak_gles_apply_bgra_dest_swizzle;
    bool tweak_l8_srgb_readback;
    bool no_coherent;
+   bool shader_sync;
    int32_t tweak_gles_tf3_value;
 
    nir_shader_compiler_options compiler_options;
diff --git a/src/util/driconf.h b/src/util/driconf.h
index 446955c3efd..6264209e7a8 100644
--- a/src/util/driconf.h
+++ b/src/util/driconf.h
@@ -523,6 +523,10 @@
    DRI_CONF_OPT_B(format_l8_srgb_enable_readback, def, \
                   "Force-enable reading back L8_SRGB textures")
 
+#define DRI_CONF_VIRGL_SHADER_SYNC(def) \
+   DRI_CONF_OPT_B(virgl_shader_sync, def, \
+                  "Make shader compilation synchronous")
+
 /**
  * \brief freedreno specific configuration options
  */

Reply via email to