Merge branch 'blender-v3.1-release'
This commit is contained in:
commit
ad53cb0b9d
|
@ -26,33 +26,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);
|
||||
|
||||
|
@ -81,15 +68,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]);
|
||||
}
|
||||
|
|
|
@ -40,16 +40,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());
|
||||
|
|
|
@ -23,33 +23,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 */
|
||||
|
|
|
@ -30,83 +30,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)
|
||||
MetalGPUVendor vendor = get_vendor_from_device_name(device_name);
|
||||
bool usable = false;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
already_enumerated = true;
|
||||
|
||||
bool MetalInfo::get_device_name(id<MTLDevice> device, string *platform_name)
|
||||
{
|
||||
*platform_name = [device.name UTF8String];
|
||||
return 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,
|
||||
|
|
|
@ -578,14 +578,6 @@ class USERPREF_PT_system_sound(SystemPanel, CenterAlignMixIn, Panel):
|
|||
class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel):
|
||||
bl_label = "Cycles Render Devices"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, _context):
|
||||
# No GPU rendering on macOS x86_64 currently.
|
||||
import platform
|
||||
import sys
|
||||
return bpy.app.build_options.cycles and \
|
||||
(sys.platform != "darwin" or platform.machine() == "arm64")
|
||||
|
||||
def draw_centered(self, context, layout):
|
||||
prefs = context.preferences
|
||||
|
||||
|
|
Loading…
Reference in New Issue