diff --git a/pressure-vessel/bwrap.c b/pressure-vessel/bwrap.c
index b6931446ffc6869f9262caa7b84997608a6e3104..dae5a3126f1becab03b9d39e0022100796accc5a 100644
--- a/pressure-vessel/bwrap.c
+++ b/pressure-vessel/bwrap.c
@@ -22,6 +22,7 @@
 #include <gio/gio.h>
 
 #include "bwrap.h"
+#include "utils.h"
 
 #include "steam-runtime-tools/resolve-in-sysroot-internal.h"
 
@@ -42,65 +43,14 @@ pv_bwrap_run_sync (FlatpakBwrap *bwrap,
                    int *exit_status_out,
                    GError **error)
 {
-  gint exit_status;
-  g_autofree gchar *output = NULL;
-  g_autofree gchar *errors = NULL;
-  guint i;
-  g_autoptr(GString) command = g_string_new ("");
-
   g_return_val_if_fail (bwrap != NULL, FALSE);
   g_return_val_if_fail (bwrap->argv->len >= 2, FALSE);
   g_return_val_if_fail (pv_bwrap_was_finished (bwrap), FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-  if (exit_status_out != NULL)
-    *exit_status_out = -1;
-
-  for (i = 0; i < bwrap->argv->len; i++)
-    {
-      g_autofree gchar *quoted = NULL;
-      char *unquoted = g_ptr_array_index (bwrap->argv, i);
-
-      if (unquoted == NULL)
-        break;
-
-      quoted = g_shell_quote (unquoted);
-      g_string_append_printf (command, " %s", quoted);
-    }
-
-  g_debug ("run:%s", command->str);
-
-  /* We use LEAVE_DESCRIPTORS_OPEN to work around a deadlock in older GLib,
-   * and to avoid wasting a lot of time closing fds if the rlimit for
-   * maximum open file descriptors is high. Because we're waiting for the
-   * subprocess to finish anyway, it doesn't really matter that any fds
-   * that are not close-on-execute will get leaked into the child. */
-  if (!g_spawn_sync (NULL,  /* cwd */
-                     (char **) bwrap->argv->pdata,
-                     bwrap->envp,
-                     (G_SPAWN_SEARCH_PATH |
-                      G_SPAWN_LEAVE_DESCRIPTORS_OPEN),
-                     NULL,
-                     NULL,
-                     &output,
-                     &errors,
-                     &exit_status,
-                     error))
-    return FALSE;
-
-  g_print ("%s", output);
-  g_printerr ("%s", errors);
-
-  if (exit_status_out != NULL)
-    {
-      if (WIFEXITED (exit_status))
-        *exit_status_out = WEXITSTATUS (exit_status);
-    }
-
-  if (!g_spawn_check_exit_status (exit_status, error))
-    return FALSE;
-
-  return TRUE;
+  return pv_run_sync ((const char * const *) bwrap->argv->pdata,
+                      (const char * const *) bwrap->envp,
+                      exit_status_out, NULL, error);
 }
 
 /**
diff --git a/pressure-vessel/runtime.c b/pressure-vessel/runtime.c
index 449214f6afe152f1ddda0b4c0c93f5b3c0173124..80e66a014f63ab168bb27b922be6c4c25d430499 100644
--- a/pressure-vessel/runtime.c
+++ b/pressure-vessel/runtime.c
@@ -325,7 +325,7 @@ runtime_architecture_init (RuntimeArchitecture *self,
    * assume that this is the same as whether we can run them
    * on the host, if different. */
   argv[0] = self->capsule_capture_libs;
-  self->ld_so = pv_capture_output (argv, NULL, NULL);
+  pv_run_sync (argv, NULL, NULL, &self->ld_so, NULL);
 
   if (self->ld_so == NULL)
     {
@@ -3432,9 +3432,9 @@ pv_runtime_get_ld_so (PvRuntime *self,
                               NULL);
       flatpak_bwrap_finish (temp_bwrap);
 
-      *ld_so_in_runtime = pv_capture_output (
-          (const char * const *) temp_bwrap->argv->pdata,
-          (const char * const *) temp_bwrap->envp, NULL);
+      pv_run_sync ((const char * const *) temp_bwrap->argv->pdata,
+                   (const char * const *) temp_bwrap->envp, NULL,
+                   ld_so_in_runtime, NULL);
     }
 
   return TRUE;
diff --git a/pressure-vessel/utils.c b/pressure-vessel/utils.c
index af84f80484f2e2b5aa94bb2dda78a773d50ddf95..57a2fb37b34f51bb7ec1315fe49dab4dd05db286 100644
--- a/pressure-vessel/utils.c
+++ b/pressure-vessel/utils.c
@@ -168,10 +168,12 @@ pv_search_path_append (GString *search_path,
   g_string_append (search_path, item);
 }
 
-gchar *
-pv_capture_output (const char * const * argv,
-                   const char * const * envp,
-                   GError **error)
+gboolean
+pv_run_sync (const char * const * argv,
+             const char * const * envp,
+             int *exit_status_out,
+             char **output_out,
+             GError **error)
 {
   gsize len;
   gint wait_status;
@@ -180,10 +182,14 @@ pv_capture_output (const char * const * argv,
   gsize i;
   g_autoptr(GString) command = g_string_new ("");
 
-  g_return_val_if_fail (argv != NULL, NULL);
-  g_return_val_if_fail (argv[0] != NULL, NULL);
+  g_return_val_if_fail (argv != NULL, FALSE);
+  g_return_val_if_fail (argv[0] != NULL, FALSE);
+  g_return_val_if_fail (output_out == NULL || *output_out == NULL, FALSE);
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
+  if (exit_status_out != NULL)
+    *exit_status_out = -1;
+
   for (i = 0; argv[i] != NULL; i++)
     {
       g_autofree gchar *quoted = g_shell_quote (argv[i]);
@@ -208,12 +214,15 @@ pv_capture_output (const char * const * argv,
                      &errors,
                      &wait_status,
                      error))
-    return NULL;
+    return FALSE;
 
   g_printerr ("%s", errors);
 
-  if (!g_spawn_check_exit_status (wait_status, error))
-    return NULL;
+  if (exit_status_out != NULL)
+    {
+      if (WIFEXITED (wait_status))
+        *exit_status_out = WEXITSTATUS (wait_status);
+    }
 
   len = strlen (output);
 
@@ -223,7 +232,13 @@ pv_capture_output (const char * const * argv,
 
   g_debug ("-> %s", output);
 
-  return g_steal_pointer (&output);
+  if (!g_spawn_check_exit_status (wait_status, error))
+    return FALSE;
+
+  if (output_out != NULL)
+    *output_out = g_steal_pointer (&output);
+
+  return TRUE;
 }
 
 /*
diff --git a/pressure-vessel/utils.h b/pressure-vessel/utils.h
index 5920b7b6ee4a30b1e2163f1e753fa0cf14795e23..cf08ccf76757cce8c33f5279857332354fa1552f 100644
--- a/pressure-vessel/utils.h
+++ b/pressure-vessel/utils.h
@@ -48,9 +48,11 @@ void pv_get_current_dirs (gchar **cwd_p,
 void pv_search_path_append (GString *search_path,
                             const gchar *item);
 
-gchar *pv_capture_output (const char * const * argv,
-                          const char * const * envp,
-                          GError **error);
+gboolean pv_run_sync (const char * const * argv,
+                      const char * const * envp,
+                      int *exit_status_out,
+                      char **output_out,
+                      GError **error);
 
 gpointer pv_hash_table_get_arbitrary_key (GHashTable *table);
 
diff --git a/pressure-vessel/wrap.c b/pressure-vessel/wrap.c
index 1c86297deb184706b686d2a84c06baa328f29d92..bafd4e2f005133e5a763e0db1a3da84d7be589bc 100644
--- a/pressure-vessel/wrap.c
+++ b/pressure-vessel/wrap.c
@@ -349,6 +349,34 @@ export_contents_of_run (FlatpakBwrap *bwrap,
   return TRUE;
 }
 
+/* Nvidia Vulkan ray-tracing requires to load the `nvidia_uvm.ko` kernel
+ * module, and this is usually done in `libcuda.so.1` by running the setuid
+ * binary `nvidia-modprobe`. But when we are inside a container we don't bind
+ * `nvidia-modprobe` and, even if we did, its setuid would not be effective
+ * because we have `PR_SET_NO_NEW_PRIVS` and we don't have `CAP_SYS_MODULE` in
+ * our capability bounding set.
+ * For this reason if the current system is using the proprietary Nvidia
+ * drivers, and `nvidia_uvm.ko` has not been already loaded, we should execute
+ * `nvidia-modprobe` before entering in the container environment. */
+static gboolean
+maybe_load_nvidia_modules (GError **error)
+{
+  const char *nvidia_modprobe_argv[] =
+  {
+    "nvidia-modprobe",
+    "-u",
+    NULL
+  };
+
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  if (g_file_test ("/sys/module/nvidia/version", G_FILE_TEST_IS_REGULAR)
+      && !g_file_test ("/sys/module/nvidia_uvm", G_FILE_TEST_IS_DIR))
+    return pv_run_sync (nvidia_modprobe_argv, NULL, NULL, NULL, error);
+
+  return TRUE;
+}
+
 typedef enum
 {
   ENV_MOUNT_FLAGS_COLON_DELIMITED = (1 << 0),
@@ -2697,6 +2725,15 @@ main (int argc,
         }
     }
 
+  if (!is_flatpak_env)
+    {
+      if (!maybe_load_nvidia_modules (error))
+        {
+          g_debug ("Cannot load nvidia modules: %s", local_error->message);
+          g_clear_error (&local_error);
+        }
+    }
+
   if (opt_only_prepare)
     ret = 0;
   else
diff --git a/tests/pressure-vessel/utils.c b/tests/pressure-vessel/utils.c
index 9fa84bb99e0e26d7134acaf3b2d6b9e00c014c9c..202431ff899bd3dabf0c12bc397d158483c76986 100644
--- a/tests/pressure-vessel/utils.c
+++ b/tests/pressure-vessel/utils.c
@@ -86,8 +86,8 @@ test_arbitrary_key (Fixture *f,
 }
 
 static void
-test_capture_output (Fixture *f,
-                     gconstpointer context)
+test_run_sync (Fixture *f,
+               gconstpointer context)
 {
   const gchar * argv[] =
   {
@@ -96,20 +96,27 @@ test_capture_output (Fixture *f,
   g_autofree gchar *output = NULL;
   g_autoptr(GError) error = NULL;
   g_auto(GStrv) envp = g_get_environ ();
+  int exit_status = -1;
 
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, NULL, &output, &error);
   g_assert_cmpstr (output, ==, "hello");
   g_assert_no_error (error);
   g_clear_pointer (&output, g_free);
 
+  pv_run_sync (argv, NULL, &exit_status, NULL, &error);
+  g_assert_cmpint (exit_status, ==, 0);
+  g_assert_no_error (error);
+
   argv[1] = "hello\\nworld";    /* deliberately no trailing newline */
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 0);
   g_assert_no_error (error);
   g_assert_cmpstr (output, ==, "hello\nworld");
   g_clear_pointer (&output, g_free);
 
   argv[0] = "/nonexistent/doesnotexist";
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, -1);
   g_assert_nonnull (error);
 
   if (error->domain == G_SPAWN_ERROR
@@ -134,7 +141,8 @@ test_capture_output (Fixture *f,
 
   argv[0] = "false";
   argv[1] = NULL;
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 1);
   g_assert_error (error, G_SPAWN_EXIT_ERROR, 1);
   g_assert_cmpstr (output, ==, NULL);
   g_clear_error (&error);
@@ -142,7 +150,8 @@ test_capture_output (Fixture *f,
   argv[0] = "sh";
   argv[1] = "-euc";
   argv[2] = "echo \"$PATH\"";
-  output = pv_capture_output (argv, NULL, &error);
+  pv_run_sync (argv, NULL, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 0);
   g_assert_no_error (error);
   g_assert_cmpstr (output, ==, g_getenv ("PATH"));
   g_clear_pointer (&output, g_free);
@@ -151,7 +160,8 @@ test_capture_output (Fixture *f,
   argv[0] = "sh";
   argv[1] = "-euc";
   argv[2] = "echo \"${FOO-unset}\"";
-  output = pv_capture_output (argv, (const char * const *) envp, &error);
+  pv_run_sync (argv, (const char * const *) envp, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 0);
   g_assert_no_error (error);
   g_assert_cmpstr (output, ==, "bar");
   g_clear_pointer (&output, g_free);
@@ -160,7 +170,8 @@ test_capture_output (Fixture *f,
   argv[0] = "sh";
   argv[1] = "-euc";
   argv[2] = "echo \"${FOO-unset}\"";
-  output = pv_capture_output (argv, (const char * const *) envp, &error);
+  pv_run_sync (argv, (const char * const *) envp, &exit_status, &output, &error);
+  g_assert_cmpint (exit_status, ==, 0);
   g_assert_no_error (error);
   g_assert_cmpstr (output, ==, "unset");
   g_clear_pointer (&output, g_free);
@@ -371,8 +382,8 @@ main (int argc,
   g_test_init (&argc, &argv, NULL);
   g_test_add ("/arbitrary-key", Fixture, NULL,
               setup, test_arbitrary_key, teardown);
-  g_test_add ("/capture-output", Fixture, NULL,
-              setup, test_capture_output, teardown);
+  g_test_add ("/run-sync", Fixture, NULL,
+              setup, test_run_sync, teardown);
   g_test_add ("/delete-dangling-symlink", Fixture, NULL,
               setup, test_delete_dangling_symlink, teardown);
   g_test_add ("/envp-cmp", Fixture, NULL, setup, test_envp_cmp, teardown);