Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorMichael Jones <michael_p_jones@apple.com>2022-02-11 21:19:51 +0300
committerBrecht Van Lommel <brecht@blender.org>2022-02-11 21:22:16 +0300
commit40fce61a6abe79508022d3e0cd3a29e187f18e74 (patch)
treeb293810b62aac2b590f1725a86d9399e999bd9f3 /intern
parent8fb2926a536f7f38755612f97c4bb9e1de8d0a8d (diff)
Cycles: enable Metal on AMD GPUs, set macOS minimum versions
* Apple Silicon support enabled on macOS 12.2+ * AMD support enabled on macOS 12.3+ This patch also fixes a device enumeration crash on certain AMD configs which was caused by over-release of MTLDevice objects. Differential Revision: https://developer.blender.org/D14090
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/device/metal/device.mm27
-rw-r--r--intern/cycles/device/metal/device_impl.mm23
-rw-r--r--intern/cycles/device/metal/util.h25
-rw-r--r--intern/cycles/device/metal/util.mm90
4 files changed, 43 insertions, 122 deletions
diff --git a/intern/cycles/device/metal/device.mm b/intern/cycles/device/metal/device.mm
index bc893adea17..ef592438980 100644
--- a/intern/cycles/device/metal/device.mm
+++ b/intern/cycles/device/metal/device.mm
@@ -39,33 +39,20 @@ bool device_metal_init()
return true;
}
-static int device_metal_get_num_devices_safe(uint32_t *num_devices)
-{
- *num_devices = MTLCopyAllDevices().count;
- return 0;
-}
-
void device_metal_info(vector<DeviceInfo> &devices)
{
- uint32_t num_devices = 0;
- device_metal_get_num_devices_safe(&num_devices);
- if (num_devices == 0) {
- return;
- }
-
- vector<MetalPlatformDevice> usable_devices;
- MetalInfo::get_usable_devices(&usable_devices);
+ auto usable_devices = MetalInfo::get_usable_devices();
/* Devices are numbered consecutively across platforms. */
set<string> unique_ids;
int device_index = 0;
- for (MetalPlatformDevice &device : usable_devices) {
+ for (id<MTLDevice> &device : usable_devices) {
/* Compute unique ID for persistent user preferences. */
- const string &device_name = device.device_name;
+ string device_name = [device.name UTF8String];
string id = string("METAL_") + device_name;
/* Hardware ID might not be unique, add device number in that case. */
if (unique_ids.find(id) != unique_ids.end()) {
- id += string_printf("_ID_%d", num_devices);
+ id += string_printf("_ID_%d", device_index);
}
unique_ids.insert(id);
@@ -94,15 +81,13 @@ void device_metal_info(vector<DeviceInfo> &devices)
string device_metal_capabilities()
{
string result = "";
- string error_msg = "";
- uint32_t num_devices = 0;
- assert(device_metal_get_num_devices_safe(&num_devices));
+ auto allDevices = MTLCopyAllDevices();
+ uint32_t num_devices = allDevices.count;
if (num_devices == 0) {
return "No Metal devices found\n";
}
result += string_printf("Number of devices: %u\n", num_devices);
- NSArray<id<MTLDevice>> *allDevices = MTLCopyAllDevices();
for (id<MTLDevice> device in allDevices) {
result += string_printf("\t\tDevice: %s\n", [device.name UTF8String]);
}
diff --git a/intern/cycles/device/metal/device_impl.mm b/intern/cycles/device/metal/device_impl.mm
index cdaafc60ab0..8ced0210e30 100644
--- a/intern/cycles/device/metal/device_impl.mm
+++ b/intern/cycles/device/metal/device_impl.mm
@@ -53,16 +53,10 @@ MetalDevice::MetalDevice(const DeviceInfo &info, Stats &stats, Profiler &profile
mtlDevId = info.num;
/* select chosen device */
- vector<MetalPlatformDevice> usable_devices;
- MetalInfo::get_usable_devices(&usable_devices);
- if (usable_devices.size() == 0) {
- set_error("Metal: no devices found.");
- return;
- }
+ auto usable_devices = MetalInfo::get_usable_devices();
assert(mtlDevId < usable_devices.size());
- MetalPlatformDevice &platform_device = usable_devices[mtlDevId];
- mtlDevice = platform_device.device_id;
- device_name = platform_device.device_name;
+ mtlDevice = usable_devices[mtlDevId];
+ device_name = [mtlDevice.name UTF8String];
device_vendor = MetalInfo::get_vendor_from_device_name(device_name);
assert(device_vendor != METAL_GPU_UNKNOWN);
metal_printf("Creating new Cycles device for Metal: %s\n", device_name.c_str());
@@ -458,7 +452,8 @@ MetalDevice::MetalMem *MetalDevice::generic_alloc(device_memory &mem)
id<MTLBuffer> metal_buffer = nil;
MTLResourceOptions options = default_storage_mode;
- /* Workaround for "bake" unit tests which fail if RenderBuffers is allocated with MTLResourceStorageModeShared. */
+ /* Workaround for "bake" unit tests which fail if RenderBuffers is allocated with
+ * MTLResourceStorageModeShared. */
if (strstr(mem.name, "RenderBuffers")) {
options = MTLResourceStorageModeManaged;
}
@@ -769,9 +764,11 @@ void MetalDevice::tex_alloc(device_texture &mem)
/* Check that dimensions fit within maximum allowable size.
See https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
*/
- if (mem.data_width > 16384 ||
- mem.data_height > 16384) {
- set_error(string_printf("Texture exceeds maximum allowed size of 16384 x 16384 (requested: %zu x %zu)", mem.data_width, mem.data_height));
+ if (mem.data_width > 16384 || mem.data_height > 16384) {
+ set_error(string_printf(
+ "Texture exceeds maximum allowed size of 16384 x 16384 (requested: %zu x %zu)",
+ mem.data_width,
+ mem.data_height));
return;
}
diff --git a/intern/cycles/device/metal/util.h b/intern/cycles/device/metal/util.h
index dbeb3a5d064..084ba626370 100644
--- a/intern/cycles/device/metal/util.h
+++ b/intern/cycles/device/metal/util.h
@@ -36,33 +36,10 @@ enum MetalGPUVendor {
METAL_GPU_INTEL = 3,
};
-/* Retains a named MTLDevice for device enumeration. */
-struct MetalPlatformDevice {
- MetalPlatformDevice(id<MTLDevice> device, const string &device_name)
- : device_id(device), device_name(device_name)
- {
- [device_id retain];
- }
- ~MetalPlatformDevice()
- {
- [device_id release];
- }
- id<MTLDevice> device_id;
- string device_name;
-};
-
/* Contains static Metal helper functions. */
struct MetalInfo {
- static bool device_version_check(id<MTLDevice> device);
- static void get_usable_devices(vector<MetalPlatformDevice> *usable_devices);
+ static vector<id<MTLDevice>> const &get_usable_devices();
static MetalGPUVendor get_vendor_from_device_name(string const &device_name);
-
- /* Platform information. */
- static bool get_num_devices(uint32_t *num_platforms);
- static uint32_t get_num_devices();
-
- static bool get_device_name(id<MTLDevice> device_id, string *device_name);
- static string get_device_name(id<MTLDevice> device_id);
};
/* 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 763a37cb503..f0eb22e57f3 100644
--- a/intern/cycles/device/metal/util.mm
+++ b/intern/cycles/device/metal/util.mm
@@ -43,83 +43,45 @@ MetalGPUVendor MetalInfo::get_vendor_from_device_name(string const &device_name)
return METAL_GPU_UNKNOWN;
}
-bool MetalInfo::device_version_check(id<MTLDevice> device)
+vector<id<MTLDevice>> const &MetalInfo::get_usable_devices()
{
- /* Metal Cycles doesn't work correctly on macOS versions older than 12.0 */
- if (@available(macos 12.0, *)) {
- MetalGPUVendor vendor = get_vendor_from_device_name([[device name] UTF8String]);
+ static vector<id<MTLDevice>> usable_devices;
+ static bool already_enumerated = false;
- /* Metal Cycles works on Apple Silicon GPUs at present */
- return (vendor == METAL_GPU_APPLE);
+ if (already_enumerated) {
+ return usable_devices;
}
- return false;
-}
+ metal_printf("Usable Metal devices:\n");
+ for (id<MTLDevice> device in MTLCopyAllDevices()) {
+ const char *device_name = [device.name UTF8String];
-void MetalInfo::get_usable_devices(vector<MetalPlatformDevice> *usable_devices)
-{
- static bool first_time = true;
-# define FIRST_VLOG(severity) \
- if (first_time) \
- VLOG(severity)
-
- usable_devices->clear();
-
- NSArray<id<MTLDevice>> *allDevices = MTLCopyAllDevices();
- for (id<MTLDevice> device in allDevices) {
- string device_name;
- if (!get_device_name(device, &device_name)) {
- FIRST_VLOG(2) << "Failed to get device name, ignoring.";
- continue;
+ MetalGPUVendor vendor = get_vendor_from_device_name(device_name);
+ bool usable = false;
+
+ if (@available(macos 12.2, *)) {
+ usable |= (vendor == METAL_GPU_APPLE);
}
- static const char *forceIntelStr = getenv("CYCLES_METAL_FORCE_INTEL");
- bool forceIntel = forceIntelStr ? (atoi(forceIntelStr) != 0) : false;
- if (forceIntel && device_name.find("Intel") == string::npos) {
- FIRST_VLOG(2) << "CYCLES_METAL_FORCE_INTEL causing non-Intel device " << device_name
- << " to be ignored.";
- continue;
+ if (@available(macos 12.3, *)) {
+ usable |= (vendor == METAL_GPU_AMD);
}
- if (!device_version_check(device)) {
- FIRST_VLOG(2) << "Ignoring device " << device_name << " due to too old compiler version.";
- continue;
+ if (usable) {
+ metal_printf("- %s\n", device_name);
+ [device retain];
+ usable_devices.push_back(device);
+ }
+ else {
+ metal_printf(" (skipping \"%s\")\n", device_name);
}
- FIRST_VLOG(2) << "Adding new device " << device_name << ".";
- string hardware_id;
- usable_devices->push_back(MetalPlatformDevice(device, device_name));
}
- first_time = false;
-}
-
-bool MetalInfo::get_num_devices(uint32_t *num_devices)
-{
- *num_devices = MTLCopyAllDevices().count;
- return true;
-}
-
-uint32_t MetalInfo::get_num_devices()
-{
- uint32_t num_devices;
- if (!get_num_devices(&num_devices)) {
- return 0;
+ if (usable_devices.empty()) {
+ metal_printf(" No usable Metal devices found\n");
}
- return num_devices;
-}
-
-bool MetalInfo::get_device_name(id<MTLDevice> device, string *platform_name)
-{
- *platform_name = [device.name UTF8String];
- return true;
-}
+ already_enumerated = true;
-string MetalInfo::get_device_name(id<MTLDevice> device)
-{
- string platform_name;
- if (!get_device_name(device, &platform_name)) {
- return "";
- }
- return platform_name;
+ return usable_devices;
}
id<MTLBuffer> MetalBufferPool::get_buffer(id<MTLDevice> device,