diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 1050f259a07..d9b499fe293 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -15,13 +15,13 @@ body: attributes: label: Godot version description: > - Specify the Git commit hash if using a development or non-official build. + Specify the Godot version, including the Git commit hash if using a development or non-official build. If you use a custom build, please test if your issue is reproducible in official builds too. - placeholder: 3.3.stable, 4.0.dev (3041becc6) + placeholder: 3.5.stable, 4.0.dev (3041becc6) validations: required: true -- type: input +- type: textarea attributes: label: System information description: | @@ -29,7 +29,15 @@ body: - For issues that are likely OS-specific and/or graphics-related, please specify the CPU model and architecture. - For graphics-related issues, specify the GPU model, driver version, and the rendering backend (GLES2, GLES3, Vulkan). - **Bug reports not including the required information may be closed at the maintainers' discretion.** If in doubt, always include all the requested information; it's better to include too much information than not enough information. - placeholder: Windows 10, Intel Core i5-7200U, GLES3, Intel HD Graphics 620 (27.20.100.9616) + - **Starting from Godot 4.1, you can copy this information to your clipboard by using *Help > Copy System Info* at the top of the editor window.**``` + placeholder: | + - OS: Windows 10 + - Godot Version: 3.5.stable, 4.0.dev (3041becc6) + - Rendering Driver: GLES3, Vulkan + - Rendering Method: Forward+, Mobile, Compatibility + - Graphics Card: Intel HD Graphics 620 (27.20.100.9616) + - Graphics Card Driver: nvidia, version 510.85.02 + - CPU: Intel Core i5-7200U validations: required: true diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 564cdf11928..ba98b043a5f 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -789,6 +789,7 @@ void EditorNode::_notification(int p_what) { help_menu->set_item_icon(help_menu->get_item_index(HELP_DOCS), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons"))); help_menu->set_item_icon(help_menu->get_item_index(HELP_QA), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons"))); help_menu->set_item_icon(help_menu->get_item_index(HELP_REPORT_A_BUG), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons"))); + help_menu->set_item_icon(help_menu->get_item_index(HELP_COPY_SYSTEM_INFO), gui_base->get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons"))); help_menu->set_item_icon(help_menu->get_item_index(HELP_SUGGEST_A_FEATURE), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons"))); help_menu->set_item_icon(help_menu->get_item_index(HELP_SEND_DOCS_FEEDBACK), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons"))); help_menu->set_item_icon(help_menu->get_item_index(HELP_COMMUNITY), gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons"))); @@ -2899,6 +2900,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { case HELP_REPORT_A_BUG: { OS::get_singleton()->shell_open("https://github.com/godotengine/godot/issues"); } break; + case HELP_COPY_SYSTEM_INFO: { + String info = _get_system_info(); + DisplayServer::get_singleton()->clipboard_set(info); + } break; case HELP_SUGGEST_A_FEATURE: { OS::get_singleton()->shell_open("https://github.com/godotengine/godot-proposals#readme"); } break; @@ -4335,6 +4340,87 @@ void EditorNode::progress_end_task_bg(const String &p_task) { singleton->progress_hb->end_task(p_task); } +String EditorNode::_get_system_info() const { + String distribution_name = OS::get_singleton()->get_distribution_name(); + if (distribution_name.is_empty()) { + distribution_name = OS::get_singleton()->get_name(); + } + if (distribution_name.is_empty()) { + distribution_name = "Other"; + } + const String distribution_version = OS::get_singleton()->get_version(); + + const String godot_version = String(VERSION_FULL_BUILD); + + const String driver_name = GLOBAL_GET("rendering/rendering_device/driver"); + String rendering_method = GLOBAL_GET("rendering/renderer/rendering_method"); + + const String rendering_device_name = RenderingServer::get_singleton()->get_rendering_device()->get_device_name(); + + RenderingDevice::DeviceType device_type = RenderingServer::get_singleton()->get_video_adapter_type(); + String device_type_string; + switch (device_type) { + case RenderingDevice::DeviceType::DEVICE_TYPE_INTEGRATED_GPU: + device_type_string = "integrated"; + break; + case RenderingDevice::DeviceType::DEVICE_TYPE_DISCRETE_GPU: + device_type_string = "dedicated"; + break; + case RenderingDevice::DeviceType::DEVICE_TYPE_VIRTUAL_GPU: + device_type_string = "virtual"; + break; + case RenderingDevice::DeviceType::DEVICE_TYPE_CPU: + device_type_string = "software emulation on CPU"; + break; + case RenderingDevice::DeviceType::DEVICE_TYPE_OTHER: + case RenderingDevice::DeviceType::DEVICE_TYPE_MAX: + break; // Can't happen, but silences warning for DEVICE_TYPE_MAX + } + + const Vector video_adapter_driver_info = OS::get_singleton()->get_video_adapter_driver_info(); + + const String processor_name = OS::get_singleton()->get_processor_name(); + const int processor_count = OS::get_singleton()->get_processor_count(); + + // Prettify + if (rendering_method == "forward_plus") { + rendering_method = "Forward+"; + } else if (rendering_method == "mobile") { + rendering_method = "Mobile"; + } else if (rendering_method == "gl_compatibility") { + rendering_method = "Compatibility"; + } + + // Join info. + Vector info; + const String prefix = "*"; + if (!distribution_version.is_empty()) { + info.push_back(vformat("%s OS: %s %s", prefix, distribution_name, distribution_version)); + } else { + info.push_back(vformat("%s OS: %s", prefix, distribution_name)); + } + info.push_back(vformat("%s Godot Version: %s", prefix, godot_version)); + info.push_back(vformat("%s Rendering Driver: %s", prefix, driver_name)); + info.push_back(vformat("%s Rendering Method: %s", prefix, rendering_method)); + if (device_type_string.is_empty()) { + info.push_back(vformat("%s Graphics Card: %s", prefix, rendering_device_name)); + } else { + info.push_back(vformat("%s Graphics Card: %s (%s)", prefix, rendering_device_name, device_type_string)); + } + if (video_adapter_driver_info.size() == 2) { // This vector is always either of length 0 or 2. + String vad_name = video_adapter_driver_info[0]; + String vad_version = video_adapter_driver_info[1]; // Version could be potentially empty on Linux/BSD. + if (!vad_version.is_empty()) { + info.push_back(vformat("%s Graphics Card Driver: %s, version %s", prefix, vad_name, vad_version)); + } else { + info.push_back(vformat("%s Graphics Card Driver: %s", prefix, vad_name)); + } + } + info.push_back(vformat("%s CPU: %s (%d Threads)", prefix, processor_name, processor_count)); + + return String("\n").join(info); +} + Ref EditorNode::_file_dialog_get_icon(const String &p_path) { EditorFileSystemDirectory *efsd = EditorFileSystem::get_singleton()->get_filesystem_path(p_path.get_base_dir()); if (efsd) { @@ -7384,6 +7470,7 @@ EditorNode::EditorNode() { help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/online_docs", TTR("Online Documentation")), HELP_DOCS); help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/q&a", TTR("Questions & Answers")), HELP_QA); help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/report_a_bug", TTR("Report a Bug")), HELP_REPORT_A_BUG); + help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/copy_system_info", TTR("Copy System Info")), HELP_COPY_SYSTEM_INFO); help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/suggest_a_feature", TTR("Suggest a Feature")), HELP_SUGGEST_A_FEATURE); help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/send_docs_feedback", TTR("Send Docs Feedback")), HELP_SEND_DOCS_FEEDBACK); help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/community", TTR("Community")), HELP_COMMUNITY); diff --git a/editor/editor_node.h b/editor/editor_node.h index b5f84a32049..de99d6dad80 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -225,6 +225,7 @@ private: HELP_DOCS, HELP_QA, HELP_REPORT_A_BUG, + HELP_COPY_SYSTEM_INFO, HELP_SUGGEST_A_FEATURE, HELP_SEND_DOCS_FEEDBACK, HELP_COMMUNITY, @@ -503,6 +504,8 @@ private: static int plugin_init_callback_count; static Vector _init_callbacks; + String _get_system_info() const; + static void _dependency_error_report(const String &p_path, const String &p_dep, const String &p_type) { DEV_ASSERT(Thread::get_caller_id() == Thread::get_main_id()); if (!singleton->dependency_errors.has(p_path)) { diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 73081e35e7b..3afaa3d90c5 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -182,7 +182,7 @@ String OS_Android::get_name() const { } String OS_Android::get_system_property(const char *key) const { - static String value; + String value; char value_str[PROP_VALUE_MAX]; if (__system_property_get(key, value_str)) { value = String(value_str); @@ -230,20 +230,20 @@ String OS_Android::get_version() const { "ro.potato.version", "ro.xtended.version", "org.evolution.version", "ro.corvus.version", "ro.pa.version", "ro.crdroid.version", "ro.syberia.version", "ro.arrow.version", "ro.lineage.version" }; for (int i = 0; i < roms.size(); i++) { - static String rom_version = get_system_property(roms[i]); + String rom_version = get_system_property(roms[i]); if (!rom_version.is_empty()) { return rom_version; } } - static String mod_version = get_system_property("ro.modversion"); // Handles other Android custom ROMs. + String mod_version = get_system_property("ro.modversion"); // Handles other Android custom ROMs. if (!mod_version.is_empty()) { return mod_version; } // Handles stock Android. - static String sdk_version = get_system_property("ro.build.version.sdk_int"); - static String build = get_system_property("ro.build.version.incremental"); + String sdk_version = get_system_property("ro.build.version.sdk_int"); + String build = get_system_property("ro.build.version.incremental"); if (!sdk_version.is_empty()) { if (!build.is_empty()) { return vformat("%s.%s", sdk_version, build); diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 8d8c8ce27b8..2c093b00e76 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -215,39 +215,40 @@ String OS_LinuxBSD::get_name() const { } String OS_LinuxBSD::get_systemd_os_release_info_value(const String &key) const { - static String info; - if (info.is_empty()) { - Ref f = FileAccess::open("/etc/os-release", FileAccess::READ); - if (f.is_valid()) { - while (!f->eof_reached()) { - const String line = f->get_line(); - if (line.find(key) != -1) { - return line.split("=")[1].strip_edges(); - } + Ref f = FileAccess::open("/etc/os-release", FileAccess::READ); + if (f.is_valid()) { + while (!f->eof_reached()) { + const String line = f->get_line(); + if (line.find(key) != -1) { + String value = line.split("=")[1].strip_edges(); + value = value.trim_prefix("\""); + return value.trim_suffix("\""); } } } - return info; + return ""; } String OS_LinuxBSD::get_distribution_name() const { - static String systemd_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string. - if (!systemd_name.is_empty()) { - return systemd_name; + static String distribution_name = get_systemd_os_release_info_value("NAME"); // returns a value for systemd users, otherwise an empty string. + if (!distribution_name.is_empty()) { + return distribution_name; } struct utsname uts; // returns a decent value for BSD family. uname(&uts); - return uts.sysname; + distribution_name = uts.sysname; + return distribution_name; } String OS_LinuxBSD::get_version() const { - static String systemd_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string. - if (!systemd_version.is_empty()) { - return systemd_version; + static String release_version = get_systemd_os_release_info_value("VERSION"); // returns a value for systemd users, otherwise an empty string. + if (!release_version.is_empty()) { + return release_version; } struct utsname uts; // returns a decent value for BSD family. uname(&uts); - return uts.version; + release_version = uts.version; + return release_version; } Vector OS_LinuxBSD::get_video_adapter_driver_info() const { @@ -255,6 +256,11 @@ Vector OS_LinuxBSD::get_video_adapter_driver_info() const { return Vector(); } + static Vector info; + if (!info.is_empty()) { + return info; + } + const String rendering_device_name = RenderingServer::get_singleton()->get_rendering_device()->get_device_name(); // e.g. `NVIDIA GeForce GTX 970` const String rendering_device_vendor = RenderingServer::get_singleton()->get_rendering_device()->get_device_vendor_name(); // e.g. `NVIDIA` const String card_name = rendering_device_name.trim_prefix(rendering_device_vendor).strip_edges(); // -> `GeForce GTX 970` @@ -320,8 +326,8 @@ Vector OS_LinuxBSD::get_video_adapter_driver_info() const { Vector class_display_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_display_device_candidates, kernel_lit, dummys); Vector class_3d_device_drivers = OS_LinuxBSD::lspci_get_device_value(class_3d_device_candidates, kernel_lit, dummys); - static String driver_name; - static String driver_version; + String driver_name; + String driver_version; // Use first valid value: for (const String &driver : class_3d_device_drivers) { @@ -341,7 +347,6 @@ Vector OS_LinuxBSD::get_video_adapter_driver_info() const { } } - Vector info; info.push_back(driver_name); String modinfo; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 38df68c7647..df7923660c7 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -450,8 +450,7 @@ String OS_UWP::get_distribution_name() const { String OS_UWP::get_version() const { winrt::hstring df_version = VersionInfo().DeviceFamilyVersion(); - static String version = String(winrt::to_string(df_version).c_str()); - return version; + return String(winrt::to_string(df_version).c_str()); } OS::DateTime OS_UWP::get_datetime(bool p_utc) const { diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index ae1649c75dc..2653efed71f 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -453,14 +453,19 @@ Vector OS_Windows::get_video_adapter_driver_info() const { return Vector(); } + static Vector info; + if (!info.is_empty()) { + return info; + } + REFCLSID clsid = CLSID_WbemLocator; // Unmarshaler CLSID REFIID uuid = IID_IWbemLocator; // Interface UUID IWbemLocator *wbemLocator = NULL; // to get the services IWbemServices *wbemServices = NULL; // to get the class IEnumWbemClassObject *iter = NULL; IWbemClassObject *pnpSDriverObject[1]; // contains driver name, version, etc. - static String driver_name; - static String driver_version; + String driver_name; + String driver_version; const String device_name = RenderingServer::get_singleton()->get_rendering_device()->get_device_name(); if (device_name.is_empty()) { @@ -536,7 +541,6 @@ Vector OS_Windows::get_video_adapter_driver_info() const { SAFE_RELEASE(wbemServices) SAFE_RELEASE(iter) - Vector info; info.push_back(driver_name); info.push_back(driver_version);