diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml
index 3c9f0fc7aff..bef1c855098 100644
--- a/doc/classes/RenderingServer.xml
+++ b/doc/classes/RenderingServer.xml
@@ -1609,7 +1609,8 @@
Returns the type of the video adapter. Since dedicated graphics cards from a given generation will [i]usually[/i] be significantly faster than integrated graphics made in the same generation, the device type can be used as a basis for automatic graphics settings adjustment. However, this is not always true, so make sure to provide users with a way to manually override graphics settings.
- [b]Note:[/b] When using the OpenGL backend or when running in headless mode, this function always returns [constant RenderingDevice.DEVICE_TYPE_OTHER].
+ [b]Note:[/b] When running the OpenGL driver, this function returns [constant RenderingDevice.DEVICE_TYPE_CPU] for software-emulated GPUs (such as llvmpipe) and [constant RenderingDevice.DEVICE_TYPE_OTHER] for all other device types. The detection is based on the video adapter name, as OpenGL does not have an actual API for querying the current device type.
+ [b]Note:[/b] When running in headless mode, this function always returns [constant RenderingDevice.DEVICE_TYPE_OTHER].
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 37e7256d764..0cad3a98b5d 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -194,6 +194,11 @@ typedef void(GLAPIENTRY *DebugMessageCallbackARB)(DEBUGPROCARB callback, const v
void RasterizerGLES3::initialize() {
Engine::get_singleton()->print_header(vformat("OpenGL API %s - Compatibility - Using Device: %s - %s", RS::get_singleton()->get_video_adapter_api_version(), RS::get_singleton()->get_video_adapter_vendor(), RS::get_singleton()->get_video_adapter_name()));
+ if (RS::get_singleton()->get_video_adapter_type() == RenderingDevice::DEVICE_TYPE_CPU) {
+ Engine::get_singleton()->print_header_rich(
+ "[color=yellow][b]WARNING:[/b] OpenGL is currently running on software emulation, which is very slow. Check whether your GPU supports OpenGL and make sure its drivers are up-to-date.");
+ }
+
// FLIP XY Bug: Are more devices affected?
// Confirmed so far: all Adreno 3xx with old driver (until 2018)
// ok on some tested Adreno devices: 4xx, 5xx and 6xx
diff --git a/drivers/gles3/storage/utilities.cpp b/drivers/gles3/storage/utilities.cpp
index 7f0be364663..3356dffebb5 100644
--- a/drivers/gles3/storage/utilities.cpp
+++ b/drivers/gles3/storage/utilities.cpp
@@ -454,6 +454,13 @@ String Utilities::get_video_adapter_vendor() const {
}
RenderingDevice::DeviceType Utilities::get_video_adapter_type() const {
+ // Detect common OpenGL software rasterizers according to the reported GPU model name.
+ // See .
+ const String adapter_name = get_video_adapter_name().to_lower();
+ if (adapter_name.contains("llvmpipe") || adapter_name.contains("softpipe") || adapter_name.contains("swr")) {
+ return RenderingDevice::DeviceType::DEVICE_TYPE_CPU;
+ }
+
return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER;
}
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 8b6d316dd16..db6c629b554 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -723,6 +723,28 @@ void EditorNode::_notification(int p_what) {
CanvasItemEditor::ThemePreviewMode theme_preview_mode = (CanvasItemEditor::ThemePreviewMode)(int)EditorSettings::get_singleton()->get_project_metadata("2d_editor", "theme_preview", CanvasItemEditor::THEME_PREVIEW_PROJECT);
update_preview_themes(theme_preview_mode);
+ if (RenderingDevice::get_singleton() && RenderingDevice::get_singleton()->get_device_type() == RenderingDevice::DEVICE_TYPE_CPU) {
+ const String driver_name = OS::get_singleton()->get_current_rendering_driver_name();
+ String driver_friendly_name;
+ if (driver_name == "d3d12") {
+ driver_friendly_name = "Direct3D 12";
+ } else if (driver_name == "metal") {
+ driver_friendly_name = "Metal";
+ } else {
+ driver_friendly_name = "Vulkan";
+ }
+ log->add_message(
+ vformat(TTR("%s is currently running on software emulation, which is very slow. Check whether your GPU supports %s and make sure its drivers are up-to-date.\nIf your GPU is not compatible with %s, try switching to the Compatibility rendering method in the top-right corner of the editor."),
+ driver_friendly_name,
+ driver_friendly_name,
+ driver_friendly_name),
+ EditorLog::MSG_TYPE_WARNING);
+ } else if (RenderingServer::get_singleton()->get_video_adapter_type() == RenderingDevice::DEVICE_TYPE_CPU) {
+ log->add_message(
+ TTR("OpenGL is currently running on software emulation, which is very slow. Check whether your GPU supports OpenGL and make sure its drivers are up-to-date.\nIf your GPU is not compatible with OpenGL, try switching to the Forward+ or Mobile rendering methods in the top-right corner of the editor."),
+ EditorLog::MSG_TYPE_WARNING);
+ }
+
/* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */
} break;
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 22044a8c2d1..b086dd5fa29 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -5382,6 +5382,22 @@ Error RenderingDevice::initialize(RenderingContextDriver *p_context, DisplayServ
// Output our device version.
Engine::get_singleton()->print_header(vformat("%s %s - %s - Using Device #%d: %s - %s", get_device_api_name(), get_device_api_version(), rendering_method, device_index, _get_device_vendor_name(device), device.name));
+
+ if (get_device_type() == DEVICE_TYPE_CPU) {
+ const String driver_name = OS::get_singleton()->get_current_rendering_driver_name();
+ String driver_friendly_name;
+ if (driver_name == "d3d12") {
+ driver_friendly_name = "Direct3D 12";
+ } else if (driver_name == "metal") {
+ driver_friendly_name = "Metal";
+ } else {
+ driver_friendly_name = "Vulkan";
+ }
+ Engine::get_singleton()->print_header_rich(
+ vformat("[color=yellow][b]WARNING:[/b] %s is currently running on software emulation, which is very slow. Check whether your GPU supports %s and make sure its drivers are up-to-date.",
+ driver_friendly_name,
+ driver_friendly_name));
+ }
}
// Pick the main queue family. It is worth noting we explicitly do not request the transfer bit, as apparently the specification defines