Add `RenderingServer.get_video_adapter_type()` method

This can be used to distinguish between integrated, dedicated, virtual
and software-emulated GPUs. This in turn can be used to automatically
adjust graphics settings, or warn users about features that may run
slowly on their hardware.
This commit is contained in:
Hugo Locurcio 2021-12-10 17:01:51 +01:00
parent 85380c5207
commit b3174e7af9
No known key found for this signature in database
GPG Key ID: 39E8F8BE30B0A49C
18 changed files with 80 additions and 0 deletions

View File

@ -654,6 +654,24 @@
</constant>
<constant name="BARRIER_MASK_NO_BARRIER" value="8">
</constant>
<constant name="DEVICE_TYPE_OTHER" value="0" enum="DeviceType">
Rendering device type does not match any of the other enum values or is unknown.
</constant>
<constant name="DEVICE_TYPE_INTEGRATED_GPU" value="1" enum="DeviceType">
Rendering device is an integrated GPU, which is typically [i](but not always)[/i] slower than dedicated GPUs ([constant DEVICE_TYPE_DISCRETE_GPU]). On Android and iOS, the rendering device type is always considered to be [constant DEVICE_TYPE_INTEGRATED_GPU].
</constant>
<constant name="DEVICE_TYPE_DISCRETE_GPU" value="2" enum="DeviceType">
Rendering device is a dedicated GPU, which is typically [i](but not always)[/i] faster than integrated GPUs ([constant DEVICE_TYPE_INTEGRATED_GPU]).
</constant>
<constant name="DEVICE_TYPE_VIRTUAL_GPU" value="3" enum="DeviceType">
Rendering device is an emulated GPU in a virtual environment. This is typically much slower than the host GPU, which means the expected performance level on a dedicated GPU will be roughly equivalent to [constant DEVICE_TYPE_INTEGRATED_GPU]. Virtual machine GPU passthrough (such as VFIO) will not report the device type as [constant DEVICE_TYPE_VIRTUAL_GPU]. Instead, the host GPU's device type will be reported as if the GPU was not emulated.
</constant>
<constant name="DEVICE_TYPE_CPU" value="4" enum="DeviceType">
Rendering device is provided by software emulation (such as Lavapipe or [url=https://github.com/google/swiftshader]SwiftShader[/url]). This is the slowest kind of rendering device available; it's typically much slower than [constant DEVICE_TYPE_INTEGRATED_GPU].
</constant>
<constant name="DEVICE_TYPE_MAX" value="5" enum="DeviceType">
Represents the size of the [enum DeviceType] enum.
</constant>
<constant name="DRIVER_RESOURCE_VULKAN_DEVICE" value="0" enum="DriverResource">
</constant>
<constant name="DRIVER_RESOURCE_VULKAN_PHYSICAL_DEVICE" value="1" enum="DriverResource">

View File

@ -1232,6 +1232,13 @@
[b]Note:[/b] When running a headless or server binary, this function returns an empty string.
</description>
</method>
<method name="get_video_adapter_type" qualifiers="const">
<return type="int" enum="RenderingDevice.DeviceType" />
<description>
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].
</description>
</method>
<method name="get_video_adapter_vendor" qualifiers="const">
<return type="String" />
<description>

View File

@ -4465,6 +4465,10 @@ String RasterizerStorageGLES3::get_video_adapter_vendor() const {
return (const char *)glGetString(GL_VENDOR);
}
RenderingDevice::DeviceType RasterizerStorageGLES3::get_video_adapter_type() const {
return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER;
}
void RasterizerStorageGLES3::initialize() {
RasterizerStorageGLES3::system_fbo = 0;

View File

@ -1361,6 +1361,7 @@ public:
// int get_render_info(RS::RenderInfo p_info) override;
String get_video_adapter_name() const override;
String get_video_adapter_vendor() const override;
RenderingDevice::DeviceType get_video_adapter_type() const override;
void capture_timestamps_begin() override {}
void capture_timestamp(const String &p_name) override {}

View File

@ -8525,6 +8525,11 @@ String RenderingDeviceVulkan::get_device_vendor_name() const {
String RenderingDeviceVulkan::get_device_name() const {
return context->get_device_name();
}
RenderingDevice::DeviceType RenderingDeviceVulkan::get_device_type() const {
return context->get_device_type();
}
String RenderingDeviceVulkan::get_device_pipeline_cache_uuid() const {
return context->get_device_pipeline_cache_uuid();
}

View File

@ -1225,6 +1225,7 @@ public:
virtual String get_device_vendor_name() const;
virtual String get_device_name() const;
virtual RenderingDevice::DeviceType get_device_type() const;
virtual String get_device_pipeline_cache_uuid() const;
virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0);

View File

@ -762,6 +762,7 @@ Error VulkanContext::_create_physical_device() {
{ 0, nullptr },
};
device_name = gpu_props.deviceName;
device_type = gpu_props.deviceType;
pipeline_cache_id = String::hex_encode_buffer(gpu_props.pipelineCacheUUID, VK_UUID_SIZE);
pipeline_cache_id += "-driver-" + itos(gpu_props.driverVersion);
{
@ -2210,6 +2211,11 @@ String VulkanContext::get_device_vendor_name() const {
String VulkanContext::get_device_name() const {
return device_name;
}
RenderingDevice::DeviceType VulkanContext::get_device_type() const {
return RenderingDevice::DeviceType(device_type);
}
String VulkanContext::get_device_pipeline_cache_uuid() const {
return pipeline_cache_id;
}

View File

@ -37,6 +37,7 @@
#include "core/templates/map.h"
#include "core/templates/rid_owner.h"
#include "servers/display_server.h"
#include "servers/rendering/rendering_device.h"
#ifdef USE_VOLK
#include <volk.h>
@ -101,6 +102,7 @@ private:
String device_vendor;
String device_name;
VkPhysicalDeviceType device_type;
String pipeline_cache_id;
uint32_t device_api_version = 0;
@ -290,6 +292,7 @@ public:
String get_device_vendor_name() const;
String get_device_name() const;
RenderingDevice::DeviceType get_device_type() const;
String get_device_pipeline_cache_uuid() const;
void set_vsync_mode(DisplayServer::WindowID p_window, DisplayServer::VSyncMode p_mode);

View File

@ -700,6 +700,7 @@ public:
String get_video_adapter_name() const override { return String(); }
String get_video_adapter_vendor() const override { return String(); }
RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
static RendererStorage *base_singleton;

View File

@ -9529,10 +9529,15 @@ uint64_t RendererStorageRD::get_rendering_info(RS::RenderingInfo p_info) {
String RendererStorageRD::get_video_adapter_name() const {
return RenderingDevice::get_singleton()->get_device_name();
}
String RendererStorageRD::get_video_adapter_vendor() const {
return RenderingDevice::get_singleton()->get_device_vendor_name();
}
RenderingDevice::DeviceType RendererStorageRD::get_video_adapter_type() const {
return RenderingDevice::get_singleton()->get_device_type();
}
RendererStorageRD *RendererStorageRD::base_singleton = nullptr;
RendererStorageRD::RendererStorageRD() {

View File

@ -2393,6 +2393,7 @@ public:
String get_video_adapter_name() const;
String get_video_adapter_vendor() const;
RenderingDevice::DeviceType get_video_adapter_type() const;
virtual void capture_timestamps_begin();
virtual void capture_timestamp(const String &p_name);

View File

@ -620,6 +620,7 @@ public:
virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) = 0;
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
static RendererStorage *base_singleton;

View File

@ -490,6 +490,13 @@ void RenderingDevice::_bind_methods() {
BIND_CONSTANT(BARRIER_MASK_ALL);
BIND_CONSTANT(BARRIER_MASK_NO_BARRIER);
BIND_ENUM_CONSTANT(DEVICE_TYPE_OTHER);
BIND_ENUM_CONSTANT(DEVICE_TYPE_INTEGRATED_GPU);
BIND_ENUM_CONSTANT(DEVICE_TYPE_DISCRETE_GPU);
BIND_ENUM_CONSTANT(DEVICE_TYPE_VIRTUAL_GPU);
BIND_ENUM_CONSTANT(DEVICE_TYPE_CPU);
BIND_ENUM_CONSTANT(DEVICE_TYPE_MAX);
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_DEVICE);
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_PHYSICAL_DEVICE);
BIND_ENUM_CONSTANT(DRIVER_RESOURCE_VULKAN_INSTANCE);

View File

@ -60,6 +60,17 @@ public:
DEVICE_DIRECTX
};
// This enum matches VkPhysicalDeviceType (except for `DEVICE_TYPE_MAX`).
// Unlike VkPhysicalDeviceType, DeviceType is exposed to the scripting API.
enum DeviceType {
DEVICE_TYPE_OTHER,
DEVICE_TYPE_INTEGRATED_GPU,
DEVICE_TYPE_DISCRETE_GPU,
DEVICE_TYPE_VIRTUAL_GPU,
DEVICE_TYPE_CPU,
DEVICE_TYPE_MAX,
};
enum DriverResource {
DRIVER_RESOURCE_VULKAN_DEVICE = 0,
DRIVER_RESOURCE_VULKAN_PHYSICAL_DEVICE,
@ -1199,6 +1210,7 @@ public:
virtual String get_device_vendor_name() const = 0;
virtual String get_device_name() const = 0;
virtual RenderingDevice::DeviceType get_device_type() const = 0;
virtual String get_device_pipeline_cache_uuid() const = 0;
virtual uint64_t get_driver_resource(DriverResource p_resource, RID p_rid = RID(), uint64_t p_index = 0) = 0;
@ -1237,6 +1249,7 @@ protected:
Vector<int64_t> _draw_list_switch_to_next_pass_split(uint32_t p_splits);
};
VARIANT_ENUM_CAST(RenderingDevice::DeviceType)
VARIANT_ENUM_CAST(RenderingDevice::DriverResource)
VARIANT_ENUM_CAST(RenderingDevice::ShaderStage)
VARIANT_ENUM_CAST(RenderingDevice::ShaderLanguage)

View File

@ -255,6 +255,10 @@ String RenderingServerDefault::get_video_adapter_vendor() const {
return RSG::storage->get_video_adapter_vendor();
}
RenderingDevice::DeviceType RenderingServerDefault::get_video_adapter_type() const {
return RSG::storage->get_video_adapter_type();
}
void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) {
RSG::storage->capturing_timestamps = p_enable;
}

View File

@ -891,6 +891,7 @@ public:
virtual uint64_t get_rendering_info(RenderingInfo p_info) override;
virtual String get_video_adapter_name() const override;
virtual String get_video_adapter_vendor() const override;
virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
virtual void set_frame_profiling_enabled(bool p_enable) override;
virtual Vector<FrameProfileArea> get_frame_profile() override;

View File

@ -2711,6 +2711,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_rendering_info", "info"), &RenderingServer::get_rendering_info);
ClassDB::bind_method(D_METHOD("get_video_adapter_name"), &RenderingServer::get_video_adapter_name);
ClassDB::bind_method(D_METHOD("get_video_adapter_vendor"), &RenderingServer::get_video_adapter_vendor);
ClassDB::bind_method(D_METHOD("get_video_adapter_type"), &RenderingServer::get_video_adapter_type);
ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &RenderingServer::make_sphere_mesh);
ClassDB::bind_method(D_METHOD("get_test_cube"), &RenderingServer::get_test_cube);

View File

@ -1473,6 +1473,7 @@ public:
virtual uint64_t get_rendering_info(RenderingInfo p_info) = 0;
virtual String get_video_adapter_name() const = 0;
virtual String get_video_adapter_vendor() const = 0;
virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
struct FrameProfileArea {
String name;