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/helpers/check-vulkan.c b/helpers/check-vulkan.c index e8303509c255e2b3c02885625ba19f25a0e2b70a..598148abbcbc935c63bea00a10e258082c716bea 100644 --- a/helpers/check-vulkan.c +++ b/helpers/check-vulkan.c @@ -1372,16 +1372,14 @@ int main (int argc, goto out; for (i = 0; i < physical_device_count; i++) - print_physical_device_info (physical_devices[i], stderr); + print_physical_device_info (physical_devices[i], original_stdout); for (i = 0; i < physical_device_count; i++) { result = draw_test_triangle (vk_instance, physical_devices[i], error); - print_draw_test_result (i, result, local_error, stderr); - - if (local_error != NULL) - g_printerr ("%s", local_error->message); + print_draw_test_result (i, result, local_error, original_stdout); + /* The eventual error has already been included in the drawing test JSON */ g_clear_error (error); /* Return exit success if we are able to draw with at least one device */ 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..075e6112732e8bd4d1bd34a6d07c7382e3f3be62 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); + + *version_string = g_strdup_printf ("%s (device %s:%s) (driver %s)", + api_version, vendor_id, device_id, driver_version); - 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"); + if (device_type == SRT_VK_PHYSICAL_DEVICE_TYPE_CPU) + issues |= SRT_GRAPHICS_ISSUES_SOFTWARE_RENDERING; - *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"); + *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,63 @@ 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); +} + +static SrtGraphicsIssues +_srt_get_graphics_issues_from_json_object (JsonObject *json_obj) +{ + JsonArray *array; + SrtGraphicsIssues graphics_issues = SRT_GRAPHICS_ISSUES_NONE; + gsize j; + + /* In graphics, a missing "issues" array means that no issues were found */ + if (json_object_has_member (json_obj, "issues")) + { + array = json_object_get_array_member (json_obj, "issues"); + + /* We are expecting an array of issues here */ + if (array == NULL) + { + g_debug ("'issues' in 'graphics-details' is not an array as expected"); + graphics_issues |= SRT_GRAPHICS_ISSUES_UNKNOWN; + } + else + { + for (j = 0; j < json_array_get_length (array); j++) + { + const gchar *issue_string = json_array_get_string_element (array, j); + if (!srt_add_flag_from_nick (SRT_TYPE_GRAPHICS_ISSUES, + issue_string, + &graphics_issues, + NULL)) + graphics_issues |= SRT_GRAPHICS_ISSUES_UNKNOWN; + } + } + } + return graphics_issues; +} + /** * _srt_graphics_get_from_report: * @json_obj: (not nullable): A JSON Object representing an ABI, @@ -1508,6 +1998,8 @@ _srt_graphics_get_from_report (JsonObject *json_obj, SrtGraphicsIssues graphics_issues = SRT_GRAPHICS_ISSUES_NONE; SrtWindowSystem window_system = SRT_WINDOW_SYSTEM_X11; SrtRenderingInterface rendering_interface = SRT_RENDERING_INTERFACE_GL; + g_autoptr(GPtrArray) devices = g_ptr_array_new_with_free_func (g_object_unref); + gsize j; gchar **stack_parts = g_strsplit (l->data, "/", 2); if (stack_parts[1] == NULL) @@ -1551,30 +2043,7 @@ _srt_graphics_get_from_report (JsonObject *json_obj, version = json_object_get_string_member_with_default (json_stack_obj, "version", NULL); - /* In graphics, a missing "issues" array means that no issues were found */ - if (json_object_has_member (json_stack_obj, "issues")) - { - array = json_object_get_array_member (json_stack_obj, "issues"); - - /* We are expecting an array of issues here */ - if (array == NULL) - { - g_debug ("'issues' in 'graphics-details' is not an array as expected"); - graphics_issues |= SRT_GRAPHICS_ISSUES_UNKNOWN; - } - else - { - for (guint j = 0; j < json_array_get_length (array); j++) - { - const gchar *issue_string = json_array_get_string_element (array, j); - if (!srt_add_flag_from_nick (SRT_TYPE_GRAPHICS_ISSUES, - issue_string, - &graphics_issues, - NULL)) - graphics_issues |= SRT_GRAPHICS_ISSUES_UNKNOWN; - } - } - } + graphics_issues = _srt_get_graphics_issues_from_json_object (json_stack_obj); /* A missing exit_status means that its value is the default zero */ exit_status = json_object_get_int_member_with_default (json_stack_obj, "exit-status", 0); @@ -1593,12 +2062,75 @@ _srt_graphics_get_from_report (JsonObject *json_obj, library_vendor = SRT_GRAPHICS_LIBRARY_VENDOR_UNKNOWN; } + if (json_object_has_member (json_stack_obj, "devices")) + { + array = json_object_get_array_member (json_stack_obj, "devices"); + gsize array_size = 0; + + /* We are expecting an array of devices here */ + if (array == NULL) + g_debug ("'devices' in 'graphics-details' is not an array as expected"); + else + array_size = json_array_get_length (array); + + for (j = 0; j < array_size; j++) + { + SrtGraphicsDevice *device = NULL; + const gchar *name; + const gchar *api_version; + const gchar *driver_version; + const gchar *vendor_id; + const gchar *device_id; + g_autofree gchar *dev_messages = NULL; + SrtVkPhysicalDeviceType type = SRT_VK_PHYSICAL_DEVICE_TYPE_OTHER; + SrtGraphicsIssues issues = SRT_GRAPHICS_ISSUES_NONE; + + JsonObject *device_obj = json_array_get_object_element (array, j); + name = json_object_get_string_member_with_default (device_obj, "name", + NULL); + api_version = json_object_get_string_member_with_default (device_obj, + "api-version", + NULL); + driver_version = json_object_get_string_member_with_default (device_obj, + "driver-version", + NULL); + vendor_id = json_object_get_string_member_with_default (device_obj, + "vendor-id", + NULL); + device_id = json_object_get_string_member_with_default (device_obj, + "device-id", + NULL); + + if (json_object_has_member (device_obj, "type")) + { + const gchar *type_str = json_object_get_string_member (device_obj, "type"); + G_STATIC_ASSERT (sizeof (SrtVkPhysicalDeviceType) == sizeof (gint)); + if (!srt_enum_from_nick (SRT_TYPE_VK_PHYSICAL_DEVICE_TYPE, + type_str, + (gint *) &type, + NULL)) + type = SRT_VK_PHYSICAL_DEVICE_TYPE_OTHER; + } + + issues = _srt_get_graphics_issues_from_json_object (device_obj); + dev_messages = _srt_json_object_dup_array_of_lines_member (device_obj, + "messages"); + + device = _srt_graphics_device_new (name, api_version, driver_version, + vendor_id, device_id, type, + issues); + _srt_graphics_device_set_messages (device, dev_messages); + g_ptr_array_add (devices, device); + } + } + graphics = _srt_graphics_new (multiarch_tuple, window_system, rendering_interface, library_vendor, renderer, version, + devices, 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..53b30ecad420793ea548edd33d06bf7c5df250b3 100644 --- a/tests/graphics.c +++ b/tests/graphics.c @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Collabora Ltd. + * Copyright © 2019-2021 Collabora Ltd. * * SPDX-License-Identifier: MIT * @@ -205,14 +205,14 @@ static void test_object (Fixture *f, gconstpointer context) { - SrtGraphics *graphics; + g_autoptr(SrtGraphics) graphics = NULL; SrtGraphicsIssues issues; SrtGraphicsLibraryVendor library_vendor; gboolean vendor_neutral; - gchar *messages; - gchar *tuple; - gchar *renderer; - gchar *version; + g_autofree gchar *messages = NULL; + g_autofree gchar *tuple = NULL; + g_autofree gchar *renderer = NULL; + g_autofree gchar *version = NULL; int exit_status; int terminating_signal; @@ -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, @@ -258,11 +259,6 @@ test_object (Fixture *f, g_assert_cmpstr (version, ==, SRT_TEST_GOOD_GRAPHICS_VERSION); g_assert_cmpint (exit_status, ==, 0); g_assert_cmpint (terminating_signal, ==, 0); - g_free (messages); - g_free (tuple); - g_free (renderer); - g_free (version); - g_object_unref (graphics); } /* @@ -331,7 +327,7 @@ test_normalize_window_system (Fixture *f, * are too old) */ }; gsize i; - SrtSystemInfo *info = srt_system_info_new (NULL); + g_autoptr(SrtSystemInfo) info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); @@ -387,8 +383,6 @@ test_normalize_window_system (Fixture *f, g_assert_cmpint (winsys, ==, test_vector->out.winsys); g_clear_object (&graphics); } - - g_object_unref (info); } /* @@ -398,13 +392,13 @@ static void test_sigusr (Fixture *f, gconstpointer context) { - SrtGraphics *graphics = NULL; + g_autoptr(SrtGraphics) graphics = NULL; SrtGraphicsIssues issues; - gchar *tuple; + g_autofree gchar *tuple = NULL; int exit_status; int terminating_signal; - SrtSystemInfo *info = srt_system_info_new (NULL); + g_autoptr(SrtSystemInfo) info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); issues = srt_system_info_check_graphics (info, @@ -428,10 +422,6 @@ test_sigusr (Fixture *f, g_assert_cmpint (exit_status, ==, 128 + SIGUSR1); } g_assert_cmpint (terminating_signal, ==, SIGUSR1); - g_free (tuple); - - g_object_unref (graphics); - g_object_unref (info); } /* @@ -440,12 +430,12 @@ test_sigusr (Fixture *f, static void assert_egl_icd (SrtEglIcd *icd) { - GError *error = NULL; - GError *error_property = NULL; - gchar *json_path = NULL; - gchar *library_path = NULL; - gchar *resolved = NULL; - gchar *resolved_property = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(GError) error_property = NULL; + g_autofree gchar *json_path = NULL; + g_autofree gchar *library_path = NULL; + g_autofree gchar *resolved = NULL; + g_autofree gchar *resolved_property = NULL; g_assert_true (SRT_IS_EGL_ICD (icd)); @@ -497,13 +487,6 @@ assert_egl_icd (SrtEglIcd *icd) g_assert_cmpstr (resolved, ==, NULL); g_assert_cmpstr (resolved_property, ==, NULL); } - - g_clear_error (&error); - g_clear_error (&error_property); - g_free (json_path); - g_free (library_path); - g_free (resolved); - g_free (resolved_property); } /* @@ -555,8 +538,9 @@ test_icd_egl (Fixture *f, gconstpointer context) { const Config *config = context; - SrtSystemInfo *info = srt_system_info_new (NULL); - GList *icds; + g_autoptr(SrtSystemInfo) info = srt_system_info_new (NULL); + g_autoptr(SrtObjectList) icds = NULL; + g_autofree gchar *resolved = NULL; const GList *iter; const char * const multiarchs[] = { "mock-abi", NULL }; @@ -589,7 +573,6 @@ test_icd_egl (Fixture *f, if (config != NULL && config->icd_mode == ICD_MODE_EXPLICIT_DIRS) { SrtEglIcd *other; - gchar *resolved; iter = icds; g_assert_nonnull (iter); @@ -637,7 +620,6 @@ test_icd_egl (Fixture *f, "/opt/libEGL_myvendor.so"); resolved = srt_egl_icd_resolve_library_path (iter->data); g_assert_cmpstr (resolved, ==, "/opt/libEGL_myvendor.so"); - g_free (resolved); iter = iter->next; g_assert_null (iter); @@ -675,7 +657,6 @@ test_icd_egl (Fixture *f, else if (config != NULL && config->icd_mode == ICD_MODE_RELATIVE_FILENAMES) { const char *path; - gchar *resolved; iter = icds; g_assert_nonnull (iter); @@ -695,7 +676,6 @@ test_icd_egl (Fixture *f, "libEGL_mesa.so.0"); resolved = srt_egl_icd_resolve_library_path (iter->data); g_assert_cmpstr (resolved, ==, "libEGL_mesa.so.0"); - g_free (resolved); iter = iter->next; g_assert_nonnull (iter); @@ -735,7 +715,6 @@ test_icd_egl (Fixture *f, else if (config != NULL && config->icd_mode == ICD_MODE_FLATPAK) { SrtEglIcd *other; - gchar *resolved; iter = icds; g_assert_nonnull (iter); @@ -747,7 +726,6 @@ test_icd_egl (Fixture *f, resolved = srt_egl_icd_resolve_library_path (iter->data); g_assert_cmpstr (resolved, ==, "/usr/lib/mock-abi/GL/glvnd/egl_vendor.d/../libEGL_relative.so"); - g_free (resolved); other = srt_egl_icd_new_replace_library_path (iter->data, "/run/host/libEGL.so"); @@ -766,8 +744,6 @@ test_icd_egl (Fixture *f, } else { - gchar *resolved; - /* EGL ICDs don't respect the XDG variables, so XDG_DIRS is the same * as NORMAL. */ iter = icds; @@ -786,13 +762,10 @@ test_icd_egl (Fixture *f, "libEGL_mesa.so.0"); resolved = srt_egl_icd_resolve_library_path (iter->data); g_assert_cmpstr (resolved, ==, "libEGL_mesa.so.0"); - g_free (resolved); iter = iter->next; g_assert_null (iter); } - - g_list_free_full (icds, g_object_unref); } /* @@ -801,13 +774,13 @@ test_icd_egl (Fixture *f, static void assert_vulkan_icd (SrtVulkanIcd *icd) { - GError *error = NULL; - GError *error_property = NULL; - gchar *api_version = NULL; - gchar *json_path = NULL; - gchar *library_path = NULL; - gchar *resolved = NULL; - gchar *resolved_property = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(GError) error_property = NULL; + g_autofree gchar *api_version = NULL; + g_autofree gchar *json_path = NULL; + g_autofree gchar *library_path = NULL; + g_autofree gchar *resolved = NULL; + g_autofree gchar *resolved_property = NULL; g_assert_true (SRT_IS_VULKAN_ICD (icd)); @@ -863,14 +836,6 @@ assert_vulkan_icd (SrtVulkanIcd *icd) g_assert_cmpstr (resolved, ==, NULL); g_assert_cmpstr (resolved_property, ==, NULL); } - - g_clear_error (&error); - g_clear_error (&error_property); - g_free (api_version); - g_free (json_path); - g_free (library_path); - g_free (resolved); - g_free (resolved_property); } /* @@ -901,9 +866,10 @@ test_icd_vulkan (Fixture *f, gconstpointer context) { const Config *config = context; - SrtSystemInfo *info = srt_system_info_new (NULL); - GList *icds; + g_autoptr(SrtSystemInfo) info = srt_system_info_new (NULL); + g_autoptr(SrtObjectList) icds = NULL; const GList *iter; + g_autofree gchar *resolved = NULL; const char * const multiarchs[] = { "mock-abi", NULL }; srt_system_info_set_environ (info, f->fake_icds_envp); @@ -1042,7 +1008,6 @@ test_icd_vulkan (Fixture *f, } else if (config != NULL && config->icd_mode == ICD_MODE_FLATPAK) { - gchar *resolved; SrtVulkanIcd *other; iter = icds; @@ -1108,7 +1073,6 @@ test_icd_vulkan (Fixture *f, g_assert_cmpstr (srt_vulkan_icd_get_api_version (iter->data), ==, "1.1.102"); resolved = srt_vulkan_icd_resolve_library_path (iter->data); g_assert_cmpstr (resolved, ==, "/usr/lib/i386-linux-gnu/libvulkan_intel.so"); - g_free (resolved); iter = iter->next; g_assert_nonnull (iter); @@ -1131,8 +1095,6 @@ test_icd_vulkan (Fixture *f, } else if (config != NULL && config->icd_mode == ICD_MODE_XDG_DIRS) { - gchar *resolved; - iter = icds; g_assert_nonnull (iter); /* We load $XDG_CONFIG_DIRS instead of /etc/xdg */ @@ -1153,7 +1115,6 @@ test_icd_vulkan (Fixture *f, g_assert_cmpstr (srt_vulkan_icd_get_api_version (iter->data), ==, "1.2.3"); resolved = srt_vulkan_icd_resolve_library_path (iter->data); g_assert_cmpstr (resolved, ==, "libvulkan_basename.so"); - g_free (resolved); iter = iter->next; g_assert_nonnull (iter); @@ -1190,8 +1151,6 @@ test_icd_vulkan (Fixture *f, } else { - gchar *resolved; - iter = icds; g_assert_nonnull (iter); g_assert_cmpstr (srt_vulkan_icd_get_json_path (iter->data), ==, @@ -1221,7 +1180,6 @@ test_icd_vulkan (Fixture *f, g_assert_cmpstr (srt_vulkan_icd_get_api_version (iter->data), ==, "1.1.102"); resolved = srt_vulkan_icd_resolve_library_path (iter->data); g_assert_cmpstr (resolved, ==, "/usr/lib/i386-linux-gnu/libvulkan_intel.so"); - g_free (resolved); iter = iter->next; g_assert_nonnull (iter); @@ -1242,8 +1200,6 @@ test_icd_vulkan (Fixture *f, iter = iter->next; g_assert_null (iter); } - - g_list_free_full (icds, g_object_unref); } typedef struct @@ -1677,9 +1633,9 @@ check_paths_are_absolute (const GList *list, SrtGraphicsModule module) { const gchar *library_path = NULL; - gchar *absolute_path = NULL; for (const GList *iter = list; iter != NULL; iter = iter->next) { + g_autofree gchar *absolute_path = NULL; switch (module) { case SRT_GRAPHICS_DRI_MODULE: @@ -1705,7 +1661,6 @@ check_paths_are_absolute (const GList *list, g_assert_cmpstr (library_path, ==, absolute_path); g_assert_nonnull (library_path); g_assert_cmpint (library_path[0], ==, '/'); - g_free (absolute_path); } } @@ -1714,10 +1669,10 @@ check_paths_are_relative (const GList *list, SrtGraphicsModule module) { const gchar *library_path = NULL; - gchar *absolute_path = NULL; gsize i = 0; for (const GList *iter = list; iter != NULL; iter = iter->next, i++) { + g_autofree gchar *absolute_path = NULL; switch (module) { case SRT_GRAPHICS_DRI_MODULE: @@ -1746,7 +1701,6 @@ check_paths_are_relative (const GList *list, g_assert_cmpint (library_path[0], !=, '/'); g_assert_cmpint (absolute_path[0], ==, '/'); assert_same_file (library_path, absolute_path); - g_free (absolute_path); } } @@ -1754,9 +1708,9 @@ static void test_dri_debian10 (Fixture *f, gconstpointer context) { - SrtSystemInfo *info; - gchar **envp; - gchar *sysroot; + g_autoptr(SrtSystemInfo) info = NULL; + g_auto(GStrv) envp = NULL; + g_autofree gchar *sysroot = NULL; GList *dri; GList *va_api; const gchar *multiarch_tuples[] = {"i386-mock-debian", "x86_64-mock-debian", NULL}; @@ -1830,19 +1784,15 @@ test_dri_debian10 (Fixture *f, va_api = srt_system_info_list_va_api_drivers (info, multiarch_tuples[1], SRT_DRIVER_FLAGS_INCLUDE_ALL); check_list_suffixes (va_api, va_api_suffixes_x86_64, SRT_GRAPHICS_VAAPI_MODULE); g_list_free_full (va_api, g_object_unref); - - g_object_unref (info); - g_free (sysroot); - g_strfreev (envp); } static void test_dri_fedora (Fixture *f, gconstpointer context) { - SrtSystemInfo *info; - gchar **envp; - gchar *sysroot; + g_autoptr(SrtSystemInfo) info = NULL; + g_auto(GStrv) envp = NULL; + g_autofree gchar *sysroot = NULL; GList *dri; GList *va_api; const gchar *multiarch_tuples[] = {"i386-mock-fedora", "x86_64-mock-fedora", NULL}; @@ -1886,19 +1836,15 @@ test_dri_fedora (Fixture *f, va_api = srt_system_info_list_va_api_drivers (info, multiarch_tuples[1], SRT_DRIVER_FLAGS_NONE); check_list_suffixes (va_api, va_api_suffixes_64, SRT_GRAPHICS_VAAPI_MODULE); g_list_free_full (va_api, g_object_unref); - - g_object_unref (info); - g_free (sysroot); - g_strfreev (envp); } static void test_dri_ubuntu16 (Fixture *f, gconstpointer context) { - SrtSystemInfo *info; - gchar **envp; - gchar *sysroot; + g_autoptr(SrtSystemInfo) info = NULL; + g_auto(GStrv) envp = NULL; + g_autofree gchar *sysroot = NULL; GList *dri; GList *va_api; const gchar *multiarch_tuples[] = {"mock-ubuntu-64-bit", NULL}; @@ -1937,27 +1883,23 @@ test_dri_ubuntu16 (Fixture *f, va_api = srt_system_info_list_va_api_drivers (info, multiarch_tuples[0], SRT_DRIVER_FLAGS_INCLUDE_ALL); check_list_suffixes (va_api, va_api_suffixes, SRT_GRAPHICS_VAAPI_MODULE); g_list_free_full (va_api, g_object_unref); - - g_object_unref (info); - g_free (sysroot); - g_strfreev (envp); } static void test_dri_with_env (Fixture *f, gconstpointer context) { - SrtSystemInfo *info; - gchar **envp; - gchar *sysroot; - gchar *libgl; - gchar *libgl2; - gchar *libgl3; - gchar *libva; - gchar *libva2; - gchar *libva3; - gchar *libgl_combined; - gchar *libva_combined; + g_autoptr(SrtSystemInfo) info = NULL; + g_auto(GStrv) envp = NULL; + g_autofree gchar *sysroot = NULL; + g_autofree gchar *libgl = NULL; + g_autofree gchar *libgl2 = NULL; + g_autofree gchar *libgl3 = NULL; + g_autofree gchar *libva = NULL; + g_autofree gchar *libva2 = NULL; + g_autofree gchar *libva3 = NULL; + g_autofree gchar *libgl_combined = NULL; + g_autofree gchar *libva_combined = NULL; GList *dri; GList *va_api; const gchar *multiarch_tuples[] = {"i386-mock-fedora", NULL}; @@ -2069,29 +2011,17 @@ test_dri_with_env (Fixture *f, check_list_suffixes (va_api, va_api_suffixes, SRT_GRAPHICS_VAAPI_MODULE); check_paths_are_relative (va_api, SRT_GRAPHICS_VAAPI_MODULE); g_list_free_full (va_api, g_object_unref); - - g_object_unref (info); - g_free (sysroot); - g_free (libgl_combined); - g_free (libva_combined); - g_free (libgl); - g_free (libgl2); - g_free (libgl3); - g_free (libva); - g_free (libva2); - g_free (libva3); - g_strfreev (envp); } static void test_dri_flatpak (Fixture *f, gconstpointer context) { - SrtSystemInfo *info; - gchar **envp; - gchar *sysroot; - GList *dri; - GList *va_api; + g_autoptr(SrtSystemInfo) info; + g_auto(GStrv) envp = NULL; + g_autofree gchar *sysroot = NULL; + g_autoptr(SrtObjectList) dri = NULL; + g_autoptr(SrtObjectList) va_api = NULL; const gchar *multiarch_tuples[] = { "mock-abi", NULL }; const gchar *dri_suffixes[] = {"/usr/lib/mock-abi/GL/lib/dri/i965_dri.so", NULL}; @@ -2113,15 +2043,9 @@ test_dri_flatpak (Fixture *f, dri = srt_system_info_list_dri_drivers (info, multiarch_tuples[0], SRT_DRIVER_FLAGS_NONE); check_list_suffixes (dri, dri_suffixes, SRT_GRAPHICS_DRI_MODULE); - g_list_free_full (dri, g_object_unref); va_api = srt_system_info_list_va_api_drivers (info, multiarch_tuples[0], SRT_DRIVER_FLAGS_NONE); check_list_suffixes (va_api, va_api_suffixes, SRT_GRAPHICS_VAAPI_MODULE); - g_list_free_full (va_api, g_object_unref); - - g_object_unref (info); - g_free (sysroot); - g_strfreev (envp); } typedef struct @@ -2266,12 +2190,12 @@ test_vdpau (Fixture *f, for (gsize i = 0; i < G_N_ELEMENTS (vdpau_test); i++) { const VdpauTest *test = &vdpau_test[i]; - SrtSystemInfo *info; - gchar **envp; - gchar *sysroot; - gchar *ld_library_path = NULL; - gchar *vdpau_path = NULL; - gchar *vdpau_relative_path = NULL; + g_autoptr(SrtSystemInfo) info = NULL; + g_auto(GStrv) envp = NULL; + g_autofree gchar *sysroot = NULL; + g_autofree gchar *ld_library_path = NULL; + g_autofree gchar *vdpau_path = NULL; + g_autofree gchar *vdpau_relative_path = NULL; GList *vdpau; g_test_message ("%s: %s", test->sysroot, test->description); @@ -2345,16 +2269,21 @@ test_vdpau (Fixture *f, check_paths_are_relative (vdpau, SRT_GRAPHICS_VDPAU_MODULE); g_list_free_full (vdpau, g_object_unref); } - - g_object_unref (info); - g_free (sysroot); - g_free (ld_library_path); - g_free (vdpau_path); - g_free (vdpau_relative_path); - g_strfreev (envp); } } +typedef struct +{ + SrtGraphicsIssues issues; + const gchar *name; + const gchar *api_version; + const gchar *driver_version; + const gchar *vendor_id; + const gchar *device_id; + const gchar *messages; + SrtVkPhysicalDeviceType type; +} GraphicsDeviceTest; + typedef struct { const gchar *description; @@ -2367,6 +2296,8 @@ typedef struct const gchar *renderer_string; const gchar *version_string; const gchar *messages; + /* Arbitrary size, increase it if necessary */ + GraphicsDeviceTest devices[4]; int exit_status; gboolean vendor_neutral; } GraphicsTest; @@ -2465,6 +2396,27 @@ 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, + .devices = + { + { + .name = SRT_TEST_GOOD_GRAPHICS_RENDERER, + .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, + .type = SRT_VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, + }, + { + .name = SRT_TEST_SOFTWARE_GRAPHICS_RENDERER, + .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, + .type = SRT_VK_PHYSICAL_DEVICE_TYPE_CPU, + .issues = SRT_GRAPHICS_ISSUES_SOFTWARE_RENDERING, + }, + }, .vendor_neutral = TRUE, }, @@ -2472,23 +2424,46 @@ 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, + .devices = + { + { + .name = SRT_TEST_GOOD_GRAPHICS_RENDERER, + .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, + .type = SRT_VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, + .messages = SRT_TEST_MIXED_VULKAN_MESSAGES_1, + .issues = SRT_GRAPHICS_ISSUES_CANNOT_DRAW, + }, + { + .name = SRT_TEST_SOFTWARE_GRAPHICS_RENDERER, + .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, + .type = SRT_VK_PHYSICAL_DEVICE_TYPE_CPU, + .messages = SRT_TEST_MIXED_VULKAN_MESSAGES_2, + .issues = SRT_GRAPHICS_ISSUES_CANNOT_DRAW | SRT_GRAPHICS_ISSUES_SOFTWARE_RENDERING, + }, + }, .vendor_neutral = TRUE, }, @@ -2521,20 +2496,23 @@ test_check_graphics (Fixture *f, for (gsize i = 0; i < G_N_ELEMENTS (graphics_test); i++) { const GraphicsTest *test = &graphics_test[i]; - SrtGraphics *graphics = NULL; + g_autoptr(SrtGraphics) graphics = NULL; + g_autoptr(SrtObjectList) devices = NULL; SrtGraphicsIssues issues; - gchar *tuple; - gchar *renderer; - gchar *version; - gchar *messages; + g_autofree gchar *tuple = NULL; + g_autofree gchar *renderer = NULL; + g_autofree gchar *version = NULL; + g_autofree gchar *messages = NULL; int exit_status; int terminating_signal; gboolean vendor_neutral; SrtGraphicsLibraryVendor library_vendor; + GList *iter; + gsize j; g_test_message ("%s", test->description); - SrtSystemInfo *info = srt_system_info_new (NULL); + g_autoptr(SrtSystemInfo) info = srt_system_info_new (NULL); srt_system_info_set_helpers_path (info, f->builddir); srt_system_info_set_test_flags (info, test->test_flags); @@ -2550,6 +2528,50 @@ test_check_graphics (Fixture *f, g_assert_cmpint (srt_graphics_get_exit_status (graphics), ==, test->exit_status); g_assert_cmpint (srt_graphics_get_terminating_signal (graphics), ==, 0); + devices = srt_graphics_get_devices (graphics); + for (j = 0, iter = devices; iter != NULL; iter = iter->next, j++) + { + g_autofree gchar *name = NULL; + g_autofree gchar *api_version = NULL; + g_autofree gchar *driver_version = NULL; + g_autofree gchar *vendor_id = NULL; + g_autofree gchar *device_id = NULL; + SrtVkPhysicalDeviceType type; + + g_assert_cmpstr (srt_graphics_device_get_name (iter->data), ==, test->devices[j].name); + g_assert_cmpstr (srt_graphics_device_get_api_version (iter->data), ==, + test->devices[j].api_version); + g_assert_cmpstr (srt_graphics_device_get_driver_version (iter->data), ==, + test->devices[j].driver_version); + g_assert_cmpstr (srt_graphics_device_get_vendor_id (iter->data), ==, + test->devices[j].vendor_id); + g_assert_cmpstr (srt_graphics_device_get_device_id (iter->data), ==, + test->devices[j].device_id); + g_assert_cmpint (srt_graphics_device_get_device_type (iter->data), ==, + test->devices[j].type); + g_assert_cmpstr (srt_graphics_device_get_messages (iter->data), ==, + test->devices[j].messages); + g_assert_cmpint (srt_graphics_device_get_issues (iter->data), ==, + test->devices[j].issues); + + g_object_get (iter->data, + "name", &name, + "api-version", &api_version, + "driver-version", &driver_version, + "vendor-id", &vendor_id, + "device-id", &device_id, + "type", &type, + "issues", &issues, + NULL); + g_assert_cmpstr (name, ==, test->devices[j].name); + g_assert_cmpstr (api_version, ==, test->devices[j].api_version); + g_assert_cmpstr (driver_version, ==, test->devices[j].driver_version); + g_assert_cmpstr (vendor_id, ==, test->devices[j].vendor_id); + g_assert_cmpstr (device_id, ==, test->devices[j].device_id); + g_assert_cmpint (type, ==, test->devices[j].type); + g_assert_cmpint (issues, ==, test->devices[j].issues); + } + vendor_neutral = srt_graphics_library_is_vendor_neutral (graphics, &library_vendor); g_assert_cmpint (library_vendor, ==, test->library_vendor); g_assert_cmpint (vendor_neutral, ==, test->vendor_neutral); @@ -2570,13 +2592,6 @@ test_check_graphics (Fixture *f, g_assert_cmpstr (messages, ==, test->messages); g_assert_cmpint (exit_status, ==, test->exit_status); g_assert_cmpint (terminating_signal, ==, 0); - g_free (tuple); - g_free (renderer); - g_free (version); - g_free (messages); - - g_object_unref (graphics); - g_object_unref (info); } } @@ -2590,9 +2605,9 @@ static void test_glx_debian (Fixture *f, gconstpointer context) { - SrtSystemInfo *info; - gchar **envp; - gchar *sysroot; + g_autoptr(SrtSystemInfo) info = NULL; + g_auto(GStrv) envp = NULL; + g_autofree gchar *sysroot = NULL; GList *glx; const gchar *multiarch_tuples[] = {"i386-mock-debian", "x86_64-mock-debian", NULL}; const gchar *glx_suffixes_i386[] = {"libGLX_mesa.so.0", @@ -2630,19 +2645,15 @@ test_glx_debian (Fixture *f, check_list_suffixes (glx, glx_suffixes_x86_64, SRT_GRAPHICS_GLX_MODULE); check_list_links (glx, glx_paths_x86_64, SRT_GRAPHICS_GLX_MODULE); g_list_free_full (glx, g_object_unref); - - g_object_unref (info); - g_free (sysroot); - g_strfreev (envp); } static void test_glx_container (Fixture *f, gconstpointer context) { - SrtSystemInfo *info; - gchar **envp; - gchar *sysroot; + g_autoptr(SrtSystemInfo) info = NULL; + g_auto(GStrv) envp = NULL; + g_autofree gchar *sysroot = NULL; GList *glx; const gchar *multiarch_tuples[] = {"i386-mock-container", "x86_64-mock-container", NULL}; const gchar *glx_suffixes_i386[] = {"libGLX_nvidia.so.0", @@ -2680,10 +2691,6 @@ test_glx_container (Fixture *f, check_list_suffixes (glx, glx_suffixes_x86_64, SRT_GRAPHICS_GLX_MODULE); check_list_links (glx, glx_paths_x86_64, SRT_GRAPHICS_GLX_MODULE); g_list_free_full (glx, g_object_unref); - - g_object_unref (info); - g_free (sysroot); - g_strfreev (envp); } static const Config dir_config = { ICD_MODE_EXPLICIT_DIRS }; diff --git a/tests/json-report/full-good-report.json b/tests/json-report/full-good-report.json index 05b01afda1950c36f802cd68bc62394135c8e538..223105bec5fc0834c6b421a2ea6b856e0bfaefaf 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", @@ -137,8 +138,26 @@ ], "graphics-details" : { "x11/vulkan" : { - "renderer" : "AMD Radeon RX 5700 XT", - "version" : "1.2.136 (device 1002:731f) (driver 2.0.140)" + "renderer" : "AMD RADV NAVI10 (ACO)", + "version" : "1.2.145 (device 0x1002:0x731f) (driver 20.3.3)", + "devices" : [ + { + "name" : "AMD RADV NAVI10 (ACO)", + "api-version" : "1.2.145", + "driver-version" : "20.3.3", + "vendor-id" : "0x1002", + "device-id" : "0x731f", + "type" : "discrete-gpu" + }, + { + "name" : "llvmpipe (LLVM 8.0, 256 bits)", + "api-version" : "1.0.2", + "driver-version" : "0.0.1", + "vendor-id" : "0x10005", + "device-id" : "0", + "type" : "cpu" + } + ] }, "x11/vdpau" : { "renderer" : "G3DVL VDPAU Driver Shared Library version 1.0\n", diff --git a/tests/json-report/partial-report.json b/tests/json-report/partial-report.json index d843f8237787346bd7a777c93c926c8935d11604..a76188cefe1f6777f7d75fd3ec4971aa6fab6211 100644 --- a/tests/json-report/partial-report.json +++ b/tests/json-report/partial-report.json @@ -17,6 +17,24 @@ "error": "We just don't know" }, "graphics-details" : { + "x11/vulkan" : { + "renderer" : "AMD RADV NAVI10 (ACO)", + "version" : "1.2.145 (device 0x1002:0x731f) (driver 20.3.3)", + "devices" : [ + { + "name" : "AMD RADV NAVI10 (ACO)", + "api-version" : "1.2.145", + "driver-version" : "20.3.3", + "type" : "discrete-gpu", + "messages" : [ + "vkWaitForFences (dev_props->device, 1, &dev_props->in_flight_fences[dev_props->current_frame], VK_TRUE, 1) failed: TIMEOUT (2)" + ], + "issues" : [ + "cannot-draw" + ] + } + ] + }, "x11/vdpau" : { "renderer" : "G3DVL VDPAU Driver Shared Library version 1.0\n", "library-vendor" : "futuristic" 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; +} + diff --git a/tests/system-info.c b/tests/system-info.c index 7dcd72b1a0742993737ba91441636d492463c499..4bcf23de815afa76fcfa7235e3b3b152316ab81e 100644 --- a/tests/system-info.c +++ b/tests/system-info.c @@ -25,6 +25,7 @@ #include <libglnx.h> +#include "steam-runtime-tools/graphics-test-defines.h" #include <steam-runtime-tools/steam-runtime-tools.h> #include "steam-runtime-tools/utils-internal.h" @@ -2448,6 +2449,18 @@ typedef struct gboolean is_extra; } DriverTest; +typedef struct +{ + SrtGraphicsIssues issues; + const gchar *name; + const gchar *api_version; + const gchar *driver_version; + const gchar *vendor_id; + const gchar *device_id; + const gchar *messages; + SrtVkPhysicalDeviceType type; +} GraphicsDeviceTest; + typedef struct { SrtWindowSystem window_system; @@ -2457,6 +2470,7 @@ typedef struct SrtGraphicsLibraryVendor library_vendor; SrtGraphicsIssues issues; const gchar *messages; + GraphicsDeviceTest devices[4]; int exit_status; int terminating_signal; gboolean is_available; @@ -2722,9 +2736,28 @@ static const JsonTest json_test[] = { .window_system = SRT_WINDOW_SYSTEM_X11, .rendering_interface = SRT_RENDERING_INTERFACE_VULKAN, - .renderer = "AMD Radeon RX 5700 XT", - .version = "1.2.136 (device 1002:731f) (driver 2.0.140)", + .renderer = SRT_TEST_GOOD_GRAPHICS_RENDERER, + .version = SRT_TEST_GOOD_VULKAN_VERSION, .is_available = TRUE, + .devices = + { + { + .name = SRT_TEST_GOOD_GRAPHICS_RENDERER, + .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, + .type = SRT_VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, + }, + { + .name = SRT_TEST_SOFTWARE_GRAPHICS_RENDERER, + .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, + .type = SRT_VK_PHYSICAL_DEVICE_TYPE_CPU, + }, + }, }, { .window_system = SRT_WINDOW_SYSTEM_X11, @@ -2962,6 +2995,26 @@ static const JsonTest json_test[] = .issues = SRT_LIBRARY_ISSUES_UNKNOWN, .graphics = { + { + .window_system = SRT_WINDOW_SYSTEM_X11, + .rendering_interface = SRT_RENDERING_INTERFACE_VULKAN, + .renderer = SRT_TEST_GOOD_GRAPHICS_RENDERER, + .version = SRT_TEST_GOOD_VULKAN_VERSION, + .is_available = TRUE, + .devices = + { + { + .name = SRT_TEST_GOOD_GRAPHICS_RENDERER, + .api_version = SRT_TEST_GOOD_GRAPHICS_API_VERSION, + .driver_version = SRT_TEST_GOOD_GRAPHICS_DRIVER_VERSION, + .type = SRT_VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU, + /* A trailing newline is added by + * _srt_json_object_dup_array_of_lines_member() */ + .messages = SRT_TEST_MIXED_VULKAN_MESSAGES_2 "\n", + .issues = SRT_GRAPHICS_ISSUES_CANNOT_DRAW, + }, + }, + }, { .window_system = SRT_WINDOW_SYSTEM_X11, .rendering_interface = SRT_RENDERING_INTERFACE_VDPAU, @@ -3240,6 +3293,7 @@ json_parsing (Fixture *f, gchar **driver_environment_list; gsize j; gsize jj; + gsize k; GList *icds; GList *iter; GList *desktop_entries; @@ -3343,6 +3397,7 @@ json_parsing (Fixture *f, for (jj = 0; this_arch.graphics[jj].is_available; jj++) { SrtGraphics *graphics = NULL; + g_autoptr(SrtObjectList) devices = NULL; SrtGraphicsLibraryVendor library_vendor; srt_system_info_check_graphics (info, multiarch_tuples[j], @@ -3363,6 +3418,29 @@ json_parsing (Fixture *f, srt_graphics_get_exit_status (graphics)); g_assert_cmpint (this_arch.graphics[jj].terminating_signal, ==, srt_graphics_get_terminating_signal (graphics)); + + devices = srt_graphics_get_devices (graphics); + for (k = 0, iter = devices; iter != NULL; iter = iter->next, k++) + { + GraphicsDeviceTest this_device_test = this_arch.graphics[jj].devices[k]; + g_assert_cmpstr (srt_graphics_device_get_name (iter->data), ==, + this_device_test.name); + g_assert_cmpstr (srt_graphics_device_get_api_version (iter->data), ==, + this_device_test.api_version); + g_assert_cmpstr (srt_graphics_device_get_driver_version (iter->data), ==, + this_device_test.driver_version); + g_assert_cmpstr (srt_graphics_device_get_vendor_id (iter->data), ==, + this_device_test.vendor_id); + g_assert_cmpstr (srt_graphics_device_get_device_id (iter->data), ==, + this_device_test.device_id); + g_assert_cmpint (srt_graphics_device_get_device_type (iter->data), ==, + this_device_test.type); + g_assert_cmpstr (srt_graphics_device_get_messages (iter->data), ==, + this_device_test.messages); + g_assert_cmpint (srt_graphics_device_get_issues (iter->data), ==, + this_device_test.issues); + } + g_object_unref (graphics); }