|
30 | 30 |
|
31 | 31 | #include "rendering_context_driver.h" |
32 | 32 |
|
| 33 | +#include "core/config/project_settings.h" |
| 34 | + |
33 | 35 | RenderingContextDriver::~RenderingContextDriver() { |
34 | 36 | } |
35 | 37 |
|
@@ -158,6 +160,58 @@ void RenderingContextDriver::window_destroy(DisplayServerEnums::WindowID p_windo |
158 | 160 | window_surface_map.erase(p_window); |
159 | 161 | } |
160 | 162 |
|
| 163 | +int32_t RenderingContextDriver::pick_device(SurfaceID p_surface, bool p_print_verbose) { |
| 164 | + if (p_print_verbose) { |
| 165 | + print_verbose("Devices:"); |
| 166 | + } |
| 167 | + |
| 168 | + int32_t device_index = Engine::get_singleton()->get_gpu_index(); |
| 169 | + const uint32_t device_count = device_get_count(); |
| 170 | + const bool device_index_out_of_range = (device_index >= int32_t(device_count)); |
| 171 | + if (device_index_out_of_range) { |
| 172 | + WARN_PRINT(vformat("The specified GPU index %d is out of range on this system (0-%d). Falling back to automatic device selection.", device_index, device_count - 1)); |
| 173 | + } |
| 174 | + |
| 175 | + const bool detect_device = (device_index < 0) || device_index_out_of_range; |
| 176 | + uint32_t device_type_score = 0; |
| 177 | + for (uint32_t i = 0; i < device_count; i++) { |
| 178 | + RenderingContextDriver::Device device_option = device_get(i); |
| 179 | + String name = device_option.name; |
| 180 | + String vendor = get_device_vendor_name(device_option); |
| 181 | + String type = get_device_type_name(device_option); |
| 182 | + bool present_supported = p_surface != 0 ? device_supports_present(i, p_surface) : false; |
| 183 | + if (p_print_verbose) { |
| 184 | + print_verbose(" #" + itos(i) + ": " + vendor + " " + name + " - " + (present_supported ? "Supported" : "Unsupported") + ", " + type); |
| 185 | + } |
| 186 | + |
| 187 | + if (detect_device && (present_supported || p_surface == 0)) { |
| 188 | + // If a window was specified, present must be supported by the device to be available as an option. |
| 189 | + // Assign a score for each type of device and prefer the device with the higher score. |
| 190 | + uint32_t option_score = get_device_type_score(device_option); |
| 191 | + if (option_score > device_type_score) { |
| 192 | + device_index = i; |
| 193 | + device_type_score = option_score; |
| 194 | + } |
| 195 | + } |
| 196 | + } |
| 197 | + |
| 198 | + return device_index; |
| 199 | +} |
| 200 | + |
| 201 | +Error RenderingContextDriver::_check_excluded_devices() { |
| 202 | + // Check if the picked device from the context is excluded from using RenderingDevice. The names must be an exact string match. |
| 203 | + String device_list_string = GLOBAL_GET("rendering/rendering_device/excluded_device_list"); |
| 204 | + PackedStringArray device_list = device_list_string.split(","); |
| 205 | + int32_t device_index = pick_device(0, false); |
| 206 | + if (device_index >= 0 && device_index < (int32_t)(device_get_count())) { |
| 207 | + const RenderingContextDriver::Device &device = device_get(device_index); |
| 208 | + return device_list.has(device.name) ? ERR_CANT_CREATE : OK; |
| 209 | + } else { |
| 210 | + // No valid device was found, so just fail on this step instead. |
| 211 | + return ERR_CANT_CREATE; |
| 212 | + } |
| 213 | +} |
| 214 | + |
161 | 215 | String RenderingContextDriver::get_driver_and_device_memory_report() const { |
162 | 216 | String report; |
163 | 217 |
|
@@ -242,3 +296,59 @@ uint64_t RenderingContextDriver::get_device_memory_by_object_type(uint32_t) cons |
242 | 296 | uint64_t RenderingContextDriver::get_device_allocs_by_object_type(uint32_t) const { |
243 | 297 | return 0; |
244 | 298 | } |
| 299 | + |
| 300 | +String RenderingContextDriver::get_device_vendor_name(const Device &p_device) { |
| 301 | + switch (p_device.vendor) { |
| 302 | + case RenderingContextDriver::Vendor::VENDOR_AMD: |
| 303 | + return "AMD"; |
| 304 | + case RenderingContextDriver::Vendor::VENDOR_IMGTEC: |
| 305 | + return "ImgTec"; |
| 306 | + case RenderingContextDriver::Vendor::VENDOR_APPLE: |
| 307 | + return "Apple"; |
| 308 | + case RenderingContextDriver::Vendor::VENDOR_NVIDIA: |
| 309 | + return "NVIDIA"; |
| 310 | + case RenderingContextDriver::Vendor::VENDOR_ARM: |
| 311 | + return "ARM"; |
| 312 | + case RenderingContextDriver::Vendor::VENDOR_MICROSOFT: |
| 313 | + return "Microsoft"; |
| 314 | + case RenderingContextDriver::Vendor::VENDOR_QUALCOMM: |
| 315 | + return "Qualcomm"; |
| 316 | + case RenderingContextDriver::Vendor::VENDOR_INTEL: |
| 317 | + return "Intel"; |
| 318 | + default: |
| 319 | + return "Unknown"; |
| 320 | + } |
| 321 | +} |
| 322 | + |
| 323 | +String RenderingContextDriver::get_device_type_name(const Device &p_device) { |
| 324 | + switch (p_device.type) { |
| 325 | + case RenderingContextDriver::DEVICE_TYPE_INTEGRATED_GPU: |
| 326 | + return "Integrated"; |
| 327 | + case RenderingContextDriver::DEVICE_TYPE_DISCRETE_GPU: |
| 328 | + return "Discrete"; |
| 329 | + case RenderingContextDriver::DEVICE_TYPE_VIRTUAL_GPU: |
| 330 | + return "Virtual"; |
| 331 | + case RenderingContextDriver::DEVICE_TYPE_CPU: |
| 332 | + return "CPU"; |
| 333 | + case RenderingContextDriver::DEVICE_TYPE_OTHER: |
| 334 | + default: |
| 335 | + return "Other"; |
| 336 | + } |
| 337 | +} |
| 338 | + |
| 339 | +uint32_t RenderingContextDriver::get_device_type_score(const Device &p_device) { |
| 340 | + static const bool prefer_integrated = OS::get_singleton()->get_user_prefers_integrated_gpu(); |
| 341 | + switch (p_device.type) { |
| 342 | + case RenderingContextDriver::DEVICE_TYPE_INTEGRATED_GPU: |
| 343 | + return prefer_integrated ? 5 : 4; |
| 344 | + case RenderingContextDriver::DEVICE_TYPE_DISCRETE_GPU: |
| 345 | + return prefer_integrated ? 4 : 5; |
| 346 | + case RenderingContextDriver::DEVICE_TYPE_VIRTUAL_GPU: |
| 347 | + return 3; |
| 348 | + case RenderingContextDriver::DEVICE_TYPE_CPU: |
| 349 | + return 2; |
| 350 | + case RenderingContextDriver::DEVICE_TYPE_OTHER: |
| 351 | + default: |
| 352 | + return 1; |
| 353 | + } |
| 354 | +} |
0 commit comments