[Bf-blender-cvs] [328a911379d] master: Cycles: Distinguish Apple GPUs by core count

Michael Jones noreply at git.blender.org
Wed Jun 22 23:32:57 CEST 2022


Commit: 328a911379d445c9acef1b67f429e8c3454dda6c
Author: Michael Jones
Date:   Wed Jun 22 22:32:34 2022 +0100
Branches: master
https://developer.blender.org/rB328a911379d445c9acef1b67f429e8c3454dda6c

Cycles: Distinguish Apple GPUs by core count

This patch suffixes Apple GPU device names with `(GPU - # cores)` so that variant GPUs with the same chipset can be distinguished. Currently benchmark scores for these M1 family GPUs are being incorrectly merged:

- M1: 7 or 8 cores
- M1 Pro: 14 or 16 cores
- M1 Max: 24 or 32 cores
- M1 Ultra: 48 or 64 cores

Reviewed By: brecht, sergey

Differential Revision: https://developer.blender.org/D15257

===================================================================

M	intern/cycles/device/metal/device.mm
M	intern/cycles/device/metal/device_impl.h
M	intern/cycles/device/metal/device_impl.mm
M	intern/cycles/device/metal/util.h
M	intern/cycles/device/metal/util.mm
M	release/scripts/addons
M	source/tools

===================================================================

diff --git a/intern/cycles/device/metal/device.mm b/intern/cycles/device/metal/device.mm
index d7f190fc01e..51e3323370a 100644
--- a/intern/cycles/device/metal/device.mm
+++ b/intern/cycles/device/metal/device.mm
@@ -34,7 +34,8 @@ void device_metal_info(vector<DeviceInfo> &devices)
   int device_index = 0;
   for (id<MTLDevice> &device : usable_devices) {
     /* Compute unique ID for persistent user preferences. */
-    string device_name = [device.name UTF8String];
+    string device_name = MetalInfo::get_device_name(device);
+
     string id = string("METAL_") + device_name;
 
     /* Hardware ID might not be unique, add device number in that case. */
@@ -48,12 +49,6 @@ void device_metal_info(vector<DeviceInfo> &devices)
     info.type = DEVICE_METAL;
     info.description = string_remove_trademark(string(device_name));
 
-    /* Ensure unique naming on Apple Silicon / SoC devices which return the same string for CPU and
-     * GPU */
-    if (info.description == system_cpu_brand_string()) {
-      info.description += " (GPU)";
-    }
-
     info.num = device_index;
     /* We don't know if it's used for display, but assume it is. */
     info.display_device = true;
@@ -69,14 +64,15 @@ string device_metal_capabilities()
 {
   string result = "";
   auto allDevices = MTLCopyAllDevices();
-  uint32_t num_devices = allDevices.count;
+  uint32_t num_devices = (uint32_t)allDevices.count;
   if (num_devices == 0) {
     return "No Metal devices found\n";
   }
   result += string_printf("Number of devices: %u\n", num_devices);
 
   for (id<MTLDevice> device in allDevices) {
-    result += string_printf("\t\tDevice: %s\n", [device.name UTF8String]);
+    string device_name = MetalInfo::get_device_name(device);
+    result += string_printf("\t\tDevice: %s\n", device_name.c_str());
   }
 
   return result;
diff --git a/intern/cycles/device/metal/device_impl.h b/intern/cycles/device/metal/device_impl.h
index 0e6817d94f8..4aea8d697a5 100644
--- a/intern/cycles/device/metal/device_impl.h
+++ b/intern/cycles/device/metal/device_impl.h
@@ -42,7 +42,6 @@ class MetalDevice : public Device {
       nil; /* encoder used for fetching device pointers from MTLAccelerationStructure */
   /*---------------------------------------------------*/
 
-  string device_name;
   MetalGPUVendor device_vendor;
 
   uint kernel_features;
diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm
index 0a89055af34..0954f586d40 100644
--- a/intern/cycles/device/metal/device_impl.mm
+++ b/intern/cycles/device/metal/device_impl.mm
@@ -9,6 +9,7 @@
 #  include "util/debug.h"
 #  include "util/md5.h"
 #  include "util/path.h"
+#  include "util/time.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -43,10 +44,9 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
   auto usable_devices = MetalInfo::get_usable_devices();
   assert(mtlDevId < usable_devices.size());
   mtlDevice = usable_devices[mtlDevId];
-  device_name = [mtlDevice.name UTF8String];
-  device_vendor = MetalInfo::get_vendor_from_device_name(device_name);
+  device_vendor = MetalInfo::get_device_vendor(mtlDevice);
   assert(device_vendor != METAL_GPU_UNKNOWN);
-  metal_printf("Creating new Cycles device for Metal: %s\n", device_name.c_str());
+  metal_printf("Creating new Cycles device for Metal: %s\n", info.description.c_str());
 
   /* determine default storage mode based on whether UMA is supported */
 
diff --git a/intern/cycles/device/metal/util.h b/intern/cycles/device/metal/util.h
index f728967835d..fd32d8a260f 100644
--- a/intern/cycles/device/metal/util.h
+++ b/intern/cycles/device/metal/util.h
@@ -25,10 +25,19 @@ enum MetalGPUVendor {
   METAL_GPU_INTEL = 3,
 };
 
+enum AppleGPUArchitecture {
+  APPLE_UNKNOWN,
+  APPLE_M1,
+  APPLE_M2,
+};
+
 /* Contains static Metal helper functions. */
 struct MetalInfo {
   static vector<id<MTLDevice>> const &get_usable_devices();
-  static MetalGPUVendor get_vendor_from_device_name(string const &device_name);
+  static int get_apple_gpu_core_count(id<MTLDevice> device);
+  static MetalGPUVendor get_device_vendor(id<MTLDevice> device);
+  static AppleGPUArchitecture get_apple_gpu_architecture(id<MTLDevice> device);
+  static string get_device_name(id<MTLDevice> device);
 };
 
 /* Pool of MTLBuffers whose lifetime is linked to a single MTLCommandBuffer */
diff --git a/intern/cycles/device/metal/util.mm b/intern/cycles/device/metal/util.mm
index a6bd593bcb6..a7a5b596b8f 100644
--- a/intern/cycles/device/metal/util.mm
+++ b/intern/cycles/device/metal/util.mm
@@ -10,21 +10,63 @@
 #  include "util/string.h"
 #  include "util/time.h"
 
+#  include <IOKit/IOKitLib.h>
 #  include <pwd.h>
 #  include <sys/shm.h>
 #  include <time.h>
 
 CCL_NAMESPACE_BEGIN
 
-MetalGPUVendor MetalInfo::get_vendor_from_device_name(string const &device_name)
+string MetalInfo::get_device_name(id<MTLDevice> device)
 {
-  if (device_name.find("Intel") != string::npos) {
+  string device_name = [device.name UTF8String];
+  if (get_device_vendor(device) == METAL_GPU_APPLE) {
+    /* Append the GPU core count so we can distinguish between GPU variants in benchmarks. */
+    int gpu_core_count = get_apple_gpu_core_count(device);
+    device_name += string_printf(gpu_core_count ? " (GPU - %d cores)" : " (GPU)", gpu_core_count);
+  }
+  return device_name;
+}
+
+int MetalInfo::get_apple_gpu_core_count(id<MTLDevice> device)
+{
+  int core_count = 0;
+  if (@available(macos 12.0, *)) {
+    io_service_t gpu_service = IOServiceGetMatchingService(
+        kIOMainPortDefault, IORegistryEntryIDMatching(device.registryID));
+    if (CFNumberRef numberRef = (CFNumberRef)IORegistryEntryCreateCFProperty(
+            gpu_service, CFSTR("gpu-core-count"), 0, 0)) {
+      if (CFGetTypeID(numberRef) == CFNumberGetTypeID()) {
+        CFNumberGetValue(numberRef, kCFNumberSInt32Type, &core_count);
+      }
+      CFRelease(numberRef);
+    }
+  }
+  return core_count;
+}
+
+AppleGPUArchitecture MetalInfo::get_apple_gpu_architecture(id<MTLDevice> device)
+{
+  const char *device_name = [device.name UTF8String];
+  if (strstr(device_name, "M1")) {
+    return APPLE_M1;
+  }
+  else if (strstr(device_name, "M2")) {
+    return APPLE_M2;
+  }
+  return APPLE_UNKNOWN;
+}
+
+MetalGPUVendor MetalInfo::get_device_vendor(id<MTLDevice> device)
+{
+  const char *device_name = [device.name UTF8String];
+  if (strstr(device_name, "Intel")) {
     return METAL_GPU_INTEL;
   }
-  else if (device_name.find("AMD") != string::npos) {
+  else if (strstr(device_name, "AMD")) {
     return METAL_GPU_AMD;
   }
-  else if (device_name.find("Apple") != string::npos) {
+  else if (strstr(device_name, "Apple")) {
     return METAL_GPU_APPLE;
   }
   return METAL_GPU_UNKNOWN;
@@ -41,9 +83,8 @@ vector<id<MTLDevice>> const &MetalInfo::get_usable_devices()
 
   metal_printf("Usable Metal devices:\n");
   for (id<MTLDevice> device in MTLCopyAllDevices()) {
-    const char *device_name = [device.name UTF8String];
-
-    MetalGPUVendor vendor = get_vendor_from_device_name(device_name);
+    string device_name = get_device_name(device);
+    MetalGPUVendor vendor = get_device_vendor(device);
     bool usable = false;
 
     if (@available(macos 12.2, *)) {
@@ -55,12 +96,12 @@ vector<id<MTLDevice>> const &MetalInfo::get_usable_devices()
     }
 
     if (usable) {
-      metal_printf("- %s\n", device_name);
+      metal_printf("- %s\n", device_name.c_str());
       [device retain];
       usable_devices.push_back(device);
     }
     else {
-      metal_printf("  (skipping \"%s\")\n", device_name);
+      metal_printf("  (skipping \"%s\")\n", device_name.c_str());
     }
   }
   if (usable_devices.empty()) {
diff --git a/release/scripts/addons b/release/scripts/addons
index bdf75cb276d..c51e0bb1793 160000
--- a/release/scripts/addons
+++ b/release/scripts/addons
@@ -1 +1 @@
-Subproject commit bdf75cb276dfd3b5266c909de4c099c00c68a659
+Subproject commit c51e0bb1793c44c7a1b7435593dd5022cf7c8eec
diff --git a/source/tools b/source/tools
index 01b4c0e4a17..ccc8fceb6bd 160000
--- a/source/tools
+++ b/source/tools
@@ -1 +1 @@
-Subproject commit 01b4c0e4a172819414229445c314be34527bf412
+Subproject commit ccc8fceb6bd83ffbf6e5207247fb8f76fc47a5b6



More information about the Bf-blender-cvs mailing list