diff --git a/bin/system-info.c b/bin/system-info.c
index 69667a6de7c4869c96ab26503fcac226bb01f2fc..83b0059f63688149051b2986cda575278f9a09b3 100644
--- a/bin/system-info.c
+++ b/bin/system-info.c
@@ -386,6 +386,53 @@ print_graphics_details(JsonBuilder *builder,
             }
 
         }
+
+      if (rendering_interface == SRT_RENDERING_INTERFACE_VULKAN)
+        {
+          g_autoptr(SrtObjectList) devices = srt_graphics_get_devices (g->data);
+          const GList *iter;
+          json_builder_set_member_name (builder, "devices");
+          json_builder_begin_array (builder);
+            {
+              for (iter = devices; iter != NULL; iter = iter->next)
+                {
+                  json_builder_begin_object (builder);
+                  json_builder_set_member_name (builder, "name");
+                  json_builder_add_string_value (builder,
+                                                 srt_graphics_device_get_name (iter->data));
+                  json_builder_set_member_name (builder, "api-version");
+                  json_builder_add_string_value (builder,
+                                                 srt_graphics_device_get_api_version (iter->data));
+                  json_builder_set_member_name (builder, "driver-version");
+                  json_builder_add_string_value (builder,
+                                                 srt_graphics_device_get_driver_version (iter->data));
+                  json_builder_set_member_name (builder, "vendor-id");
+                  json_builder_add_string_value (builder,
+                                                 srt_graphics_device_get_vendor_id (iter->data));
+                  json_builder_set_member_name (builder, "device-id");
+                  json_builder_add_string_value (builder,
+                                                 srt_graphics_device_get_device_id (iter->data));
+                  json_builder_set_member_name (builder, "type");
+                  jsonify_enum (builder, SRT_TYPE_VK_PHYSICAL_DEVICE_TYPE,
+                                srt_graphics_device_get_device_type (iter->data));
+
+                  messages = srt_graphics_device_get_messages (iter->data);
+                  if (messages != NULL)
+                    _srt_json_builder_add_array_of_lines (builder, "messages", messages);
+
+                  if (srt_graphics_device_get_issues (iter->data) != SRT_GRAPHICS_ISSUES_NONE)
+                    {
+                      json_builder_set_member_name (builder, "issues");
+                      json_builder_begin_array (builder);
+                      jsonify_graphics_issues (builder, srt_graphics_device_get_issues (iter->data));
+                      json_builder_end_array (builder);
+                    }
+                  json_builder_end_object (builder);
+                }
+            }
+          json_builder_end_array (builder);
+        }
+
       json_builder_end_object (builder); // End object for parameters
       g_free (parameters);
     }
diff --git a/bin/system-info.md b/bin/system-info.md
index 88bdeea84726361f4d7fce62bbe3798c3928ab84..117fd6dca29df2e696e0227831410682b30b37d9 100644
--- a/bin/system-info.md
+++ b/bin/system-info.md
@@ -504,6 +504,46 @@ keys:
         **messages**
         :   Human-readable array of diagnostic messages.
 
+        **devices**
+        :   An array of objects describing the available graphics devices.
+            It is currently printed only when the rendering interface is
+            **vulkan**. Every object has the following keys:
+
+            **name**
+            :   The name of this graphics device, or **null** if it could
+                not be determined.
+
+            **api-version**
+            :   The API version used by this graphics device, or **null**
+                if it could not be determined.
+
+            **driver-version**
+            :   The driver version used by this graphics device, or **null**
+                if it could not be determined.
+
+            **vendor-id**
+            :   The vendor ID of this graphics device, or **null** if it
+                could not be determined.
+
+            **device-id**
+            :   The device ID of this graphics device, or **null** if it
+                could not be determined.
+
+            **type**
+            :   The type of this graphics device, typically one of
+                `integrated-gpu`, `discrete-gpu`, `virtual-gpu`,
+                or `cpu` (denoting software rendering such as llvmpipe).
+
+
+            **messages**
+            :   Human-readable array of diagnostic messages.
+
+            **issues**
+            :   Problems with this graphics device, represented as an array
+                of strings. The array is empty if no problems were detected.
+                The possible values are the same as the ones in the **issues**
+                of **graphics-details**.
+
     **dri_drivers**
     :   An array of objects describing the Mesa DRI driver modules that have been
         found. These drivers are used by Mesa and by older versions of Xorg.
diff --git a/steam-runtime-tools/graphics-internal.h b/steam-runtime-tools/graphics-internal.h
index f8931abde06d096ef6b3ba3b3a2695d398008acb..55300797b890ece83d9b5def27fede5db9a9a76c 100644
--- a/steam-runtime-tools/graphics-internal.h
+++ b/steam-runtime-tools/graphics-internal.h
@@ -1,6 +1,6 @@
 /*< internal_header >*/
 /*
- * Copyright © 2019 Collabora Ltd.
+ * Copyright © 2019-2021 Collabora Ltd.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -35,8 +35,9 @@
  * _srt_graphics_new:
  * @multiarch_tuple: A multiarch tuple like %SRT_ABI_I386,
  *  representing an ABI
- * @window_system: The window system to check,
- * @rendering_interface: The renderint interface to check,
+ * @window_system: The window system to check
+ * @rendering_interface: The rendering interface to check
+ * @graphics_devices: Array of #SrtGraphicsDevice
  * @issues: Problems found when checking @multiarch_tuple with
  *  the given @winsys and @renderer.
  * @messages: Any debug messages found when checking graphics.
@@ -54,11 +55,37 @@ static inline SrtGraphics *_srt_graphics_new (const char *multiarch_tuple,
                                               SrtGraphicsLibraryVendor library_vendor,
                                               const gchar *renderer_string,
                                               const gchar *version_string,
+                                              GPtrArray *graphics_devices,
                                               SrtGraphicsIssues issues,
                                               const gchar *messages,
                                               int exit_status,
                                               int termination_signal);
 
+/*
+ * _srt_graphics_device_new:
+ * @name: Device name, also referred as renderer name
+ * @api_version: API version used by this device
+ * @driver_version: Driver version used by this device
+ * @vendor_id: Device vendor ID
+ * @device_id: Device ID
+ * @type: The device type
+ * @issues: Problems found when checking the drawing capabilities of
+ *  the device
+ *
+ * Inline convenience function to create a new SrtGraphicsDevice.
+ * This is not part of the public API.
+ *
+ * Returns: (transfer full): A new #SrtGraphicsDevice
+ */
+static inline SrtGraphicsDevice *_srt_graphics_device_new (const gchar *name,
+                                                           const gchar *api_version,
+                                                           const gchar *driver_version,
+                                                           const gchar *vendor_id,
+                                                           const gchar *device_id,
+                                                           SrtVkPhysicalDeviceType type,
+                                                           SrtGraphicsIssues issues);
+
+
 /*
  * _srt_graphics_hash_key:
  * @window_system: The window system,
@@ -89,6 +116,7 @@ _srt_graphics_new (const char *multiarch_tuple,
                    SrtGraphicsLibraryVendor library_vendor,
                    const gchar *renderer_string,
                    const gchar *version_string,
+                   GPtrArray *graphics_devices,
                    SrtGraphicsIssues issues,
                    const gchar *messages,
                    int exit_status,
@@ -103,12 +131,33 @@ _srt_graphics_new (const char *multiarch_tuple,
                        "rendering-interface", rendering_interface,
                        "renderer-string", renderer_string,
                        "version-string", version_string,
+                       "graphics-devices", graphics_devices,
                        "messages", messages,
                        "exit-status", exit_status,
                        "terminating-signal", terminating_signal,
                        NULL);
 }
 
+static inline SrtGraphicsDevice *
+_srt_graphics_device_new (const gchar *name,
+                          const gchar *api_version,
+                          const gchar *driver_version,
+                          const gchar *vendor_id,
+                          const gchar *device_id,
+                          SrtVkPhysicalDeviceType type,
+                          SrtGraphicsIssues issues)
+{
+  return g_object_new (SRT_TYPE_GRAPHICS_DEVICE,
+                       "name", name,
+                       "api-version", api_version,
+                       "driver-version", driver_version,
+                       "vendor-id", vendor_id,
+                       "device-id", device_id,
+                       "type", type,
+                       "issues", issues,
+                       NULL);
+}
+
 static inline int _srt_graphics_hash_key(SrtWindowSystem window_system,
                                          SrtRenderingInterface rendering_interface)
 {
diff --git a/steam-runtime-tools/graphics-test-defines.h b/steam-runtime-tools/graphics-test-defines.h
index a53de0fd34e269a02f3f1d67d3e66cf903b12843..a31e73a0bdeb9250352b248799f906727585b3aa 100644
--- a/steam-runtime-tools/graphics-test-defines.h
+++ b/steam-runtime-tools/graphics-test-defines.h
@@ -1,6 +1,6 @@
 /*< internal_header >*/
 /*
- * Copyright © 2019 Collabora Ltd.
+ * Copyright © 2019-2021 Collabora Ltd.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -27,12 +27,35 @@
 #pragma once
 
 // Test strings for use in mock and graphics test
-#define SRT_TEST_GOOD_GRAPHICS_RENDERER "Mesa DRI Intel(R) Haswell Desktop "
+#define SRT_TEST_GOOD_GRAPHICS_RENDERER "AMD RADV NAVI10 (ACO)"
+#define SRT_TEST_GOOD_GRAPHICS_API_VERSION "1.2.145"
+#define SRT_TEST_GOOD_GRAPHICS_DRIVER_VERSION "20.3.3"
+#define SRT_TEST_GOOD_GRAPHICS_VENDOR_ID "0x1002"
+#define SRT_TEST_GOOD_GRAPHICS_DEVICE_ID "0x731f"
+
 #define SRT_TEST_SOFTWARE_GRAPHICS_RENDERER "llvmpipe (LLVM 8.0, 256 bits)"
+#define SRT_TEST_SOFTWARE_GRAPHICS_API_VERSION "1.0.2"
+#define SRT_TEST_SOFTWARE_GRAPHICS_DRIVER_VERSION "0.0.1"
+#define SRT_TEST_SOFTWARE_GRAPHICS_VENDOR_ID "0x10005"
+#define SRT_TEST_SOFTWARE_GRAPHICS_DEVICE_ID "0"
+
 #define SRT_TEST_GOOD_GRAPHICS_VERSION "3.0 Mesa 19.1.3"
 #define SRT_TEST_SOFTWARE_GRAPHICS_VERSION "3.1 Mesa 19.1.3"
-#define SRT_TEST_GOOD_VULKAN_DRIVER_VERSION "79695877"
-#define SRT_TEST_GOOD_VULKAN_VERSION "1.1.102 (device 8086:0412) (driver 19.1.5)"
+#define SRT_TEST_GOOD_VULKAN_MESSAGES "WARNING: lavapipe is not a conformant vulkan implementation, testing use only."
+#define SRT_TEST_GOOD_VULKAN_VERSION \
+SRT_TEST_GOOD_GRAPHICS_API_VERSION \
+" (device " \
+SRT_TEST_GOOD_GRAPHICS_VENDOR_ID \
+":" \
+SRT_TEST_GOOD_GRAPHICS_DEVICE_ID \
+") (driver " \
+SRT_TEST_GOOD_GRAPHICS_DRIVER_VERSION \
+")"
+
+#define SRT_TEST_MIXED_VULKAN_MESSAGES_1 "Failed to open file “./_build/helpers/shaders/vert.spv”: No such file or directory"
+#define SRT_TEST_MIXED_VULKAN_MESSAGES_2 "vkWaitForFences (dev_props->device, 1, &dev_props->in_flight_fences[dev_props->current_frame], VK_TRUE, 1) failed: TIMEOUT (2)"
+#define SRT_TEST_BAD_VULKAN_MESSAGES "failed to create window surface!\n"
+
 #define SRT_TEST_GOOD_VDPAU_RENDERER "G3DVL VDPAU Driver Shared Library version 1.0\n"
 #define SRT_TEST_BAD_VDPAU_MESSAGES "Failed to open VDPAU backend libvdpau_nvidia.so: cannot open shared object file: No such file or directory\n\
 vdp_device_create_x11 (display, screen, &device, &vdp_get_proc_address) failed: 1\n"
diff --git a/steam-runtime-tools/graphics.c b/steam-runtime-tools/graphics.c
index 20d1a99937dbfcdfbbcf4efa700d9e94609609e3..798d4967fd0614ac039d68223a5a57332fdc4d33 100644
--- a/steam-runtime-tools/graphics.c
+++ b/steam-runtime-tools/graphics.c
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2019-2020 Collabora Ltd.
+ * Copyright © 2019-2021 Collabora Ltd.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -61,6 +61,11 @@
  * This is a reference-counted object: use g_object_ref() and
  * g_object_unref() to manage its lifecycle.
  *
+ * #SrtGraphicsDevice is an opaque object representing a single, physical or
+ * virtual, GPU.
+ * This is a reference-counted object: use g_object_ref() and
+ * g_object_unref() to manage its lifecycle.
+ *
  * #SrtEglIcd is an opaque object representing the metadata describing
  * an EGL ICD.
  * This is a reference-counted object: use g_object_ref() and
@@ -72,6 +77,379 @@
  * g_object_unref() to manage its lifecycle.
  */
 
+struct _SrtGraphicsDevice
+{
+  /*< private >*/
+  GObject parent;
+  SrtGraphicsIssues issues;
+  gchar *name;
+  gchar *api_version;
+  gchar *driver_version;
+  gchar *vendor_id;
+  gchar *device_id;
+  gchar *messages;
+  SrtVkPhysicalDeviceType type;
+};
+
+struct _SrtGraphicsDeviceClass
+{
+  /*< private >*/
+  GObjectClass parent_class;
+};
+
+enum
+{
+  GRAPHICS_DEVICE_PROP_0,
+  GRAPHICS_DEVICE_PROP_ISSUES,
+  GRAPHICS_DEVICE_PROP_NAME,
+  GRAPHICS_DEVICE_PROP_API_VERSION,
+  GRAPHICS_DEVICE_PROP_DRIVER_VERSION,
+  GRAPHICS_DEVICE_PROP_VENDOR_ID,
+  GRAPHICS_DEVICE_PROP_DEVICE_ID,
+  GRAPHICS_DEVICE_PROP_TYPE,
+  N_GRAPHICS_DEVICE_PROPERTIES,
+};
+
+G_DEFINE_TYPE (SrtGraphicsDevice, srt_graphics_device, G_TYPE_OBJECT)
+
+static void
+srt_graphics_device_init (SrtGraphicsDevice *self)
+{
+}
+
+static void
+srt_graphics_device_get_property (GObject *object,
+                                  guint prop_id,
+                                  GValue *value,
+                                  GParamSpec *pspec)
+{
+  SrtGraphicsDevice *self = SRT_GRAPHICS_DEVICE (object);
+
+  switch (prop_id)
+    {
+      case GRAPHICS_DEVICE_PROP_ISSUES:
+        g_value_set_flags (value, self->issues);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_NAME:
+        g_value_set_string (value, self->name);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_API_VERSION:
+        g_value_set_string (value, self->api_version);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_DRIVER_VERSION:
+        g_value_set_string (value, self->driver_version);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_VENDOR_ID:
+        g_value_set_string (value, self->vendor_id);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_DEVICE_ID:
+        g_value_set_string (value, self->device_id);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_TYPE:
+        g_value_set_enum (value, self->type);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+srt_graphics_device_set_property (GObject *object,
+                                  guint prop_id,
+                                  const GValue *value,
+                                  GParamSpec *pspec)
+{
+  SrtGraphicsDevice *self = SRT_GRAPHICS_DEVICE (object);
+
+  switch (prop_id)
+    {
+      case GRAPHICS_DEVICE_PROP_ISSUES:
+        /* Construct-only */
+        g_return_if_fail (self->issues == 0);
+        self->issues = g_value_get_flags (value);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_NAME:
+        /* Construct only */
+        g_return_if_fail (self->name == NULL);
+        self->name = g_value_dup_string (value);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_API_VERSION:
+        /* Construct only */
+        g_return_if_fail (self->api_version == NULL);
+        self->api_version = g_value_dup_string (value);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_DRIVER_VERSION:
+        /* Construct only */
+        g_return_if_fail (self->driver_version == NULL);
+        self->driver_version = g_value_dup_string (value);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_VENDOR_ID:
+        /* Construct only */
+        g_return_if_fail (self->vendor_id == NULL);
+        self->vendor_id = g_value_dup_string (value);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_DEVICE_ID:
+        /* Construct only */
+        g_return_if_fail (self->device_id == NULL);
+        self->device_id = g_value_dup_string (value);
+        break;
+
+      case GRAPHICS_DEVICE_PROP_TYPE:
+        /* Construct-only */
+        g_return_if_fail (self->type == 0);
+        self->type = g_value_get_enum (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+srt_graphics_device_finalize (GObject *object)
+{
+  SrtGraphicsDevice *self = SRT_GRAPHICS_DEVICE (object);
+
+  g_free (self->name);
+  g_free (self->api_version);
+  g_free (self->driver_version);
+  g_free (self->vendor_id);
+  g_free (self->device_id);
+  g_free (self->messages);
+
+  G_OBJECT_CLASS (srt_graphics_device_parent_class)->finalize (object);
+}
+
+static GParamSpec *graphics_device_properties[N_GRAPHICS_DEVICE_PROPERTIES] = { NULL };
+
+static void
+srt_graphics_device_class_init (SrtGraphicsDeviceClass *cls)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (cls);
+
+  object_class->get_property = srt_graphics_device_get_property;
+  object_class->set_property = srt_graphics_device_set_property;
+  object_class->finalize = srt_graphics_device_finalize;
+
+  graphics_device_properties[GRAPHICS_DEVICE_PROP_ISSUES] =
+    g_param_spec_flags ("issues", "Issues", "Problems with the graphics device card",
+                        SRT_TYPE_GRAPHICS_ISSUES, SRT_GRAPHICS_ISSUES_NONE,
+                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                        G_PARAM_STATIC_STRINGS);
+
+  graphics_device_properties[GRAPHICS_DEVICE_PROP_NAME] =
+    g_param_spec_string ("name", "Device name",
+                         "Which name the device has.",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+
+  graphics_device_properties[GRAPHICS_DEVICE_PROP_API_VERSION] =
+    g_param_spec_string ("api-version", "API version",
+                         "Which API version is in use.",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+
+  graphics_device_properties[GRAPHICS_DEVICE_PROP_DRIVER_VERSION] =
+    g_param_spec_string ("driver-version", "Driver version",
+                         "Which driver version is in use.",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+
+  graphics_device_properties[GRAPHICS_DEVICE_PROP_VENDOR_ID] =
+    g_param_spec_string ("vendor-id", "Vendor ID", "The vendor ID of the device.",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+
+  graphics_device_properties[GRAPHICS_DEVICE_PROP_DEVICE_ID] =
+    g_param_spec_string ("device-id", "Device ID", "The device ID of the device.",
+                         NULL,
+                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+
+  graphics_device_properties[GRAPHICS_DEVICE_PROP_TYPE] =
+    g_param_spec_enum ("type", "Type", "Which type the device is.",
+                       SRT_TYPE_VK_PHYSICAL_DEVICE_TYPE, SRT_VK_PHYSICAL_DEVICE_TYPE_OTHER,
+                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                       G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_GRAPHICS_DEVICE_PROPERTIES,
+                                     graphics_device_properties);
+}
+
+/**
+ * srt_graphics_device_get_issues:
+ * @self: a SrtGraphicsDevice object
+ *
+ * Return the problems found when testing @self.
+ *
+ * Returns: A bitfield containing problems, or %SRT_GRAPHICS_ISSUES_NONE
+ *  if no problems were found
+ */
+SrtGraphicsIssues
+srt_graphics_device_get_issues (SrtGraphicsDevice *self)
+{
+  g_return_val_if_fail (SRT_IS_GRAPHICS_DEVICE (self), SRT_GRAPHICS_ISSUES_UNKNOWN);
+  return self->issues;
+}
+
+/**
+ * srt_graphics_device_get_name:
+ * @self: a SrtGraphicsDevice object
+ *
+ * Return the device name of @self, or %NULL if it's not known.
+ *
+ * Returns (nullable): A string indicating the device name.
+ */
+const char *
+srt_graphics_device_get_name (SrtGraphicsDevice *self)
+{
+  g_return_val_if_fail (SRT_IS_GRAPHICS_DEVICE (self), NULL);
+  return self->name;
+}
+
+/**
+ * srt_graphics_device_get_api_version:
+ * @self: a SrtGraphicsDevice object
+ *
+ * Return the API version used by @self, or %NULL if it's not known.
+ *
+ * Returns (nullable): A string indicating the API version.
+ */
+const char *
+srt_graphics_device_get_api_version (SrtGraphicsDevice *self)
+{
+  g_return_val_if_fail (SRT_IS_GRAPHICS_DEVICE (self), NULL);
+  return self->api_version;
+}
+
+/**
+ * srt_graphics_device_get_driver_version:
+ * @self: a SrtGraphicsDevice object
+ *
+ * Return the driver version used by @self, or %NULL if it's not known.
+ *
+ * Returns (nullable): A string indicating the driver version.
+ */
+const char *
+srt_graphics_device_get_driver_version (SrtGraphicsDevice *self)
+{
+  g_return_val_if_fail (SRT_IS_GRAPHICS_DEVICE (self), NULL);
+  return self->driver_version;
+}
+
+/**
+ * srt_graphics_device_get_vendor_id:
+ * @self: a SrtGraphicsDevice object
+ *
+ * Return the vendor ID of @self, or %NULL if it's not known.
+ *
+ * Returns (nullable): A string indicating the vendor ID.
+ */
+const char *
+srt_graphics_device_get_vendor_id (SrtGraphicsDevice *self)
+{
+  g_return_val_if_fail (SRT_IS_GRAPHICS_DEVICE (self), NULL);
+  return self->vendor_id;
+}
+
+/**
+ * srt_graphics_device_get_device_id:
+ * @self: a SrtGraphicsDevice object
+ *
+ * Return the device ID of @self, or %NULL if it's not known.
+ *
+ * Returns (nullable): A string indicating the device ID.
+ */
+const char *
+srt_graphics_device_get_device_id (SrtGraphicsDevice *self)
+{
+  g_return_val_if_fail (SRT_IS_GRAPHICS_DEVICE (self), NULL);
+  return self->device_id;
+}
+
+/**
+ * srt_graphics_device_get_messages:
+ * @self: a SrtGraphicsDevice object
+ *
+ * Return the diagnostic messages produced while checking @self device
+ * drawing capabilities.
+ *
+ * Returns: (nullable) (transfer none): A string, which must not be freed,
+ *  or %NULL if there were no diagnostic messages.
+ */
+const char *
+srt_graphics_device_get_messages (SrtGraphicsDevice *self)
+{
+  g_return_val_if_fail (SRT_IS_GRAPHICS_DEVICE (self), NULL);
+  return self->messages;
+}
+
+/**
+ * srt_graphics_device_get_device_type:
+ * @self: a SrtGraphicsDevice object
+ *
+ * Return the @self device type
+ *
+ * Returns: An enumeration of #SrtVkPhysicalDeviceType indicating the type
+ *  of this device.
+ */
+SrtVkPhysicalDeviceType
+srt_graphics_device_get_device_type (SrtGraphicsDevice *self)
+{
+  g_return_val_if_fail (SRT_IS_GRAPHICS_DEVICE (self),
+                        SRT_VK_PHYSICAL_DEVICE_TYPE_OTHER);
+  return self->type;
+}
+
+/*
+ * @self: a SrtGraphicsDevice object
+ * @can_draw: if %TRUE, this device is able to successfully draw a triangle
+ *  test
+ *
+ * @self issues is adjusted accordingly to the @can_draw value.
+ */
+static void
+_srt_graphics_device_set_can_draw (SrtGraphicsDevice *self,
+                                   gboolean can_draw)
+{
+  g_return_if_fail (SRT_IS_GRAPHICS_DEVICE (self));
+  if (can_draw)
+    self->issues &= ~SRT_GRAPHICS_ISSUES_CANNOT_DRAW;
+  else
+    self->issues |= SRT_GRAPHICS_ISSUES_CANNOT_DRAW;
+}
+
+/*
+ * @self: a SrtGraphicsDevice object
+ * @messages (nullable): diagnostic messages
+ *
+ * Set @self diagnostic messages to the provided @messages.
+ */
+static void
+_srt_graphics_device_set_messages (SrtGraphicsDevice *self,
+                                   const gchar *messages)
+{
+  g_return_if_fail (SRT_IS_GRAPHICS_DEVICE (self));
+  g_free (self->messages);
+  self->messages = g_strdup (messages);
+}
+
 struct _SrtGraphics
 {
   /*< private >*/
@@ -84,6 +462,7 @@ struct _SrtGraphics
   gchar *messages;
   gchar *renderer_string;
   gchar *version_string;
+  GPtrArray *devices;
   int exit_status;
   int terminating_signal;
 };
@@ -104,6 +483,7 @@ enum {
   PROP_RENDERING_INTERFACE,
   PROP_RENDERER_STRING,
   PROP_VERSION_STRING,
+  PROP_GRAPHICS_DEVICES,
   PROP_EXIT_STATUS,
   PROP_TERMINATING_SIGNAL,
   N_PROPERTIES
@@ -158,6 +538,10 @@ srt_graphics_get_property (GObject *object,
         g_value_set_string (value, self->version_string);
         break;
 
+      case PROP_GRAPHICS_DEVICES:
+        g_value_set_boxed (value, self->devices);
+        break;
+
       case PROP_EXIT_STATUS:
         g_value_set_int (value, self->exit_status);
         break;
@@ -173,9 +557,9 @@ srt_graphics_get_property (GObject *object,
 
 static void
 srt_graphics_set_property (GObject *object,
-                          guint prop_id,
-                          const GValue *value,
-                          GParamSpec *pspec)
+                           guint prop_id,
+                           const GValue *value,
+                           GParamSpec *pspec)
 {
   SrtGraphics *self = SRT_GRAPHICS (object);
   const char *tmp;
@@ -239,6 +623,12 @@ srt_graphics_set_property (GObject *object,
         self->version_string = g_value_dup_string (value);
         break;
 
+      case PROP_GRAPHICS_DEVICES:
+        /* Construct only */
+        g_return_if_fail (self->devices == NULL);
+        self->devices = g_value_dup_boxed (value);
+        break;
+
       case PROP_EXIT_STATUS:
         self->exit_status = g_value_get_int (value);
         break;
@@ -252,6 +642,16 @@ srt_graphics_set_property (GObject *object,
     }
 }
 
+static void
+srt_graphics_dispose (GObject *object)
+{
+  SrtGraphics *self = SRT_GRAPHICS (object);
+
+  g_clear_pointer (&self->devices, g_ptr_array_unref);
+
+  G_OBJECT_CLASS (srt_graphics_parent_class)->dispose (object);
+}
+
 static void
 srt_graphics_finalize (GObject *object)
 {
@@ -273,6 +673,7 @@ srt_graphics_class_init (SrtGraphicsClass *cls)
 
   object_class->get_property = srt_graphics_get_property;
   object_class->set_property = srt_graphics_set_property;
+  object_class->dispose = srt_graphics_dispose;
   object_class->finalize = srt_graphics_finalize;
 
   properties[PROP_ISSUES] =
@@ -327,6 +728,12 @@ srt_graphics_class_init (SrtGraphicsClass *cls)
                          G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                          G_PARAM_STATIC_STRINGS);
 
+  properties[PROP_GRAPHICS_DEVICES] =
+    g_param_spec_boxed ("graphics-devices", "List of graphics devices", "List of #SrtGraphicsDevice, representing the graphical cards.",
+                        G_TYPE_PTR_ARRAY,
+                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                        G_PARAM_STATIC_STRINGS);
+
   properties[PROP_EXIT_STATUS] =
     g_param_spec_int ("exit-status", "Exit status", "Exit status of helper(s) executed. 0 on success, positive on unsuccessful exit(), -1 if killed by a signal or not run at all",
                       -1,
@@ -352,7 +759,9 @@ srt_graphics_class_init (SrtGraphicsClass *cls)
  * @renderer_string: (out) (transfer none) (not optional):
  */
 static SrtGraphicsIssues
-_srt_process_wflinfo (JsonNode *node, const gchar **version_string, const gchar **renderer_string)
+_srt_process_wflinfo (JsonNode *node,
+                      gchar **version_string,
+                      const gchar **renderer_string)
 {
   g_return_val_if_fail (version_string != NULL, SRT_GRAPHICS_ISSUES_UNKNOWN);
   g_return_val_if_fail (renderer_string != NULL, SRT_GRAPHICS_ISSUES_UNKNOWN);
@@ -388,7 +797,7 @@ _srt_process_wflinfo (JsonNode *node, const gchar **version_string, const gchar
       return issues;
     }
 
-  *version_string = json_object_get_string_member (sub_object, "version string");
+  *version_string = g_strdup (json_object_get_string_member (sub_object, "version string"));
   *renderer_string = json_object_get_string_member (sub_object, "renderer string");
 
   /* Check renderer to see if we are using software rendering */
@@ -402,73 +811,59 @@ _srt_process_wflinfo (JsonNode *node, const gchar **version_string, const gchar
 }
 
 /*
- * @node: The JsonNode to process the vulkaninfo results from.
- * @new_version_string: (out) (transfer full) (not optional):
- * @renderer_string: (out) (transfer none) (not optional):
+ * @node (not nullable):
+ * @version_string (not optional) (out):
+ * @device (not optional) (out):
  */
 static SrtGraphicsIssues
-_srt_process_vulkaninfo (JsonNode *node, gchar **new_version_string, const gchar **renderer_string)
+_srt_process_check_vulkan_info (JsonNode *node,
+                                gchar **version_string,
+                                SrtGraphicsDevice **device)
 {
-  g_return_val_if_fail (new_version_string != NULL, SRT_GRAPHICS_ISSUES_UNKNOWN);
-  g_return_val_if_fail (renderer_string != NULL, SRT_GRAPHICS_ISSUES_UNKNOWN);
-
-  SrtGraphicsIssues issues = SRT_GRAPHICS_ISSUES_NONE;
-
-  if (node == NULL)
-    {
-      g_debug ("The json output is empty");
-      issues |= SRT_GRAPHICS_ISSUES_CANNOT_LOAD;
-      return issues;
-    }
-
-  JsonObject *object = json_node_get_object (node);
-  JsonNode *sub_node = NULL;
+  JsonObject *object = NULL;
   JsonObject *sub_object = NULL;
+  JsonNode *sub_node = NULL;
+  const gchar *device_name = NULL;
+  const gchar *api_version = NULL;
+  const gchar *driver_version = NULL;
+  const gchar *vendor_id = NULL;
+  const gchar *device_id = NULL;
+  SrtVkPhysicalDeviceType device_type;
 
-  // Parse vulkaninfo output
-  unsigned int api_version = 0;
-  unsigned int hw_vendor = 0;
-  unsigned int hw_device = 0;
-  unsigned int driver_version = 0;
+  /* Until we parse the drawing test results, we assume that we are not
+   * able to draw with this device */
+  SrtGraphicsIssues issues = SRT_GRAPHICS_ISSUES_CANNOT_DRAW;
 
-  if (!json_object_has_member (object, "VkPhysicalDeviceProperties"))
-    {
-      g_debug ("The json output doesn't contain VkPhysicalDeviceProperties");
-      issues |= SRT_GRAPHICS_ISSUES_CANNOT_LOAD;
-      return issues;
-    }
+  object = json_node_get_object (node);
+
+  /* We only parse the device information, not the drawing test result */
+  if (!json_object_has_member (object, "device-info"))
+    return issues;
 
-  sub_node = json_object_get_member (object, "VkPhysicalDeviceProperties");
+  sub_node = json_object_get_member (object, "device-info");
   sub_object = json_node_get_object (sub_node);
 
-  if (!json_object_has_member (sub_object, "deviceName") ||
-      !json_object_has_member (sub_object, "driverVersion") ||
-      !json_object_has_member (sub_object, "apiVersion") ||
-      !json_object_has_member (sub_object, "deviceID") ||
-      !json_object_has_member (sub_object, "vendorID"))
-    {
-      g_debug ("Json output is missing deviceName or driverVersion");
-      issues |= SRT_GRAPHICS_ISSUES_CANNOT_LOAD;
-      return issues;
-    }
+  device_name = json_object_get_string_member_with_default (sub_object, "device-name",
+                                                            NULL);
+  device_type = json_object_get_int_member_with_default (sub_object, "device-type", 0);
+  api_version = json_object_get_string_member_with_default (sub_object, "api-version",
+                                                            NULL);
+  driver_version = json_object_get_string_member_with_default (sub_object, "driver-version",
+                                                               NULL);
+  vendor_id = json_object_get_string_member_with_default (sub_object, "vendor-id",
+                                                          NULL);
+  device_id = json_object_get_string_member_with_default (sub_object, "device-id",
+                                                          NULL);
 
-  api_version = json_object_get_int_member (sub_object, "apiVersion");
-  hw_vendor = json_object_get_int_member (sub_object, "vendorID");
-  driver_version = json_object_get_int_member (sub_object, "driverVersion");
-  hw_device = json_object_get_int_member (sub_object, "deviceID");
+  *version_string = g_strdup_printf ("%s (device %s:%s) (driver %s)",
+                                     api_version, vendor_id, device_id, driver_version);
 
-  *new_version_string = g_strdup_printf ("%u.%u.%u (device %04x:%04x) (driver %u.%u.%u)",
-                                        VK_VERSION_MAJOR (api_version),
-                                        VK_VERSION_MINOR (api_version),
-                                        VK_VERSION_PATCH (api_version),
-                                        hw_vendor,
-                                        hw_device,
-                                        VK_VERSION_MAJOR (driver_version),
-                                        VK_VERSION_MINOR (driver_version),
-                                        VK_VERSION_PATCH (driver_version));
-  *renderer_string = json_object_get_string_member (sub_object, "deviceName");
+  if (device_type == SRT_VK_PHYSICAL_DEVICE_TYPE_CPU)
+    issues |= SRT_GRAPHICS_ISSUES_SOFTWARE_RENDERING;
+
+  *device = _srt_graphics_device_new (device_name, api_version, driver_version,
+                                      vendor_id, device_id, device_type, issues);
 
-  /* NOTE: No need to check for software rendering with vulkan yet */
   return issues;
 }
 
@@ -586,13 +981,12 @@ _argv_for_graphics_test (const char *helpers_path,
         break;
 
       case SRT_RENDERING_INTERFACE_VULKAN:
-        argv = _srt_get_helper (helpers_path, multiarch_tuple, "vulkaninfo",
+        argv = _srt_get_helper (helpers_path, multiarch_tuple, "check-vulkan",
                                 flags, error);
 
         if (argv == NULL)
           goto out;
 
-        g_ptr_array_add (argv, g_strdup ("-j"));
         break;
 
       case SRT_RENDERING_INTERFACE_VDPAU:
@@ -627,28 +1021,6 @@ out:
   return argv;
 }
 
-static GPtrArray *
-_argv_for_check_vulkan (const char *helpers_path,
-                        SrtTestFlags test_flags,
-                        const char *multiarch_tuple,
-                        GError **error)
-{
-  GPtrArray *argv;
-  SrtHelperFlags flags = SRT_HELPER_FLAGS_TIME_OUT;
-
-  if (test_flags & SRT_TEST_FLAGS_TIME_OUT_SOONER)
-    flags |= SRT_HELPER_FLAGS_TIME_OUT_SOONER;
-
-  argv = _srt_get_helper (helpers_path, multiarch_tuple, "check-vulkan",
-                          flags, error);
-
-  if (argv == NULL)
-    return NULL;
-
-  g_ptr_array_add (argv, NULL);
-  return argv;
-}
-
 static GPtrArray *
 _argv_for_check_gl (const char *helpers_path,
                     SrtTestFlags test_flags,
@@ -998,8 +1370,7 @@ _srt_check_graphics (gchar **envp,
   int exit_status = -1;
   int terminating_signal = 0;
   g_autoptr(JsonNode) node = NULL;
-  const gchar *version_string = NULL;
-  gchar *new_version_string = NULL;
+  g_autofree gchar *version_string = NULL;
   const gchar *renderer_string = NULL;
   GError *error = NULL;
   SrtGraphicsIssues issues = SRT_GRAPHICS_ISSUES_NONE;
@@ -1008,6 +1379,9 @@ _srt_check_graphics (gchar **envp,
   const gchar *ld_preload;
   gchar *filtered_preload = NULL;
   SrtGraphicsLibraryVendor library_vendor = SRT_GRAPHICS_LIBRARY_VENDOR_UNKNOWN;
+  g_auto(GStrv) json_output = NULL;
+  g_autoptr(GPtrArray) graphics_device = g_ptr_array_new_with_free_func (g_object_unref);
+  gsize i;
 
   g_return_val_if_fail (details_out == NULL || *details_out == NULL, SRT_GRAPHICS_ISSUES_UNKNOWN);
   g_return_val_if_fail (((unsigned) window_system) < SRT_N_WINDOW_SYSTEMS, SRT_GRAPHICS_ISSUES_UNKNOWN);
@@ -1046,10 +1420,10 @@ _srt_check_graphics (gchar **envp,
     {
       case SRT_RENDERING_INTERFACE_GL:
       case SRT_RENDERING_INTERFACE_GLESV2:
-      case SRT_RENDERING_INTERFACE_VULKAN:
         non_zero_wait_status_issue = SRT_GRAPHICS_ISSUES_CANNOT_LOAD;
         break;
 
+      case SRT_RENDERING_INTERFACE_VULKAN:
       case SRT_RENDERING_INTERFACE_VDPAU:
       case SRT_RENDERING_INTERFACE_VAAPI:
         /* The test here tries to draw an offscreen X11 window */
@@ -1070,8 +1444,13 @@ _srt_check_graphics (gchar **envp,
                              FALSE,
                              non_zero_wait_status_issue);
 
-  if (issues != SRT_GRAPHICS_ISSUES_NONE)
+  if (rendering_interface != SRT_RENDERING_INTERFACE_VULKAN
+      && issues != SRT_GRAPHICS_ISSUES_NONE)
     {
+      /* For Vulkan `LIBGL_DEBUG` has no effect. Also we try to continue even
+       * if we faced some issues because we might still have a valid JSON in
+       * output */
+
       // Issues found, so run again with LIBGL_DEBUG=verbose set in environment
       issues |= _srt_run_helper (&my_environ,
                                  &output,
@@ -1090,8 +1469,6 @@ _srt_check_graphics (gchar **envp,
     {
       case SRT_RENDERING_INTERFACE_GL:
       case SRT_RENDERING_INTERFACE_GLESV2:
-      case SRT_RENDERING_INTERFACE_VULKAN:
-
         node = json_from_string (output, &error);
         if (node == NULL)
           {
@@ -1114,21 +1491,7 @@ _srt_check_graphics (gchar **envp,
 
             goto out;
           }
-        break;
-
-      case SRT_RENDERING_INTERFACE_VDPAU:
-      case SRT_RENDERING_INTERFACE_VAAPI:
-        /* The output is in plan text, nothing to do here */
-        break;
 
-      default:
-        g_return_val_if_reached (SRT_GRAPHICS_ISSUES_UNKNOWN);
-    }
-
-  switch (rendering_interface)
-    {
-      case SRT_RENDERING_INTERFACE_GL:
-      case SRT_RENDERING_INTERFACE_GLESV2:
         issues |= _srt_process_wflinfo (node, &version_string, &renderer_string);
 
         if (issues != SRT_GRAPHICS_ISSUES_NONE)
@@ -1193,39 +1556,109 @@ _srt_check_graphics (gchar **envp,
         break;
 
       case SRT_RENDERING_INTERFACE_VULKAN:
-        issues |= _srt_process_vulkaninfo (node, &new_version_string, &renderer_string);
-        if (new_version_string != NULL)
+        if (output == NULL || output[0] == '\0')
           {
-            version_string = new_version_string;
+            g_debug ("The helper output is empty");
+            issues |= SRT_GRAPHICS_ISSUES_CANNOT_LOAD;
+            goto out;
           }
 
-        /* Now perform *-check-vulkan drawing test */
-        g_ptr_array_unref (argv);
-        g_clear_pointer (&output, g_free);
+        json_output = g_strsplit (output, "\n", -1);
 
-        argv = _argv_for_check_vulkan (helpers_path,
-                                       test_flags,
-                                       multiarch_tuple,
-                                       &error);
-
-        if (argv == NULL)
+        for (i = 0; json_output[i] != NULL; i++)
           {
-            issues |= SRT_GRAPHICS_ISSUES_CANNOT_DRAW;
-            /* Put the error message in the 'messages' */
-            child_stderr2 = g_strdup (error->message);
-            goto out;
+            g_autofree gchar *new_version_string = NULL;
+            g_autoptr(JsonNode) this_node = NULL;
+            SrtGraphicsDevice *device = NULL;
+            SrtGraphicsIssues device_issues = SRT_GRAPHICS_ISSUES_NONE;
+            this_node = json_from_string (json_output[i], &error);
+            if (this_node == NULL)
+              {
+                if (error != NULL)
+                  {
+                    g_debug ("The Vulkan helper output is not a valid JSON: %s", error->message);
+                    g_clear_error (&error);
+                  }
+                break;
+              }
+
+            device_issues |= _srt_process_check_vulkan_info (this_node, &new_version_string,
+                                                             &device);
+
+            /* If we were unable to get the device info from this node, it
+             * probably means that we already checked all the "device-info"
+             * JSON objects. There is no need to continue because drawing
+             * tests always follow the device info. */
+            if (device == NULL)
+              break;
+
+            /* If the GPU 0 is a software rendering, we propagate this info to
+             * the general Vulkan issues too. */
+            if (i == 0 && device_issues & SRT_GRAPHICS_ISSUES_SOFTWARE_RENDERING)
+              issues |= SRT_GRAPHICS_ISSUES_SOFTWARE_RENDERING;
+
+            /* If this is the first device that we have, store its version and
+             * renderer for the SrtGraphics object */
+            if (version_string == NULL)
+              version_string = g_strdup (new_version_string);
+
+            if (renderer_string == NULL)
+              renderer_string = srt_graphics_device_get_name (device);
+
+            g_ptr_array_add (graphics_device, device);
           }
 
-        /* Now run and report exit code/messages if failure */
-        issues |= _srt_run_helper (&my_environ,
-                                   &output,
-                                   &child_stderr2,
-                                   argv,
-                                   &wait_status,
-                                   &exit_status,
-                                   &terminating_signal,
-                                   FALSE,
-                                   SRT_GRAPHICS_ISSUES_CANNOT_DRAW);
+        for (i = 0; json_output[i] != NULL; i++)
+          {
+            JsonObject *object = NULL;
+            JsonObject *sub_object = NULL;
+            JsonNode *sub_node = NULL;
+            gboolean can_draw;
+            gsize index;
+            const gchar *messages = NULL;
+            g_autoptr(JsonNode) this_node = NULL;
+            this_node = json_from_string (json_output[i], &error);
+            if (this_node == NULL)
+              {
+                if (error != NULL)
+                  {
+                    g_debug ("The Vulkan helper output is not a valid JSON: %s", error->message);
+                    g_clear_error (&error);
+                  }
+                /* Apparently we reached the final empty line */
+                break;
+              }
+
+            object = json_node_get_object (this_node);
+            /* We only parse the drawing test result */
+            if (!json_object_has_member (object, "test"))
+              continue;
+
+            sub_node = json_object_get_member (object, "test");
+            sub_object = json_node_get_object (sub_node);
+
+            if (!json_object_has_member (sub_object, "index"))
+              {
+                g_debug ("The Vulkan helper output seems to be malformed");
+                break;
+              }
+
+            index = json_object_get_int_member (sub_object, "index");
+            can_draw = json_object_get_boolean_member_with_default (sub_object, "can-draw",
+                                                                    FALSE);
+            messages = json_object_get_string_member_with_default (sub_object, "error-message",
+                                                                   NULL);
+
+            if (graphics_device->len < index + 1)
+              {
+                g_debug ("Apparently the Vulkan helper returned more test results than devices info");
+                break;
+              }
+            _srt_graphics_device_set_can_draw (g_ptr_array_index (graphics_device, index),
+                                               can_draw);
+            _srt_graphics_device_set_messages (g_ptr_array_index (graphics_device, index),
+                                               messages);
+          }
         break;
 
       case SRT_RENDERING_INTERFACE_VDPAU:
@@ -1240,8 +1673,8 @@ _srt_check_graphics (gchar **envp,
 
 out:
 
-  /* If we have stderr (or error messages) from both vulkaninfo and
-   * check-vulkan, combine them */
+  /* If we have stderr (or error messages) from both wflinfo and
+   * check-gl, combine them */
   if (child_stderr2 != NULL && child_stderr2[0] != '\0')
     {
       gchar *tmp = g_strconcat (child_stderr, child_stderr2, NULL);
@@ -1257,12 +1690,12 @@ out:
                                       library_vendor,
                                       renderer_string,
                                       version_string,
+                                      graphics_device,
                                       issues,
                                       child_stderr,
                                       exit_status,
                                       terminating_signal);
 
-  g_free (new_version_string);
   g_clear_pointer (&argv, g_ptr_array_unref);
   g_free (output);
   g_free (child_stderr);
@@ -1464,6 +1897,29 @@ srt_graphics_get_messages (SrtGraphics *self)
   return self->messages;
 }
 
+/**
+ * srt_graphics_get_devices:
+ * @self: a graphics object
+ *
+ * Return the list of graphics devices that have been found.
+ *
+ * Returns: (transfer full) (element-type SrtGraphicsDevice): The graphics
+ *  devices. Free with `g_list_free_full (list, g_object_unref)`.
+ */
+GList *
+srt_graphics_get_devices (SrtGraphics *self)
+{
+  GList *ret = NULL;
+  guint i;
+
+  g_return_val_if_fail (SRT_IS_GRAPHICS (self), NULL);
+
+  for (i = 0; self->devices != NULL && i < self->devices->len; i++)
+    ret = g_list_prepend (ret, g_object_ref (g_ptr_array_index (self->devices, i)));
+
+  return g_list_reverse (ret);
+}
+
 /**
  * _srt_graphics_get_from_report:
  * @json_obj: (not nullable): A JSON Object representing an ABI,
@@ -1599,6 +2055,7 @@ _srt_graphics_get_from_report (JsonObject *json_obj,
                                         library_vendor,
                                         renderer,
                                         version,
+                                        NULL,  //TODO
                                         graphics_issues,
                                         messages,
                                         exit_status,
diff --git a/steam-runtime-tools/graphics.h b/steam-runtime-tools/graphics.h
index a5ad1d0804a3b8ffef59749f60bfeba4b06d02ab..da2cf0e84da3b417769b6e37893e2d1e5eedc2f9 100644
--- a/steam-runtime-tools/graphics.h
+++ b/steam-runtime-tools/graphics.h
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2019 Collabora Ltd.
+ * Copyright © 2019-2021 Collabora Ltd.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -47,6 +47,18 @@ typedef struct _SrtGraphicsClass SrtGraphicsClass;
 _SRT_PUBLIC
 GType srt_graphics_get_type (void);
 
+typedef struct _SrtGraphicsDevice SrtGraphicsDevice;
+typedef struct _SrtGraphicsDeviceClass SrtGraphicsDeviceClass;
+
+#define SRT_TYPE_GRAPHICS_DEVICE (srt_graphics_device_get_type ())
+#define SRT_GRAPHICS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SRT_TYPE_GRAPHICS_DEVICE, SrtGraphicsDevice))
+#define SRT_GRAPHICS_DEVICE_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST ((cls), SRT_TYPE_GRAPHICS_DEVICE, SrtGraphicsDeviceClass))
+#define SRT_IS_GRAPHICS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SRT_TYPE_GRAPHICS_DEVICE))
+#define SRT_IS_GRAPHICS_DEVICE_CLASS(cls) (G_TYPE_CHECK_CLASS_TYPE ((cls), SRT_TYPE_GRAPHICS_DEVICE))
+#define SRT_GRAPHICS_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SRT_TYPE_GRAPHICS_DEVICE, SrtGraphicsDeviceClass)
+_SRT_PUBLIC
+GType srt_graphics_device_get_type (void);
+
 /* Backward compatibility with previous steam-runtime-tools naming */
 #define SRT_GRAPHICS_ISSUES_INTERNAL_ERROR SRT_GRAPHICS_ISSUES_UNKNOWN
 
@@ -133,6 +145,48 @@ typedef enum
 
 #define SRT_N_RENDERING_INTERFACES (SRT_RENDERING_INTERFACE_VAAPI + 1)
 
+/**
+ * SrtVkPhysicalDeviceType:
+ * @SRT_VK_PHYSICAL_DEVICE_TYPE_OTHER: The GPU does not match any other available types
+ * @SRT_VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: The GPU is typically one embedded in or
+ *  tightly coupled with the host
+ * @SRT_VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: The GPU is typically a separate processor
+ *  connected to the host via an interlink.
+ * @SRT_VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: The GPU is typically a virtual node in a
+ *  virtualization environment
+ * @SRT_VK_PHYSICAL_DEVICE_TYPE_CPU: The GPU is typically running on the same processors
+ *  as the host (software rendering such as llvmpipe)
+ *
+ * These enums have been taken from the VkPhysicalDeviceType Vulkan specs.
+ * Please keep them in sync.
+ * https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VkPhysicalDeviceType.html
+ */
+typedef enum
+{
+  SRT_VK_PHYSICAL_DEVICE_TYPE_OTHER = 0,
+  SRT_VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
+  SRT_VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2,
+  SRT_VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3,
+  SRT_VK_PHYSICAL_DEVICE_TYPE_CPU = 4,
+} SrtVkPhysicalDeviceType;
+
+_SRT_PUBLIC
+SrtGraphicsIssues srt_graphics_device_get_issues (SrtGraphicsDevice *self);
+_SRT_PUBLIC
+const char *srt_graphics_device_get_name (SrtGraphicsDevice *self);
+_SRT_PUBLIC
+const char *srt_graphics_device_get_api_version (SrtGraphicsDevice *self);
+_SRT_PUBLIC
+const char *srt_graphics_device_get_driver_version (SrtGraphicsDevice *self);
+_SRT_PUBLIC
+const char *srt_graphics_device_get_vendor_id (SrtGraphicsDevice *self);
+_SRT_PUBLIC
+const char *srt_graphics_device_get_device_id (SrtGraphicsDevice *self);
+_SRT_PUBLIC
+const char *srt_graphics_device_get_messages (SrtGraphicsDevice *self);
+_SRT_PUBLIC
+SrtVkPhysicalDeviceType srt_graphics_device_get_device_type (SrtGraphicsDevice *self);
+
 _SRT_PUBLIC
 const char *srt_graphics_get_multiarch_tuple (SrtGraphics *self);
 _SRT_PUBLIC
@@ -151,6 +205,8 @@ const char *srt_graphics_get_renderer_string (SrtGraphics *self);
 _SRT_PUBLIC
 const char *srt_graphics_get_messages (SrtGraphics *self);
 _SRT_PUBLIC
+GList *srt_graphics_get_devices (SrtGraphics *self);
+_SRT_PUBLIC
 gchar *srt_graphics_dup_parameters_string (SrtGraphics *self);
 _SRT_PUBLIC
 int srt_graphics_get_exit_status (SrtGraphics *self);
@@ -340,6 +396,7 @@ const gchar *srt_glx_icd_get_library_path (SrtGlxIcd *self);
 
 #ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtGraphics, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtGraphicsDevice, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtEglIcd, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtDriDriver, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtVaApiDriver, g_object_unref)
diff --git a/tests/graphics.c b/tests/graphics.c
index b8e527bb4daedf9a844630540fabfdf3be37dcc6..bd6e3921ce36050efa4d7054660becd1a997ffac 100644
--- a/tests/graphics.c
+++ b/tests/graphics.c
@@ -222,6 +222,7 @@ test_object (Fixture *f,
                                SRT_GRAPHICS_LIBRARY_VENDOR_GLVND,
                                SRT_TEST_GOOD_GRAPHICS_RENDERER,
                                SRT_TEST_GOOD_GRAPHICS_VERSION,
+                               NULL,
                                SRT_GRAPHICS_ISSUES_NONE,
                                "",
                                0,
@@ -2465,6 +2466,7 @@ static const GraphicsTest graphics_test[] =
     .multiarch_tuple = "mock-good",
     .renderer_string = SRT_TEST_GOOD_GRAPHICS_RENDERER,
     .version_string = SRT_TEST_GOOD_VULKAN_VERSION,
+    .messages = SRT_TEST_GOOD_VULKAN_MESSAGES,
     .vendor_neutral = TRUE,
   },
 
@@ -2472,22 +2474,22 @@ static const GraphicsTest graphics_test[] =
     .description = "bad vulkan",
     .window_system = SRT_WINDOW_SYSTEM_X11,
     .rendering_interface = SRT_RENDERING_INTERFACE_VULKAN,
-    .issues = SRT_GRAPHICS_ISSUES_CANNOT_LOAD,
+    .issues = SRT_GRAPHICS_ISSUES_CANNOT_LOAD | SRT_GRAPHICS_ISSUES_CANNOT_DRAW,
     .multiarch_tuple = "mock-bad",
-    .messages = "/build/vulkan-tools/src/Vulkan-Tools-1.1.114/vulkaninfo/vulkaninfo.c:5884: failed with VK_ERROR_INITIALIZATION_FAILED\n",
+    .messages = SRT_TEST_BAD_VULKAN_MESSAGES,
     .exit_status = 1,
     .vendor_neutral = TRUE,
   },
 
   {
-    .description = "good vulkan driver but check-vulkan failure",
+    .description = "good vulkan driver but drawing test fails",
     .window_system = SRT_WINDOW_SYSTEM_X11,
     .rendering_interface = SRT_RENDERING_INTERFACE_VULKAN,
     .issues = SRT_GRAPHICS_ISSUES_CANNOT_DRAW,
     .multiarch_tuple = "mock-mixed",
     .renderer_string = SRT_TEST_GOOD_GRAPHICS_RENDERER,
     .version_string = SRT_TEST_GOOD_VULKAN_VERSION,
-    .messages = "failed to create window surface!\n",
+    .messages = SRT_TEST_GOOD_VULKAN_MESSAGES,
     .exit_status = 1,
     .vendor_neutral = TRUE,
   },
diff --git a/tests/json-report/full-good-report.json b/tests/json-report/full-good-report.json
index 05b01afda1950c36f802cd68bc62394135c8e538..d1e6b2e1789f3f5793e5a392a7eab3999a5d0266 100644
--- a/tests/json-report/full-good-report.json
+++ b/tests/json-report/full-good-report.json
@@ -71,7 +71,8 @@
             "cannot-load",
             "cannot-draw"
           ],
-          "exit-status" : 1
+          "exit-status" : 1,
+          "devices" : []
         },
         "x11/vdpau" : {
           "renderer" : "G3DVL VDPAU Driver Shared Library version 1.0\n",
@@ -138,7 +139,8 @@
       "graphics-details" : {
         "x11/vulkan" : {
           "renderer" : "AMD Radeon RX 5700 XT",
-          "version" : "1.2.136 (device 1002:731f) (driver 2.0.140)"
+          "version" : "1.2.136 (device 1002:731f) (driver 2.0.140)",
+          "devices" : []
         },
         "x11/vdpau" : {
           "renderer" : "G3DVL VDPAU Driver Shared Library version 1.0\n",
diff --git a/tests/meson.build b/tests/meson.build
index f395896ec7c83161a2ae6e1e18b6afffd733f7ba..a6b4f79dea839308be9cd30ceb09412129d5f9c6 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -125,7 +125,6 @@ install_data('generate-sysroots.py', install_dir : tests_dir)
 # These are all the same: they just exit 0.
 foreach helper : [
   'mock-good-check-gl',
-  'mock-good-check-vulkan',
   'mock-software-check-gl',
   'mock-true',
 ]
@@ -264,14 +263,14 @@ foreach helper : [
   'mock-bad-check-vdpau',
   'mock-bad-check-vulkan',
   'mock-bad-check-xdg-portal',
-  'mock-bad-vulkaninfo',
   'mock-good-check-va-api',
   'mock-good-check-vdpau',
+  'mock-good-check-vulkan',
   'mock-good-check-xdg-portal',
   'mock-good-flatpak-check-xdg-portal',
-  'mock-good-vulkaninfo',
   'mock-hanging-check-xdg-portal',
   'mock-hanging-wflinfo',
+  'mock-mixed-check-vulkan',
   'mock-sigusr-wflinfo',
 ]
   executable(
@@ -286,13 +285,6 @@ endforeach
 # These need to be the same as their -good- counterparts, to exercise
 # the case where the preliminary check succeeds, but actually rendering
 # a window fails (hence "mixed").
-executable(
-  'mock-mixed-vulkaninfo',
-  'mock-good-vulkaninfo.c',
-  include_directories : project_include_dirs,
-  install: true,
-  install_dir: tests_dir
-)
 executable(
   'mock-mixed-wflinfo',
   'mock-good-wflinfo.c',
@@ -302,20 +294,15 @@ executable(
   install_dir: tests_dir
 )
 
-# These are all essentially the same as mock-bad-check-vulkan: they
-# fail with a message on stderr.
-foreach helper : [
+# mock-bad-check-gl is essentially the same as mock-bad-check-vulkan:
+# it fails with a message on stderr.
+executable(
   'mock-bad-check-gl',
-  'mock-mixed-check-vulkan',
-]
-  executable(
-    helper,
-    'mock-bad-check-vulkan.c',
-    include_directories : project_include_dirs,
-    install: true,
-    install_dir: tests_dir
-  )
-endforeach
+  'mock-bad-check-vulkan.c',
+  include_directories : project_include_dirs,
+  install: true,
+  install_dir: tests_dir
+)
 
 # Helpers with a GLib dependency and one source file of the same name
 # as the helper itself.
diff --git a/tests/mock-bad-check-vulkan.c b/tests/mock-bad-check-vulkan.c
index 3e3fc6050282bc0680a9269f5e47c7dd6bc4283c..c0786bfd490b9a9490dd96f4e413cd03a28a3bab 100644
--- a/tests/mock-bad-check-vulkan.c
+++ b/tests/mock-bad-check-vulkan.c
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2019 Collabora Ltd.
+ * Copyright © 2019-2021 Collabora Ltd.
  *
  * SPDX-License-Identifier: MIT
  *
@@ -25,12 +25,13 @@
 
 #include <stdio.h>
 
+#include "../steam-runtime-tools/graphics-test-defines.h"
+
 int
 main (int argc,
       char **argv)
 {
   // Give bad output
-  fprintf (stderr, "failed to create window surface!\n");
+  fprintf (stderr, SRT_TEST_BAD_VULKAN_MESSAGES);
   return 1;
 }
-
diff --git a/tests/mock-good-check-vulkan.c b/tests/mock-good-check-vulkan.c
new file mode 100644
index 0000000000000000000000000000000000000000..f002d89b5eb14cda36d6c237be2095bbfbf432d0
--- /dev/null
+++ b/tests/mock-good-check-vulkan.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2021 Collabora Ltd.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#include "../steam-runtime-tools/graphics-test-defines.h"
+
+int
+main (int argc,
+      char **argv)
+{
+  // Give good output
+  fprintf (stderr, SRT_TEST_GOOD_VULKAN_MESSAGES);
+
+  printf ("{\"device-info\":{"
+          "\"device-name\":\"" SRT_TEST_GOOD_GRAPHICS_RENDERER "\","
+          "\"device-type\":2,"
+          "\"api-version\":\"" SRT_TEST_GOOD_GRAPHICS_API_VERSION "\","
+          "\"driver-version\":\"" SRT_TEST_GOOD_GRAPHICS_DRIVER_VERSION "\","
+          "\"vendor-id\":\"" SRT_TEST_GOOD_GRAPHICS_VENDOR_ID "\","
+          "\"device-id\":\"" SRT_TEST_GOOD_GRAPHICS_DEVICE_ID "\"}}\n"
+          "{\"device-info\":{"
+          "\"device-name\":\"" SRT_TEST_SOFTWARE_GRAPHICS_RENDERER "\","
+          "\"device-type\":4,"
+          "\"api-version\":\"" SRT_TEST_SOFTWARE_GRAPHICS_API_VERSION "\","
+          "\"driver-version\":\"" SRT_TEST_SOFTWARE_GRAPHICS_DRIVER_VERSION "\","
+          "\"vendor-id\":\"" SRT_TEST_SOFTWARE_GRAPHICS_VENDOR_ID "\","
+          "\"device-id\":\"" SRT_TEST_SOFTWARE_GRAPHICS_DEVICE_ID "\"}}\n"
+          "{\"test\":{"
+          "\"index\":0,"
+          "\"can-draw\":true}}\n"
+          "{\"test\":{"
+          "\"index\":1,"
+          "\"can-draw\":true}}\n");
+
+  return 0;
+}
+
diff --git a/tests/mock-good-vulkaninfo.c b/tests/mock-good-vulkaninfo.c
deleted file mode 100644
index 26c191bfda7d17cde928c617886b8ea27ff5e866..0000000000000000000000000000000000000000
--- a/tests/mock-good-vulkaninfo.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright © 2019 Collabora Ltd.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <stdio.h>
-
-#include "../steam-runtime-tools/graphics-test-defines.h"
-
-int
-main (int argc,
-      char **argv)
-{
-  // Give good output
-  printf ("{\n\t\"$schema\": \"https://schema.khronos.org/vulkan/devsim_1_0_0.json#\",\n"
-          "\t\"comments\": {\n\t\t\"desc\": \"JSON configuration file describing GPU 0. Generated using the vulkaninfo program.\","
-          "\"vulkanApiVersion\": \"1.1.121\"\n\t},\n\t\"ArrayOfVkLayerProperties\": [\n\t\t{\n"
-          "\t\t\t\"layerName\": \"VK_LAYER_LUNARG_standard_validation\",\n"
-          "\t\t\t\"specVersion\": 4194425,\n"
-          "\t\t\t\"implementationVersion\": 1,\n"
-          "\t\t\t\"description\": \"LunarG Standard Validation Layer\"\n"
-          "\t\t},\n"
-          "\t\t{\n"
-          "\t\t\t\"layerName\": \"VK_LAYER_VALVE_steam_fossilize_32\",\n"
-          "\t\t\t\"specVersion\": 4198473,\n"
-          "\t\t\t\"implementationVersion\": 1,\n"
-          "\t\t\t\"description\": \"Steam Pipeline Caching Layer\"\n"
-          "\t\t},\n"
-          "\t\t{\n"
-          "\t\t\t\"layerName\": \"VK_LAYER_VALVE_steam_fossilize_64\",\n"
-          "\t\t\t\"specVersion\": 4198473,\n"
-          "\t\t\t\"implementationVersion\": 1,\n"
-          "\t\t\t\"description\": \"Steam Pipeline Caching Layer\"\n"
-          "\t\t},\n"
-          "\t\t{\n"
-          "\t\t\t\"layerName\": \"VK_LAYER_VALVE_steam_overlay_32\",\n"
-          "\t\t\t\"specVersion\": 4198473,\n"
-          "\t\t\t\"implementationVersion\": 1,\n"
-          "\t\t\t\"description\": \"Steam Overlay Layer\"\n"
-          "\t\t},\n"
-          "\t\t{\n"
-          "\t\t\t\"layerName\": \"VK_LAYER_VALVE_steam_overlay_64\",\n"
-          "\t\t\t\"specVersion\": 4198473,\n"
-          "\t\t\t\"implementationVersion\": 1,\n"
-          "\t\t\t\"description\": \"Steam Overlay Layer\"\n"
-          "\t\t}\n"
-          "\t],\n"
-          "\t\"VkPhysicalDeviceProperties\": {\n"
-          "\t\t\"apiVersion\": 4198502,\n"
-          "\t\t\"driverVersion\": "
-          SRT_TEST_GOOD_VULKAN_DRIVER_VERSION
-          ",\n"
-          "\t\t\"vendorID\": 32902,\n"
-          "\t\t\"deviceID\": 1042,\n"
-          "\t\t\"deviceType\": 1,\n"
-          "\t\t\"deviceName\": \""
-          SRT_TEST_GOOD_GRAPHICS_RENDERER
-          "\"\n"
-          "\t}\n"
-          "}\n");
-  return 0;
-}
-
diff --git a/tests/mock-mixed-check-vulkan.c b/tests/mock-mixed-check-vulkan.c
new file mode 100644
index 0000000000000000000000000000000000000000..f932d6255eeb431f5d2667c6fe4f05f1597b206f
--- /dev/null
+++ b/tests/mock-mixed-check-vulkan.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright © 2021 Collabora Ltd.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#include "../steam-runtime-tools/graphics-test-defines.h"
+
+int
+main (int argc,
+      char **argv)
+{
+  fprintf (stderr, SRT_TEST_GOOD_VULKAN_MESSAGES);
+
+  printf ("{\"device-info\":{"
+          "\"device-name\":\"" SRT_TEST_GOOD_GRAPHICS_RENDERER "\","
+          "\"device-type\":2,"
+          "\"api-version\":\"" SRT_TEST_GOOD_GRAPHICS_API_VERSION "\","
+          "\"driver-version\":\"" SRT_TEST_GOOD_GRAPHICS_DRIVER_VERSION "\","
+          "\"vendor-id\":\"" SRT_TEST_GOOD_GRAPHICS_VENDOR_ID "\","
+          "\"device-id\":\"" SRT_TEST_GOOD_GRAPHICS_DEVICE_ID "\"}}\n"
+          "{\"device-info\":{"
+          "\"device-name\":\"" SRT_TEST_SOFTWARE_GRAPHICS_RENDERER "\","
+          "\"device-type\":4,"
+          "\"api-version\":\"" SRT_TEST_SOFTWARE_GRAPHICS_API_VERSION "\","
+          "\"driver-version\":\"" SRT_TEST_SOFTWARE_GRAPHICS_DRIVER_VERSION "\","
+          "\"vendor-id\":\"" SRT_TEST_SOFTWARE_GRAPHICS_VENDOR_ID "\","
+          "\"device-id\":\"" SRT_TEST_SOFTWARE_GRAPHICS_DEVICE_ID "\"}}\n"
+          "{\"test\":{"
+          "\"index\":0,"
+          "\"can-draw\":false,"
+          "\"error-message\":\"" SRT_TEST_MIXED_VULKAN_MESSAGES_1 "\"}}\n"
+          "{\"test\":{"
+          "\"index\":1,"
+          "\"can-draw\":false,"
+          "\"error-message\":\"" SRT_TEST_MIXED_VULKAN_MESSAGES_2 "\"}}\n");
+
+  return 1;
+}
+