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; +} +